📄 net_ipv4_tftp.c
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * net_ipv4_tftp.c * * TFTP client * Based on RFC 1350 "The TFTP Protocol (Revision 2)" * Based on RFC 1782 "TFTP Option Extension" * * Written by Ho Lee 11/20/2002 */#include "config.h"#include "util.h"#include "vsprintf.h"#include "uart.h"#include "timer.h"#include "net.h"#include "net_ipv4.h"static const char *blkstr = "blksize";/* TFTP file transfer example (from RFC 1782) Read Request client server ------------------------------------------------------- |1|foofile|0|octet|0|blksize|0|1432|0| --> RRQ <-- |6|blksize|0|1432|0| OACK |4|0| --> ACK <-- |3|1| 1432 octets of data | DATA |4|1| --> ACK <-- |3|2| 1432 octets of data | DATA |4|2| --> ACK <-- |3|3|<1432 octets of data | DATA |4|3| --> ACK*/int tftp_parsepacket(struct sk_buff *skb){ skb->tftp = (struct tftphdr *) ((char *) skb->udp + sizeof(struct udphdr)); skb->tftp->opcode = ntohs(skb->tftp->opcode); switch (skb->tftp->opcode) { case TFTPOP_DATA : skb->tftp->u.data.block = ntohs(skb->tftp->u.data.block); break; case TFTPOP_ACK : skb->tftp->u.ack.block = ntohs(skb->tftp->u.ack.block); break; case TFTPOP_ERROR : skb->tftp->u.err.errcode = ntohs(skb->tftp->u.err.errcode); break; } return 0;}void tftp_dump_packet(struct sk_buff *skb, int need_parsing){ uart_printf("TFTP : \n");}int ipv4_tftp(in_addr_t ipaddr, char *filename, unsigned int addr, unsigned int *datalen){ tftpip_t packet; int len, nretry; int nloop = 0, nloop2 = 0; struct sk_buff *skb = NULL; unsigned char *dataptr; unsigned int iport = ipv4_alloc_port(); unsigned int blksize = TFTP_DEF_PACKET; unsigned int last_block = 0; dataptr = (unsigned char *) addr; *datalen = 0; // send RRQ packet.tftp.opcode = htons(TFTPOP_RRQ); len = sizeof packet.tftp.opcode; len += sprintf((char *) packet.tftp.u.rrq, "%s%coctet%c%s%c%d", filename, 0, 0, blkstr, 0, TFTP_MAX_PACKET); len += 1; for (nretry = 1; nretry <= MAX_TFTP_RETRIES; ++nretry) { uart_printf("Getting (%s)...\n", filename); udp_transmit(ipaddr, iport, IPPORT_TFTP, len, &packet, 0); if ((skb = udp_receive(ipaddr, 0, iport, TIMEOUT)) != NULL) break; if (nretry == MAX_TFTP_RETRIES) { uart_puts("Timeout. Connection failed.\n"); return TFTPRET_NETWORKERR; } else { uart_puts("Timeout. Retrying...\n"); } } while (skb) { tftp_parsepacket(skb); switch (skb->tftp->opcode) { case TFTPOP_RRQ : case TFTPOP_WRQ : case TFTPOP_ACK : // invalid op code for client // just ignore them break; case TFTPOP_DATA : // print progress if ((nloop++ & 0x3f) == 0) { if ((nloop2++ & 0x3f) == 0) { if (nloop2 == 1) uart_puts("Receiving"); else uart_puts("\n "); } uart_putc('.'); } /* Save the last block# so if ack is lost we won't copy the same packet more than once */ if (last_block != skb->tftp->u.data.block) { // Append to data buffer len = skb->udpdata_len - 4; memcpy(dataptr, skb->tftp->u.data.data, len); dataptr += len; *datalen += len; last_block = skb->tftp->u.data.block; } // reply ACK packet.tftp.opcode = htons(TFTPOP_ACK); packet.tftp.u.ack.block = htons(skb->tftp->u.data.block); udp_transmit(ipaddr, iport, skb->udp->src, 4, &packet, 0); if (len < blksize) { uart_puts("\n"); //uart_printf("Received %d (0x%x) bytes\n", *datalen, *datalen); return 0; } break; case TFTPOP_ERROR : switch (skb->tftp->u.err.errcode) { case TFTPERR_FILENOTFOUND : uart_puts("File not found\n"); return TFTPRET_FILENOTFOUND; case TFTPERR_ACCESSDENIED : uart_puts("Access denied\n"); return TFTPRET_ACCESSDENIED; default : uart_printf("TFTP error %d : %s\n", skb->tftp->u.err.errcode, skb->tftp->u.err.errmsg); return TFTPRET_OTHER; } break; case TFTPOP_OACK : // reply with ACK if (strcmp(skb->tftp->u.oack.data, blkstr) == 0) { blksize = atoi(&(skb->tftp->u.oack.data[strlen(blkstr) + 1])); uart_printf("Block size set to %d.\n", blksize); } packet.tftp.opcode = htons(TFTPOP_ACK); packet.tftp.u.ack.block = 0; udp_transmit(ipaddr, iport, skb->udp->src, 4, &packet, 0); break; } skb_free(skb); for (nretry = 1; nretry <= MAX_TFTP_RETRIES; ++nretry) { if ((skb = udp_receive(ipaddr, 0, iport, TIMEOUT)) != NULL) break; if (nretry == MAX_TFTP_RETRIES) { uart_puts("Timeout. Transfer failed.\n"); return TFTPRET_NETWORKERR; } } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -