📄 net_ipv4_tftp.c
字号:
/***************************************** Copyright (c) 2001-2002 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 2002/11/20 */#include "util.h"#include "vsprintf.h"#include "uart.h"#include "timer.h"#include "net.h"#include "net_ipv4.h"/* 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){ PrintFormat("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(); 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%cblksize%c%d", filename, 0, 0, 0, TFTP_MAX_PACKET); len += 1; for (nretry = 1; nretry <= MAX_TFTP_RETRIES; ++nretry) { PrintUart("Connecting...\r\n", -1); udp_transmit(ipaddr, iport, IPPORT_TFTP, len, &packet); if ((skb = udp_receive(ipaddr, 0, iport, TIMEOUT)) != NULL) break; if (nretry == MAX_TFTP_RETRIES) { PrintUart("Timeout. Connection failed.\r\n", -1); return TFTPRET_NETWORKERR; } else { PrintUart("Timeout. Retrying...\r\n", -1); } } 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) PrintUart("Receiving : ", -1); else PrintUart("\r\n ", -1); } PrintChar('.'); } // Append to data buffer len = skb->udpdata_len - 4; PrintFormat("Received len=%d bytes\n", len); memcpy(dataptr, skb->tftp->u.data.data, len); dataptr += len; *datalen += len; // 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); if (len < TFTP_MAX_PACKET) { PrintUart("\r\n", -1); PrintFormat("Received Total=%d (0x%x) bytes\n", *datalen, *datalen); return 0; } break; case TFTPOP_ERROR : switch (skb->tftp->u.err.errcode) { case TFTPERR_FILENOTFOUND : PrintUart("File not found\r\n", -1); return TFTPRET_FILENOTFOUND; case TFTPERR_ACCESSDENIED : PrintUart("Access denied\r\n", -1); return TFTPRET_ACCESSDENIED; default : PrintFormat("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 packet.tftp.opcode = htons(TFTPOP_ACK); packet.tftp.u.ack.block = 0; udp_transmit(ipaddr, iport, skb->udp->src, 4, &packet); 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) { PrintUart("Timeout. Transfer failed.\r\n", -1); return TFTPRET_NETWORKERR; } } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -