diff options
Diffstat (limited to 'main/common/tftp.c')
-rw-r--r-- | main/common/tftp.c | 2475 |
1 files changed, 1251 insertions, 1224 deletions
diff --git a/main/common/tftp.c b/main/common/tftp.c index f4b9130..1bc7d1b 100644 --- a/main/common/tftp.c +++ b/main/common/tftp.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -55,9 +55,9 @@ #endif -#define MODE_NULL 0 -#define MODE_NETASCII 1 -#define MODE_OCTET 2 +#define MODE_NULL 0 +#define MODE_NETASCII 1 +#define MODE_OCTET 2 void ShowTftpStats(void); static int SendTFTPData(struct ether_header *,ushort,uchar *,int); @@ -67,49 +67,49 @@ static int SendTFTPRRQ(uchar *,uchar *,char *,char *,uchar *); static int SendTFTPWRQ(uchar *,uchar *,char *,char *); -static struct elapsed_tmr tftpTmr; +static struct elapsed_tmr tftpTmr; -static ushort tftpPrevBlock; /* Keeps the value of the block number of - * the previous TFTP transaction. - */ -static int TftpWrqMode; /* Set to MODE_NETASCII, MODE_OCTET or - * MODE_NULL based on the incoming WRQ - * request - */ -static int TftpChopCount; /* Number of characters chopped from the - * incoming file because of NETASCII - * conversion (remove 0x0d). - */ +static ushort tftpPrevBlock; /* Keeps the value of the block number of + * the previous TFTP transaction. + */ +static int TftpWrqMode; /* Set to MODE_NETASCII, MODE_OCTET or + * MODE_NULL based on the incoming WRQ + * request + */ +static int TftpChopCount; /* Number of characters chopped from the + * incoming file because of NETASCII + * conversion (remove 0x0d). + */ static short TftpLastPktSize; static uchar TftpLastPkt[TFTP_PKTOVERHEAD+TFTP_DATAMAX+4]; - /* Storage of last packet sent. This is - * used if it is determined that the packet - * most recently sent must be sent again. - */ - -static long TftpRetryTimeout; /* Count used during a TFTP transfer to - * kick off a retransmission of a packet. - */ -static ushort TftpRmtPort; /* Remote port of tftp transfer */ -static uchar *TftpAddr; /* Current destination address used for tftp - * file transfer to/from local memory. - */ -static char *TftpLTMptr; /* List-to-mem pointer used when filename - * for RRQ is ".". - */ -static int TftpCount; /* Running total number of bytes transferred - * for a particular tftp transaction. - */ -static char TftpState; /* Used to keep track of the current state - * of a tftp transaction. - */ -static char TftpTurnedOff; /* If non-zero, then tftp is disabled. */ -static char TftpGetActive; /* If non-zero, then 'get' is in progress. */ -static char TftpPutActive; /* If non-zero, then 'put' is in progress. */ -static char TftpErrString[32]; /* Used to post a tftp error message. */ -static char TftpTfsFname[TFSNAMESIZE+64]; /* Store name of WRQ destination - * file (plus flags & info). - */ +/* Storage of last packet sent. This is + * used if it is determined that the packet + * most recently sent must be sent again. + */ + +static long TftpRetryTimeout; /* Count used during a TFTP transfer to + * kick off a retransmission of a packet. + */ +static ushort TftpRmtPort; /* Remote port of tftp transfer */ +static uchar *TftpAddr; /* Current destination address used for tftp + * file transfer to/from local memory. + */ +static char *TftpLTMptr; /* List-to-mem pointer used when filename + * for RRQ is ".". + */ +static int TftpCount; /* Running total number of bytes transferred + * for a particular tftp transaction. + */ +static char TftpState; /* Used to keep track of the current state + * of a tftp transaction. + */ +static char TftpTurnedOff; /* If non-zero, then tftp is disabled. */ +static char TftpGetActive; /* If non-zero, then 'get' is in progress. */ +static char TftpPutActive; /* If non-zero, then 'put' is in progress. */ +static char TftpErrString[32]; /* Used to post a tftp error message. */ +static char TftpTfsFname[TFSNAMESIZE+64]; /* Store name of WRQ destination + * file (plus flags & info). + */ #if INCLUDE_TFTPSRVR /* ls_to_mem(): * Turn the list of files into a string buffer that contains @@ -122,62 +122,69 @@ static char * ls_to_mem(void) { #if INCLUDE_TFS - int size; - TFILE *tfp; - char *base, *bp, *info, *flags, fbuf[16]; - - /* First determine how much memory will be needed to store - * the list of files... Each filename in the list will consist - * of the string formatted as "name,flags,info\n"... - */ - size = 0; - tfp = (TFILE *)0; - while((tfp = tfsnext(tfp))) { - /* Increment size to include filename, 2 commas and a newline... - */ - size += (strlen(TFS_NAME(tfp)) + 3); - - /* Determine if flags and/or info field is to be present in - * the name, and add that to the size appropriately... - */ - flags = tfsflagsbtoa(TFS_FLAGS(tfp),fbuf); - if (!fbuf[0]) - flags = 0; - if (flags) - size += strlen(flags); - if (TFS_INFO(tfp)) - size += strlen(TFS_INFO(tfp)); - } - - if (size == 0) - return(0); - - /* Allocate the space. Add one additional byte to the size to - * account for the NULL termination at the end of the string... - */ - base = bp = malloc(size+1); - if (bp == (char *)0) - return(0); - - /* Load the buffer with the list of names with their - * TFS extensions... - */ - tfp = (TFILE *)0; - while((tfp = tfsnext(tfp))) { - flags = tfsflagsbtoa(TFS_FLAGS(tfp),fbuf); - if (!flags || !fbuf[0]) - flags = ""; - if (TFS_INFO(tfp)) - info = TFS_INFO(tfp); - else - info = ""; - - bp += sprintf(bp,"%s,%s,%s\n",TFS_NAME(tfp),flags,info); - } - - return(base); + int size; + TFILE *tfp; + char *base, *bp, *info, *flags, fbuf[16]; + + /* First determine how much memory will be needed to store + * the list of files... Each filename in the list will consist + * of the string formatted as "name,flags,info\n"... + */ + size = 0; + tfp = (TFILE *)0; + while((tfp = tfsnext(tfp))) { + /* Increment size to include filename, 2 commas and a newline... + */ + size += (strlen(TFS_NAME(tfp)) + 3); + + /* Determine if flags and/or info field is to be present in + * the name, and add that to the size appropriately... + */ + flags = tfsflagsbtoa(TFS_FLAGS(tfp),fbuf); + if(!fbuf[0]) { + flags = 0; + } + if(flags) { + size += strlen(flags); + } + if(TFS_INFO(tfp)) { + size += strlen(TFS_INFO(tfp)); + } + } + + if(size == 0) { + return(0); + } + + /* Allocate the space. Add one additional byte to the size to + * account for the NULL termination at the end of the string... + */ + base = bp = malloc(size+1); + if(bp == (char *)0) { + return(0); + } + + /* Load the buffer with the list of names with their + * TFS extensions... + */ + tfp = (TFILE *)0; + while((tfp = tfsnext(tfp))) { + flags = tfsflagsbtoa(TFS_FLAGS(tfp),fbuf); + if(!flags || !fbuf[0]) { + flags = ""; + } + if(TFS_INFO(tfp)) { + info = TFS_INFO(tfp); + } else { + info = ""; + } + + bp += sprintf(bp,"%s,%s,%s\n",TFS_NAME(tfp),flags,info); + } + + return(base); #else - return(0); + return(0); #endif } #endif @@ -185,123 +192,125 @@ ls_to_mem(void) static char * tftpStringState(int state) { - switch(state) { - case TFTPOFF: - return("OFF"); - case TFTPIDLE: - return("IDLE"); - case TFTPACTIVE: - return("ACTIVE"); - case TFTPERROR: - return("ERROR"); - case TFTPHOSTERROR: - return("HOSTERROR"); - case TFTPSENTRRQ: - return("SENTRRQ"); - case TFTPSENTWRQ: - return("SENTWRQ"); - case TFTPTIMEOUT: - return("TIMEOUT"); - default: - return("???"); - } + switch(state) { + case TFTPOFF: + return("OFF"); + case TFTPIDLE: + return("IDLE"); + case TFTPACTIVE: + return("ACTIVE"); + case TFTPERROR: + return("ERROR"); + case TFTPHOSTERROR: + return("HOSTERROR"); + case TFTPSENTRRQ: + return("SENTRRQ"); + case TFTPSENTWRQ: + return("SENTWRQ"); + case TFTPTIMEOUT: + return("TIMEOUT"); + default: + return("???"); + } } static int tftpGotoState(int state) { - int ostate; + int ostate; - ostate = TftpState; - TftpState = state; + ostate = TftpState; + TftpState = state; #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_TFTP_STATE) && (state != ostate)) - printf(" TFTP State change %s -> %s\n", - tftpStringState(ostate), tftpStringState(state)); + if((EtherVerbose & SHOW_TFTP_STATE) && (state != ostate)) + printf(" TFTP State change %s -> %s\n", + tftpStringState(ostate), tftpStringState(state)); #endif - return(ostate); + return(ostate); } /* tftpGet(): - * Return size of file if successful; else 0. + * Return size of file if successful; else 0. */ int tftpGet(ulong addr,char *tftpsrvr,char *mode, char *hostfile,char *tfsfile, - char *tfsflags,char *tfsinfo) + char *tfsflags,char *tfsinfo) { - int done; - uchar binip[8], binenet[8], *enetaddr; - - setenv("TFTPGET",0); - - /* Convert IP address to binary: */ - if (IpToBin(tftpsrvr,binip) < 0) - return(0); - - /* Get the ethernet address for the IP: */ - /* Give ARP the same verbosity (if any) set up for TFTP: */ - TFTPVERBOSE(if (EtherVerbose & SHOW_TFTP_STATE) EtherVerbose |= SHOW_ARP); - enetaddr = ArpEther(binip,binenet,0); - TFTPVERBOSE(EtherVerbose &= ~SHOW_ARP); - if (!enetaddr) { - printf("ARP failed for %s\n",tftpsrvr); - return(0); - } - - printf("Retrieving %s from %s...\n",hostfile,tftpsrvr); - - /* Send the TFTP RRQ to initiate the transfer. */ - if (SendTFTPRRQ(binip,binenet,hostfile,mode,(uchar *)addr) < 0) { - printf("RRQ failed\n"); - return(0); - } - - TftpGetActive = 1; - - /* Wait for TftpState to indicate that the transaction has completed... */ - done = 0; - while(!done) { - pollethernet(); - switch(TftpState) { - case TFTPIDLE: - printf("Rcvd %d bytes",TftpCount); - done = 1; - break; - case TFTPERROR: - printf("TFTP Terminating\n"); - done = 2; - break; - case TFTPHOSTERROR: - printf("Host error: %s\n",TftpErrString); - done = 2; - break; - case TFTPTIMEOUT: - printf("Timing out (%d bytes rcvd)\n",TftpCount); - done = 2; - break; - default: - break; - } - } - TftpGetActive = 0; - - if (done == 2) { - tftpInit(); - return(0); - } - - if (tfsfile) { - int err, filesize; - - filesize = TftpCount - TftpChopCount; - printf("\nAdding %s (size=%d) to TFS...",tfsfile,filesize); - err = tfsadd(tfsfile,tfsinfo,tfsflags,(uchar *)addr,filesize); - if (err != TFS_OKAY) - printf("%s: %s\n",tfsfile,(char *)tfsctrl(TFS_ERRMSG,err,0)); - } - printf("\n"); - shell_sprintf("TFTPGET","%d",TftpCount); - return(TftpCount); + int done; + uchar binip[8], binenet[8], *enetaddr; + + setenv("TFTPGET",0); + + /* Convert IP address to binary: */ + if(IpToBin(tftpsrvr,binip) < 0) { + return(0); + } + + /* Get the ethernet address for the IP: */ + /* Give ARP the same verbosity (if any) set up for TFTP: */ + TFTPVERBOSE(if(EtherVerbose & SHOW_TFTP_STATE) EtherVerbose |= SHOW_ARP); + enetaddr = ArpEther(binip,binenet,0); + TFTPVERBOSE(EtherVerbose &= ~SHOW_ARP); + if(!enetaddr) { + printf("ARP failed for %s\n",tftpsrvr); + return(0); + } + + printf("Retrieving %s from %s...\n",hostfile,tftpsrvr); + + /* Send the TFTP RRQ to initiate the transfer. */ + if(SendTFTPRRQ(binip,binenet,hostfile,mode,(uchar *)addr) < 0) { + printf("RRQ failed\n"); + return(0); + } + + TftpGetActive = 1; + + /* Wait for TftpState to indicate that the transaction has completed... */ + done = 0; + while(!done) { + pollethernet(); + switch(TftpState) { + case TFTPIDLE: + printf("Rcvd %d bytes",TftpCount); + done = 1; + break; + case TFTPERROR: + printf("TFTP Terminating\n"); + done = 2; + break; + case TFTPHOSTERROR: + printf("Host error: %s\n",TftpErrString); + done = 2; + break; + case TFTPTIMEOUT: + printf("Timing out (%d bytes rcvd)\n",TftpCount); + done = 2; + break; + default: + break; + } + } + TftpGetActive = 0; + + if(done == 2) { + tftpInit(); + return(0); + } + + if(tfsfile) { + int err, filesize; + + filesize = TftpCount - TftpChopCount; + printf("\nAdding %s (size=%d) to TFS...",tfsfile,filesize); + err = tfsadd(tfsfile,tfsinfo,tfsflags,(uchar *)addr,filesize); + if(err != TFS_OKAY) { + printf("%s: %s\n",tfsfile,(char *)tfsctrl(TFS_ERRMSG,err,0)); + } + } + printf("\n"); + shell_sprintf("TFTPGET","%d",TftpCount); + return(TftpCount); } /* tftpPut(): @@ -318,222 +327,228 @@ tftpGet(ulong addr,char *tftpsrvr,char *mode, char *hostfile,char *tfsfile, int tftpPut(char *tftpsrvr,char *mode,char *hostfile,char *tfsfile, - char *tfsflags,char *tfsinfo) + char *tfsflags,char *tfsinfo) { #if INCLUDE_TFS - int done, tot; - TFILE *tfp; - uchar binip[8], binenet[8], *enetaddr; - - setenv("TFTPPUT",0); - - if ((tfp = tfsstat(tfsfile)) == (TFILE *)0) - return(0); - - /* For 'put', the address increments and the count decrements as - * the transfer progresses. - */ - TftpAddr = (uchar *)TFS_BASE(tfp); - TftpCount = tot = TFS_SIZE(tfp); - - /* Convert IP address to binary: */ - if (IpToBin(tftpsrvr,binip) < 0) - return(0); - - /* Get the ethernet address for the IP: - * (give ARP the same verbosity set up for TFTP) - */ - TFTPVERBOSE(if (EtherVerbose & SHOW_TFTP_STATE) EtherVerbose |= SHOW_ARP); - enetaddr = ArpEther(binip,binenet,0); - TFTPVERBOSE(EtherVerbose &= ~SHOW_ARP); - - if (!enetaddr) { - printf("ARP failed for %s\n",tftpsrvr); - return(0); - } - - printf("Sending %s to %s:%s...\n",tfsfile,tftpsrvr,hostfile); - TftpPutActive = 1; - tftpPrevBlock = 0; - - /* Send the TFTP WRQ to initiate the transfer. */ - if (SendTFTPWRQ(binip,binenet,hostfile,mode) < 0) { - printf("WRQ failed\n"); - return(0); - } - - /* Wait for TftpState to indicate that the transaction has completed... */ - done = 0; - while(!done) { - pollethernet(); - switch(TftpState) { - case TFTPIDLE: - printf("Sent %d bytes",tot); - done = 1; - break; - case TFTPERROR: - printf("TFTP Terminating\n"); - done = 2; - break; - case TFTPHOSTERROR: - printf("Host error: %s\n",TftpErrString); - done = 2; - break; - case TFTPTIMEOUT: - printf("Timing out (%d bytes sent)\n",TftpCount); - done = 2; - break; - default: - break; - } - } - TftpPutActive = 0; - - if (done == 2) { - tftpInit(); - return(0); - } - printf("\n"); - shell_sprintf("TFTPPUT","%d",tot); - return(tot); + int done, tot; + TFILE *tfp; + uchar binip[8], binenet[8], *enetaddr; + + setenv("TFTPPUT",0); + + if((tfp = tfsstat(tfsfile)) == (TFILE *)0) { + return(0); + } + + /* For 'put', the address increments and the count decrements as + * the transfer progresses. + */ + TftpAddr = (uchar *)TFS_BASE(tfp); + TftpCount = tot = TFS_SIZE(tfp); + + /* Convert IP address to binary: */ + if(IpToBin(tftpsrvr,binip) < 0) { + return(0); + } + + /* Get the ethernet address for the IP: + * (give ARP the same verbosity set up for TFTP) + */ + TFTPVERBOSE(if(EtherVerbose & SHOW_TFTP_STATE) EtherVerbose |= SHOW_ARP); + enetaddr = ArpEther(binip,binenet,0); + TFTPVERBOSE(EtherVerbose &= ~SHOW_ARP); + + if(!enetaddr) { + printf("ARP failed for %s\n",tftpsrvr); + return(0); + } + + printf("Sending %s to %s:%s...\n",tfsfile,tftpsrvr,hostfile); + TftpPutActive = 1; + tftpPrevBlock = 0; + + /* Send the TFTP WRQ to initiate the transfer. */ + if(SendTFTPWRQ(binip,binenet,hostfile,mode) < 0) { + printf("WRQ failed\n"); + return(0); + } + + /* Wait for TftpState to indicate that the transaction has completed... */ + done = 0; + while(!done) { + pollethernet(); + switch(TftpState) { + case TFTPIDLE: + printf("Sent %d bytes",tot); + done = 1; + break; + case TFTPERROR: + printf("TFTP Terminating\n"); + done = 2; + break; + case TFTPHOSTERROR: + printf("Host error: %s\n",TftpErrString); + done = 2; + break; + case TFTPTIMEOUT: + printf("Timing out (%d bytes sent)\n",TftpCount); + done = 2; + break; + default: + break; + } + } + TftpPutActive = 0; + + if(done == 2) { + tftpInit(); + return(0); + } + printf("\n"); + shell_sprintf("TFTPPUT","%d",tot); + return(tot); #else - printf("TFTP 'put' requires TFS\n"); - return(0); + printf("TFTP 'put' requires TFS\n"); + return(0); #endif } /* tftpInit(): - * Called by the ethenet initialization to initialize state variables. + * Called by the ethenet initialization to initialize state variables. */ void tftpInit() { - TftpCount = -1; - TftpRmtPort = 0; - TftpTurnedOff = 0; - tftpGotoState(TFTPIDLE); - TftpAddr = (uchar *)0; + TftpCount = -1; + TftpRmtPort = 0; + TftpTurnedOff = 0; + tftpGotoState(TFTPIDLE); + TftpAddr = (uchar *)0; } /* storePktAndSend(): - * The final stage in sending a TFTP packet... - * 1. Compute IP and UDP checksums; - * 2. Copy ethernet packet to a buffer so that it can be resent - * if necessary (by tftpStateCheck()). - * 3. Store the size of the packet; - * 4. Send the packet out the interface. - * 5. Reset the timeout count and re-transmission delay variables. + * The final stage in sending a TFTP packet... + * 1. Compute IP and UDP checksums; + * 2. Copy ethernet packet to a buffer so that it can be resent + * if necessary (by tftpStateCheck()). + * 3. Store the size of the packet; + * 4. Send the packet out the interface. + * 5. Reset the timeout count and re-transmission delay variables. */ static void storePktAndSend(struct ip *ipp, struct ether_header *epkt,int size) { - ipChksum(ipp); /* Compute csum of ip hdr */ - udpChksum(ipp); /* Compute UDP checksum */ - /* Copy packet to static buffer */ - memcpy((char *)TftpLastPkt,(char *)epkt,size); - TftpLastPktSize = size; /* Copy size to static location */ - sendBuffer(size); /* Send buffer out ethernet i*/ - - /* Re-initialize the re-transmission delay variables. - */ - TftpRetryTimeout = RetransmitDelay(DELAY_INIT_TFTP); - startElapsedTimer(&tftpTmr,TftpRetryTimeout * 1000); + ipChksum(ipp); /* Compute csum of ip hdr */ + udpChksum(ipp); /* Compute UDP checksum */ + /* Copy packet to static buffer */ + memcpy((char *)TftpLastPkt,(char *)epkt,size); + TftpLastPktSize = size; /* Copy size to static location */ + sendBuffer(size); /* Send buffer out ethernet i*/ + + /* Re-initialize the re-transmission delay variables. + */ + TftpRetryTimeout = RetransmitDelay(DELAY_INIT_TFTP); + startElapsedTimer(&tftpTmr,TftpRetryTimeout * 1000); } /* getTftpSrcPort(): - * Each time a TFTP RRQ goes out, use a new source port number. - * Cycle through a block of 256 port numbers... + * Each time a TFTP RRQ goes out, use a new source port number. + * Cycle through a block of 256 port numbers... */ static ushort getTftpSrcPort(void) { - if (TftpSrcPort < (IPPORT_TFTPSRC+256)) - TftpSrcPort++; - else - TftpSrcPort = IPPORT_TFTPSRC; - return(TftpSrcPort); + if(TftpSrcPort < (IPPORT_TFTPSRC+256)) { + TftpSrcPort++; + } else { + TftpSrcPort = IPPORT_TFTPSRC; + } + return(TftpSrcPort); } /* tftpStateCheck(): - * Called by the pollethernet function to support the ability to retry - * on a TFTP transmission that appears to have terminated prematurely - * due to a lost packet. If a packet is sent and the response is not - * received within about 1-2 seconds, the packet is re-sent. The retry - * will repeat 8 times; then give up and set the TFTP state to idle. + * Called by the pollethernet function to support the ability to retry + * on a TFTP transmission that appears to have terminated prematurely + * due to a lost packet. If a packet is sent and the response is not + * received within about 1-2 seconds, the packet is re-sent. The retry + * will repeat 8 times; then give up and set the TFTP state to idle. * - * Taken from RFC 1350 section 2 "Overview of the Protocol"... - * ... If a packet gets lost in the network, the intended recipient will - * timeout and may retransmit his last packet (which may be data or an - * acknowledgement), thus causing the sender of the lost packet to retransmit - * the lost packet. + * Taken from RFC 1350 section 2 "Overview of the Protocol"... + * ... If a packet gets lost in the network, the intended recipient will + * timeout and may retransmit his last packet (which may be data or an + * acknowledgement), thus causing the sender of the lost packet to retransmit + * the lost packet. * - * Taken from RFC 1123 section 4.2.3.2 "Timeout Algorithms"... - * ... a TFTP implementation MUST use an adaptive timeout ... + * Taken from RFC 1123 section 4.2.3.2 "Timeout Algorithms"... + * ... a TFTP implementation MUST use an adaptive timeout ... */ void tftpStateCheck(void) { - uchar *buf; - long delay; - ushort tftp_opcode; - struct ip *ihdr; - struct Udphdr *uhdr; - struct ether_header *ehdr; - - switch(TftpState) { - case TFTPIDLE: - case TFTPTIMEOUT: - case TFTPERROR: - return; - default: - break; - } - - /* If timeout occurs, re-transmit the packet... - */ - if (!msecElapsed(&tftpTmr)) - return; - - delay = RetransmitDelay(DELAY_INCREMENT); - if (delay == RETRANSMISSION_TIMEOUT) { + uchar *buf; + long delay; + ushort tftp_opcode; + struct ip *ihdr; + struct Udphdr *uhdr; + struct ether_header *ehdr; + + switch(TftpState) { + case TFTPIDLE: + case TFTPTIMEOUT: + case TFTPERROR: + return; + default: + break; + } + + /* If timeout occurs, re-transmit the packet... + */ + if(!msecElapsed(&tftpTmr)) { + return; + } + + delay = RetransmitDelay(DELAY_INCREMENT); + if(delay == RETRANSMISSION_TIMEOUT) { #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" TFTP_RETRY giving up\n"); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" TFTP_RETRY giving up\n"); + } #endif - tftpGotoState(TFTPTIMEOUT); - enableBroadcastReception(); - return; - } - - /* Get a transmit buffer and copy the packet that was last sent. - * Insert a new IP ID, recalculate the checksums and send it again... - * If the opcode of the packet to be re-transmitted is RRQ, then - * use a new port number. - */ - buf = (uchar *)getXmitBuffer(); - memcpy((char *)buf,(char *)TftpLastPkt,TftpLastPktSize); - ehdr = (struct ether_header *)buf; - ihdr = (struct ip *)(ehdr + 1); - uhdr = (struct Udphdr *)(ihdr + 1); - tftp_opcode = *(ushort *)(uhdr + 1); - ihdr->ip_id = ipId(); - if (tftp_opcode == ecs(TFTP_RRQ)) { - uhdr->uh_sport = getTftpSrcPort(); - self_ecs(uhdr->uh_sport); - } - ipChksum(ihdr); - udpChksum(ihdr); - sendBuffer(TftpLastPktSize); + tftpGotoState(TFTPTIMEOUT); + enableBroadcastReception(); + return; + } + + /* Get a transmit buffer and copy the packet that was last sent. + * Insert a new IP ID, recalculate the checksums and send it again... + * If the opcode of the packet to be re-transmitted is RRQ, then + * use a new port number. + */ + buf = (uchar *)getXmitBuffer(); + memcpy((char *)buf,(char *)TftpLastPkt,TftpLastPktSize); + ehdr = (struct ether_header *)buf; + ihdr = (struct ip *)(ehdr + 1); + uhdr = (struct Udphdr *)(ihdr + 1); + tftp_opcode = *(ushort *)(uhdr + 1); + ihdr->ip_id = ipId(); + if(tftp_opcode == ecs(TFTP_RRQ)) { + uhdr->uh_sport = getTftpSrcPort(); + self_ecs(uhdr->uh_sport); + } + ipChksum(ihdr); + udpChksum(ihdr); + sendBuffer(TftpLastPktSize); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" TFTP_RETRY (%ld secs)\n",TftpRetryTimeout); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" TFTP_RETRY (%ld secs)\n",TftpRetryTimeout); + } #endif - TftpRetryTimeout = delay; - startElapsedTimer(&tftpTmr,TftpRetryTimeout * 1000); - return; + TftpRetryTimeout = delay; + startElapsedTimer(&tftpTmr,TftpRetryTimeout * 1000); + return; } #if INCLUDE_TFTPSRVR @@ -541,45 +556,44 @@ tftpStateCheck(void) * Called when either a TFTP_RRQ or TFTP_WRQ is received indicating that * a client wants to start up a transfer. * If TftpState is IDLE, ERROR or TIMEOUT, this means it is safe to start - * up a new transfer through the server; otherwise return 0. + * up a new transfer through the server; otherwise return 0. * Also, if the server has been disabled by "tftp off" at the command line * (i.e. TftpTurnedOff == 1) then return 0. */ static int tftpStartSrvrFilter(struct ether_header *ehdr,struct Udphdr *uhdr) { - if (TftpTurnedOff) { - SendTFTPErr(ehdr,0,1,"TFTP srvr off"); - return(0); - } - - if ((TftpState == TFTPIDLE) || (TftpState == TFTPERROR) || - (TftpState == TFTPTIMEOUT)) { - TftpTfsFname[0] = 0; - TftpRmtPort = ecs(uhdr->uh_sport); - tftpGotoState(TFTPACTIVE); - return(1); - } - /* If block is zero and the incoming WRQ request is from the same - * port as was previously recorded, then assume the ACK sent back - * to the requester was not received, and this is a WRQ that is - * being re-sent. That being the case, just send the Ack back. - */ - else if ((tftpPrevBlock == 0) && (TftpRmtPort == uhdr->uh_sport)) { - SendTFTPAck(ehdr,0); - return(0); - } - else { - /* Note: the value of TftpState is not changed (final arg to - * SendTFTPErr is 0) to TFTPERROR. This is because - * we received a RRQ/WRQ request while processing a different - * TFTP transfer. We want to send the error response to the - * sender, but we don't want to stay in an error state because - * there is another valid TFTP transfer in progress. - */ - SendTFTPErr(ehdr,0,0,"TFTP srvr busy"); - return(0); - } + if(TftpTurnedOff) { + SendTFTPErr(ehdr,0,1,"TFTP srvr off"); + return(0); + } + + if((TftpState == TFTPIDLE) || (TftpState == TFTPERROR) || + (TftpState == TFTPTIMEOUT)) { + TftpTfsFname[0] = 0; + TftpRmtPort = ecs(uhdr->uh_sport); + tftpGotoState(TFTPACTIVE); + return(1); + } + /* If block is zero and the incoming WRQ request is from the same + * port as was previously recorded, then assume the ACK sent back + * to the requester was not received, and this is a WRQ that is + * being re-sent. That being the case, just send the Ack back. + */ + else if((tftpPrevBlock == 0) && (TftpRmtPort == uhdr->uh_sport)) { + SendTFTPAck(ehdr,0); + return(0); + } else { + /* Note: the value of TftpState is not changed (final arg to + * SendTFTPErr is 0) to TFTPERROR. This is because + * we received a RRQ/WRQ request while processing a different + * TFTP transfer. We want to send the error response to the + * sender, but we don't want to stay in an error state because + * there is another valid TFTP transfer in progress. + */ + SendTFTPErr(ehdr,0,0,"TFTP srvr busy"); + return(0); + } } #endif @@ -590,593 +604,598 @@ static void tftpTransferComplete(void) { #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) - printf("TFTP transfer complete.\n"); + if((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) { + printf("TFTP transfer complete.\n"); + } #endif } /* processTFTP(): - * This function handles the majority of the TFTP requests that a - * TFTP server must be able to handle. There is no real robust - * error handling, but it seems to work pretty well. - * Refer to Stevens' "UNIX Network Programming" chap 12 for details - * on TFTP. - * Note: During TFTP, promiscuity, broadcast & multicast reception - * are all turned off. This is done to speed up the file transfer. + * This function handles the majority of the TFTP requests that a + * TFTP server must be able to handle. There is no real robust + * error handling, but it seems to work pretty well. + * Refer to Stevens' "UNIX Network Programming" chap 12 for details + * on TFTP. + * Note: During TFTP, promiscuity, broadcast & multicast reception + * are all turned off. This is done to speed up the file transfer. */ int processTFTP(struct ether_header *ehdr,ushort size) { - struct ip *ihdr; - struct Udphdr *uhdr; - uchar *data; - int count; - ushort opcode, block, errcode; - char *errstring, *tftpp; + struct ip *ihdr; + struct Udphdr *uhdr; + uchar *data; + int count; + ushort opcode, block, errcode; + char *errstring, *tftpp; #if INCLUDE_TFTPSRVR - char *comma, *env, *filename, *mode; + char *comma, *env, *filename, *mode; #endif - ihdr = (struct ip *)(ehdr + 1); - uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); - tftpp = (char *)(uhdr + 1); - opcode = *(ushort *)tftpp; + ihdr = (struct ip *)(ehdr + 1); + uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); + tftpp = (char *)(uhdr + 1); + opcode = *(ushort *)tftpp; - switch (opcode) { + switch(opcode) { #if INCLUDE_TFTPSRVR - case ecs(TFTP_WRQ): - filename = tftpp+2; + case ecs(TFTP_WRQ): + filename = tftpp+2; #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) - printf("TFTP rcvd WRQ: file <%s>\n", filename); + if((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) { + printf("TFTP rcvd WRQ: file <%s>\n", filename); + } #endif - if (!tftpStartSrvrFilter(ehdr,uhdr)) - return(0); - - mode = filename; - while(*mode) - mode++; - mode++; - - /* Destination of WRQ can be an address (0x...), environment - * variable ($...) or a TFS filename... - */ - if (filename[0] == '$') { - env = getenv(&filename[1]); - if (env) { - TftpAddr = (uchar *)strtol(env,(char **)0,0); - } - else { - SendTFTPErr(ehdr,0,1,"Shell var not set"); - return(0); - } - } - else if ((filename[0] == '0') && (filename[1] == 'x')) { - TftpAddr = (uchar *)strtol(filename,(char **)0,0); - } - else { - if (MFLAGS_NOTFTPOVW() && tfsstat(filename)) { - SendTFTPErr(ehdr,6,1,"File exists"); - return(0); - } - TftpAddr = (uchar *)getAppRamStart(); - strncpy(TftpTfsFname,filename,sizeof(TftpTfsFname)-1); - TftpTfsFname[sizeof(TftpTfsFname)-1] = 0; - } - TftpCount = -1; /* not used with WRQ, so clear it */ - - /* Convert mode to lower case... */ - strtolower(mode); - if (!strcmp(mode,"netascii")) - TftpWrqMode = MODE_NETASCII; - else if (!strcmp(mode,"octet")) - TftpWrqMode = MODE_OCTET; - else { - SendTFTPErr(ehdr,0,1,"Mode '%s' not supported.",mode); - TftpWrqMode = MODE_NULL; - TftpCount = -1; - return(0); - } - block = 0; - tftpPrevBlock = block; - TftpChopCount = 0; - disableBroadcastReception(); - break; - case ecs(TFTP_RRQ): - filename = tftpp+2; + if(!tftpStartSrvrFilter(ehdr,uhdr)) { + return(0); + } + + mode = filename; + while(*mode) { + mode++; + } + mode++; + + /* Destination of WRQ can be an address (0x...), environment + * variable ($...) or a TFS filename... + */ + if(filename[0] == '$') { + env = getenv(&filename[1]); + if(env) { + TftpAddr = (uchar *)strtol(env,(char **)0,0); + } else { + SendTFTPErr(ehdr,0,1,"Shell var not set"); + return(0); + } + } else if((filename[0] == '0') && (filename[1] == 'x')) { + TftpAddr = (uchar *)strtol(filename,(char **)0,0); + } else { + if(MFLAGS_NOTFTPOVW() && tfsstat(filename)) { + SendTFTPErr(ehdr,6,1,"File exists"); + return(0); + } + TftpAddr = (uchar *)getAppRamStart(); + strncpy(TftpTfsFname,filename,sizeof(TftpTfsFname)-1); + TftpTfsFname[sizeof(TftpTfsFname)-1] = 0; + } + TftpCount = -1; /* not used with WRQ, so clear it */ + + /* Convert mode to lower case... */ + strtolower(mode); + if(!strcmp(mode,"netascii")) { + TftpWrqMode = MODE_NETASCII; + } else if(!strcmp(mode,"octet")) { + TftpWrqMode = MODE_OCTET; + } else { + SendTFTPErr(ehdr,0,1,"Mode '%s' not supported.",mode); + TftpWrqMode = MODE_NULL; + TftpCount = -1; + return(0); + } + block = 0; + tftpPrevBlock = block; + TftpChopCount = 0; + disableBroadcastReception(); + break; + case ecs(TFTP_RRQ): + filename = tftpp+2; #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) - printf("TFTP rcvd RRQ: file <%s>\n",filename); + if((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) { + printf("TFTP rcvd RRQ: file <%s>\n",filename); + } #endif - if (!tftpStartSrvrFilter(ehdr,uhdr)) - return(0); - mode = filename; - while(*mode) mode++; - mode++; - comma = strchr(filename,','); - if (!comma) { - TFILE *tfp; - - if (!strcmp(filename,".")) { - TftpLTMptr = (char *)ls_to_mem(); - TftpAddr = (uchar *)TftpLTMptr; - if (TftpLTMptr) - TftpCount = strlen((char *)TftpAddr); - else - TftpCount = 0; - } - else { - tfp = tfsstat(filename); - if (!tfp) { - SendTFTPErr(ehdr,0,1,"File (%s) not found",filename); - TftpCount = -1; - return(0); - } - TftpAddr = (uchar *)TFS_BASE(tfp); - TftpCount = TFS_SIZE(tfp); - } - } - else { - *comma++ = 0; - if ((filename[0] == '$') && (getenv(&filename[1]))) - TftpAddr = (uchar *)strtol(getenv(&filename[1]),(char **)0,0); - else - TftpAddr = (uchar *)strtol(filename,(char **)0,0); - TftpCount = strtol(comma,(char **)0,0); - } - if (strcmp(mode,"octet")) { - SendTFTPErr(ehdr,0,1,"Must use binary mode"); - TftpCount = -1; - return(0); - } - block = tftpPrevBlock = 1; - disableBroadcastReception(); - tftpGotoState(TFTPACTIVE); - SendTFTPData(ehdr,block,TftpAddr,TftpCount); - return(0); + if(!tftpStartSrvrFilter(ehdr,uhdr)) { + return(0); + } + mode = filename; + while(*mode) { + mode++; + } + mode++; + comma = strchr(filename,','); + if(!comma) { + TFILE *tfp; + + if(!strcmp(filename,".")) { + TftpLTMptr = (char *)ls_to_mem(); + TftpAddr = (uchar *)TftpLTMptr; + if(TftpLTMptr) { + TftpCount = strlen((char *)TftpAddr); + } else { + TftpCount = 0; + } + } else { + tfp = tfsstat(filename); + if(!tfp) { + SendTFTPErr(ehdr,0,1,"File (%s) not found",filename); + TftpCount = -1; + return(0); + } + TftpAddr = (uchar *)TFS_BASE(tfp); + TftpCount = TFS_SIZE(tfp); + } + } else { + *comma++ = 0; + if((filename[0] == '$') && (getenv(&filename[1]))) { + TftpAddr = (uchar *)strtol(getenv(&filename[1]),(char **)0,0); + } else { + TftpAddr = (uchar *)strtol(filename,(char **)0,0); + } + TftpCount = strtol(comma,(char **)0,0); + } + if(strcmp(mode,"octet")) { + SendTFTPErr(ehdr,0,1,"Must use binary mode"); + TftpCount = -1; + return(0); + } + block = tftpPrevBlock = 1; + disableBroadcastReception(); + tftpGotoState(TFTPACTIVE); + SendTFTPData(ehdr,block,TftpAddr,TftpCount); + return(0); #endif - case ecs(TFTP_DAT): - block = ecs(*(ushort *)(tftpp+2)); - count = ecs(uhdr->uh_ulen) - (sizeof(struct Udphdr)+4); + case ecs(TFTP_DAT): + block = ecs(*(ushort *)(tftpp+2)); + count = ecs(uhdr->uh_ulen) - (sizeof(struct Udphdr)+4); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Rcvd TFTP_DAT (%d,blk=%d)\n",count,block); - else if (EtherVerbose & SHOW_TFTP_TICKER) - ticktock(); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" Rcvd TFTP_DAT (%d,blk=%d)\n",count,block); + } else if(EtherVerbose & SHOW_TFTP_TICKER) { + ticktock(); + } #endif - if (TftpState == TFTPSENTRRQ) { /* See notes in SendTFTPRRQ() */ - tftpPrevBlock = 0; - if (block == 1) { - TftpRmtPort = ecs(uhdr->uh_sport); - tftpGotoState(TFTPACTIVE); - } - else { - SendTFTPErr(ehdr,0,1,"invalid block (%d)",block); - return(0); - } - } - /* Since we don't ACK the final TFTP_DAT from the server until after - * the file has been written, it is possible that we will receive - * a re-transmitted TFTP_DAT from the server. This is ignored by - * Sending another ACK... - */ - else if ((TftpState == TFTPIDLE) && (block == tftpPrevBlock)) { - SendTFTPAck(ehdr,block); + if(TftpState == TFTPSENTRRQ) { /* See notes in SendTFTPRRQ() */ + tftpPrevBlock = 0; + if(block == 1) { + TftpRmtPort = ecs(uhdr->uh_sport); + tftpGotoState(TFTPACTIVE); + } else { + SendTFTPErr(ehdr,0,1,"invalid block (%d)",block); + return(0); + } + } + /* Since we don't ACK the final TFTP_DAT from the server until after + * the file has been written, it is possible that we will receive + * a re-transmitted TFTP_DAT from the server. This is ignored by + * Sending another ACK... + */ + else if((TftpState == TFTPIDLE) && (block == tftpPrevBlock)) { + SendTFTPAck(ehdr,block); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" (packet ignored)\n"); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" (packet ignored)\n"); + } #endif - return(0); - } - else if (TftpState != TFTPACTIVE) { - SendTFTPErr(ehdr,0,1,"Bad state (%s) for incoming TFTP_DAT", - tftpStringState(TftpState)); - return(0); - } - - if (ecs(uhdr->uh_sport) != TftpRmtPort) { - SendTFTPErr(ehdr,0,0,"TFTP_DAT porterr: rcvd %d, expected %d", - ecs(uhdr->uh_sport),TftpRmtPort); - return(0); - } - if (block == tftpPrevBlock) { /* If block didn't increment, assume */ - SendTFTPAck(ehdr,block); /* retry. Ack it and return here. */ - return(0); /* Otherwise, if block != tftpPrevBlock+1, */ - } /* return an error, and quit now. */ - else if ((block == 0) && ((tftpPrevBlock & 0xffff) == 0xffff)) { - /* This case occurs when the block number wraps. - * It is a legal case where the downloaded data exceeds - * 32Mg (blockno > 0xffff). - */ - } - else if (block != tftpPrevBlock+1) { + return(0); + } else if(TftpState != TFTPACTIVE) { + SendTFTPErr(ehdr,0,1,"Bad state (%s) for incoming TFTP_DAT", + tftpStringState(TftpState)); + return(0); + } + + if(ecs(uhdr->uh_sport) != TftpRmtPort) { + SendTFTPErr(ehdr,0,0,"TFTP_DAT porterr: rcvd %d, expected %d", + ecs(uhdr->uh_sport),TftpRmtPort); + return(0); + } + if(block == tftpPrevBlock) { /* If block didn't increment, assume */ + SendTFTPAck(ehdr,block); /* retry. Ack it and return here. */ + return(0); /* Otherwise, if block != tftpPrevBlock+1, */ + } /* return an error, and quit now. */ + else if((block == 0) && ((tftpPrevBlock & 0xffff) == 0xffff)) { + /* This case occurs when the block number wraps. + * It is a legal case where the downloaded data exceeds + * 32Mg (blockno > 0xffff). + */ + } else if(block != tftpPrevBlock+1) { #ifdef DONT_IGNORE_OUT_OF_SEQUENCE_BLOCKS - SendTFTPErr(ehdr,0,1,"TFTP_DAT blockerr: rcvd %d, expected %d", - block,tftpPrevBlock+1); - TftpCount = -1; + SendTFTPErr(ehdr,0,1,"TFTP_DAT blockerr: rcvd %d, expected %d", + block,tftpPrevBlock+1); + TftpCount = -1; #endif - return(0); - } - TftpCount += count; - tftpPrevBlock = block; - data = (uchar *)(tftpp+4); - - /* If count is less than TFTP_DATAMAX, this must be the last - * packet of the transfer, so clean up state here. - */ - if (count < TFTP_DATAMAX) { - enableBroadcastReception(); - tftpGotoState(TFTPIDLE); - } - - /* Make sure the destination address for the data is not flash - * or BSS space... - */ - if (inUmonBssSpace((char *)TftpAddr,(char *)(TftpAddr+count))) { - SendTFTPErr(ehdr,0,1,"TFTP can't write to uMon BSS space"); - TftpCount = -1; - return(0); - } - + return(0); + } + TftpCount += count; + tftpPrevBlock = block; + data = (uchar *)(tftpp+4); + + /* If count is less than TFTP_DATAMAX, this must be the last + * packet of the transfer, so clean up state here. + */ + if(count < TFTP_DATAMAX) { + enableBroadcastReception(); + tftpGotoState(TFTPIDLE); + } + + /* Make sure the destination address for the data is not flash + * or BSS space... + */ + if(inUmonBssSpace((char *)TftpAddr,(char *)(TftpAddr+count))) { + SendTFTPErr(ehdr,0,1,"TFTP can't write to uMon BSS space"); + TftpCount = -1; + return(0); + } + #if INCLUDE_FLASH - if (InFlashSpace(TftpAddr,count)) { - SendTFTPErr(ehdr,0,1,"TFTP can't write directly to flash"); - TftpCount = -1; - return(0); - } + if(InFlashSpace(TftpAddr,count)) { + SendTFTPErr(ehdr,0,1,"TFTP can't write directly to flash"); + TftpCount = -1; + return(0); + } #endif - /* Copy data from enet buffer to TftpAddr location. - * If netascii mode is active, then this transfer is much - * slower... - * If not netascii, then we use s_memcpy() because it does - * a verification of each byte written and will abort as soon - * as a failure is detected. - */ - if (TftpWrqMode == MODE_NETASCII) { - int tmpcount = count; - - while(tmpcount) { - if (*data == 0x0d) { - data++; - tmpcount--; - TftpChopCount++; - continue; - } - - *TftpAddr = *data; - if (*TftpAddr != *data) { - SendTFTPErr(ehdr,0,1,"Write error at 0x%lx", - (ulong)TftpAddr); - TftpCount = -1; - return(0); - } - TftpAddr++; - data++; - tmpcount--; - } - } - else { - if (s_memcpy((char *)TftpAddr,(char *)data,count,0,0) != 0) { - SendTFTPErr(ehdr,0,1,"Write error at 0x%lx",(ulong)TftpAddr); - TftpCount = -1; - return(0); - } - TftpAddr += count; - } - - /* Check for transfer complete (count < TFTP_DATAMAX)... */ - if (count < TFTP_DATAMAX) { - if (TftpTfsFname[0]) { - char *fcomma, *icomma, *flags, *info; - int err; - - /* If the transfer is complete and TftpTfsFname[0] - * is non-zero, then write the data to the specified - * TFS file... Note that a comma in the filename is - * used to find the start of (if any) the TFS flags - * string. A second comma, marks the info field. - */ - info = (char *)0; - flags = (char *)0; - fcomma = strchr(TftpTfsFname,','); - if (fcomma) { - icomma = strchr(fcomma+1,','); - if (icomma) { - *icomma = 0; - info = icomma+1; - } - if (tfsctrl(TFS_FATOB,(long)(fcomma+1),0) != -1) { - *fcomma = 0; - flags = fcomma+1; - } - else { - SendTFTPErr(ehdr,0,1,"Invalid flag '%s'", - TftpTfsFname); - TftpTfsFname[0] = 0; - break; - } - } + /* Copy data from enet buffer to TftpAddr location. + * If netascii mode is active, then this transfer is much + * slower... + * If not netascii, then we use s_memcpy() because it does + * a verification of each byte written and will abort as soon + * as a failure is detected. + */ + if(TftpWrqMode == MODE_NETASCII) { + int tmpcount = count; + + while(tmpcount) { + if(*data == 0x0d) { + data++; + tmpcount--; + TftpChopCount++; + continue; + } + + *TftpAddr = *data; + if(*TftpAddr != *data) { + SendTFTPErr(ehdr,0,1,"Write error at 0x%lx", + (ulong)TftpAddr); + TftpCount = -1; + return(0); + } + TftpAddr++; + data++; + tmpcount--; + } + } else { + if(s_memcpy((char *)TftpAddr,(char *)data,count,0,0) != 0) { + SendTFTPErr(ehdr,0,1,"Write error at 0x%lx",(ulong)TftpAddr); + TftpCount = -1; + return(0); + } + TftpAddr += count; + } + + /* Check for transfer complete (count < TFTP_DATAMAX)... */ + if(count < TFTP_DATAMAX) { + if(TftpTfsFname[0]) { + char *fcomma, *icomma, *flags, *info; + int err; + + /* If the transfer is complete and TftpTfsFname[0] + * is non-zero, then write the data to the specified + * TFS file... Note that a comma in the filename is + * used to find the start of (if any) the TFS flags + * string. A second comma, marks the info field. + */ + info = (char *)0; + flags = (char *)0; + fcomma = strchr(TftpTfsFname,','); + if(fcomma) { + icomma = strchr(fcomma+1,','); + if(icomma) { + *icomma = 0; + info = icomma+1; + } + if(tfsctrl(TFS_FATOB,(long)(fcomma+1),0) != -1) { + *fcomma = 0; + flags = fcomma+1; + } else { + SendTFTPErr(ehdr,0,1,"Invalid flag '%s'", + TftpTfsFname); + TftpTfsFname[0] = 0; + break; + } + } #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) - printf("TFTP adding file: '%s' to TFS.\n",TftpTfsFname); + if((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) { + printf("TFTP adding file: '%s' to TFS.\n",TftpTfsFname); + } #endif - err = tfsadd(TftpTfsFname,info,flags, - (uchar *)getAppRamStart(),TftpCount+1-TftpChopCount); - if (err != TFS_OKAY) { - SendTFTPErr(ehdr,0,1,"TFS err: %s", - (char *)tfsctrl(TFS_ERRMSG,err,0)); - } - TftpTfsFname[0] = 0; - } - else { - int cnt; - char *addr; - - /* If the transfer is complete and no file add is to - * be done, then we flush d-cache and invalidate - * i-cache across the memory space that was just - * copied to. This is necessary in case the - * binary data that was just transferred is code. - */ - cnt = TftpCount + 1; - addr = (char *)TftpAddr - cnt; - flushDcache(addr,cnt); - invalidateIcache(addr,cnt); - } - if (!TftpGetActive) - shell_sprintf("TFTPRCV","%d",TftpCount+1); - tftpTransferComplete(); - } - break; - case ecs(TFTP_ACK): - block = ecs(*(ushort *)(tftpp+2)); + err = tfsadd(TftpTfsFname,info,flags, + (uchar *)getAppRamStart(),TftpCount+1-TftpChopCount); + if(err != TFS_OKAY) { + SendTFTPErr(ehdr,0,1,"TFS err: %s", + (char *)tfsctrl(TFS_ERRMSG,err,0)); + } + TftpTfsFname[0] = 0; + } else { + int cnt; + char *addr; + + /* If the transfer is complete and no file add is to + * be done, then we flush d-cache and invalidate + * i-cache across the memory space that was just + * copied to. This is necessary in case the + * binary data that was just transferred is code. + */ + cnt = TftpCount + 1; + addr = (char *)TftpAddr - cnt; + flushDcache(addr,cnt); + invalidateIcache(addr,cnt); + } + if(!TftpGetActive) { + shell_sprintf("TFTPRCV","%d",TftpCount+1); + } + tftpTransferComplete(); + } + break; + case ecs(TFTP_ACK): + block = ecs(*(ushort *)(tftpp+2)); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Rcvd TFTP_ACK (blk#%d)\n",block); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" Rcvd TFTP_ACK (blk#%d)\n",block); + } #endif - if ((TftpState != TFTPACTIVE) && (TftpState != TFTPSENTWRQ)) { - SendTFTPErr(ehdr,0,1,"Bad state (%s) for incoming TFTP_ACK", - tftpStringState(TftpState)); - return(0); - } - if (block == tftpPrevBlock) { - if (TftpCount > TFTP_DATAMAX) { - if (TftpState == TFTPACTIVE) { - TftpCount -= TFTP_DATAMAX; - TftpAddr += TFTP_DATAMAX; - } - SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); - if (TftpState == TFTPSENTWRQ) { - TftpCount -= TFTP_DATAMAX; - TftpAddr += TFTP_DATAMAX; - } - tftpPrevBlock++; - } - else if (TftpCount == TFTP_DATAMAX) { - if (TftpState == TFTPACTIVE) - TftpCount = 0; - SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); - if (TftpState == TFTPSENTWRQ) { - TftpCount = 0; - } - tftpPrevBlock++; - } - else { - if (TftpState == TFTPSENTWRQ) { - if (TftpCount == -1) { - TftpCount = 0; - tftpGotoState(TFTPIDLE); - enableBroadcastReception(); - tftpTransferComplete(); - } - else { - SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); - TftpAddr += TftpCount; - TftpCount = -1; - tftpPrevBlock++; - } - } - else { - TftpAddr += TftpCount; - TftpCount = 0; - tftpGotoState(TFTPIDLE); - if (TftpLTMptr) { - free(TftpLTMptr); - TftpLTMptr = (char *)0; - } - enableBroadcastReception(); - tftpTransferComplete(); - } - } - } - else if (block == tftpPrevBlock-1) { - SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); - } - else { + if((TftpState != TFTPACTIVE) && (TftpState != TFTPSENTWRQ)) { + SendTFTPErr(ehdr,0,1,"Bad state (%s) for incoming TFTP_ACK", + tftpStringState(TftpState)); + return(0); + } + if(block == tftpPrevBlock) { + if(TftpCount > TFTP_DATAMAX) { + if(TftpState == TFTPACTIVE) { + TftpCount -= TFTP_DATAMAX; + TftpAddr += TFTP_DATAMAX; + } + SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); + if(TftpState == TFTPSENTWRQ) { + TftpCount -= TFTP_DATAMAX; + TftpAddr += TFTP_DATAMAX; + } + tftpPrevBlock++; + } else if(TftpCount == TFTP_DATAMAX) { + if(TftpState == TFTPACTIVE) { + TftpCount = 0; + } + SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); + if(TftpState == TFTPSENTWRQ) { + TftpCount = 0; + } + tftpPrevBlock++; + } else { + if(TftpState == TFTPSENTWRQ) { + if(TftpCount == -1) { + TftpCount = 0; + tftpGotoState(TFTPIDLE); + enableBroadcastReception(); + tftpTransferComplete(); + } else { + SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); + TftpAddr += TftpCount; + TftpCount = -1; + tftpPrevBlock++; + } + } else { + TftpAddr += TftpCount; + TftpCount = 0; + tftpGotoState(TFTPIDLE); + if(TftpLTMptr) { + free(TftpLTMptr); + TftpLTMptr = (char *)0; + } + enableBroadcastReception(); + tftpTransferComplete(); + } + } + } else if(block == tftpPrevBlock-1) { + SendTFTPData(ehdr,block+1,TftpAddr,TftpCount); + } else { #ifdef DONT_IGNORE_OUT_OF_SEQUENCE_BLOCKS - SendTFTPErr(ehdr,0,1,"TFTP_ACK blockerr: rcvd %d, expected %d", - block,tftpPrevBlock-1); - TftpCount = -1; + SendTFTPErr(ehdr,0,1,"TFTP_ACK blockerr: rcvd %d, expected %d", + block,tftpPrevBlock-1); + TftpCount = -1; #endif - return(0); - } - return(0); - case ecs(TFTP_ERR): - errcode = ecs(*(ushort *)(tftpp+2)); - errstring = tftpp+4; + return(0); + } + return(0); + case ecs(TFTP_ERR): + errcode = ecs(*(ushort *)(tftpp+2)); + errstring = tftpp+4; #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Rcvd TFTP_ERR #%d (%s)\n",errcode,errstring); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" Rcvd TFTP_ERR #%d (%s)\n",errcode,errstring); + } #endif - TftpCount = -1; - tftpGotoState(TFTPHOSTERROR); - strncpy(TftpErrString,errstring,sizeof(TftpErrString)-1); - TftpErrString[sizeof(TftpErrString)-1] = 0; - return(0); - default: + TftpCount = -1; + tftpGotoState(TFTPHOSTERROR); + strncpy(TftpErrString,errstring,sizeof(TftpErrString)-1); + TftpErrString[sizeof(TftpErrString)-1] = 0; + return(0); + default: #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Rcvd <%04x> unknown TFTP opcode\n", opcode); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" Rcvd <%04x> unknown TFTP opcode\n", opcode); + } #endif - TftpCount = -1; - return(-1); - } - SendTFTPAck(ehdr,block); - return(0); + TftpCount = -1; + return(-1); + } + SendTFTPAck(ehdr,block); + return(0); } /* SendTFTPRRQ(): - * Pass the ether and ip address of the TFTP server, along with the - * filename and mode to start up a target-initiated TFTP download. - * The initial TftpState value is TFTPSENTRRQ, this is done so that incoming - * TFTP_DAT packets can be verified... - * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then - * the block number should be 1. If this is true, then that server's - * source port is stored away in TftpRmtPort so that all subsequent - * TFTP_DAT packets will be compared to the initial source port. If no - * match, then respond with a TFTP error or ICMP PortUnreachable message. - * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then - * if the block number is not 1, generate a error. + * Pass the ether and ip address of the TFTP server, along with the + * filename and mode to start up a target-initiated TFTP download. + * The initial TftpState value is TFTPSENTRRQ, this is done so that incoming + * TFTP_DAT packets can be verified... + * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then + * the block number should be 1. If this is true, then that server's + * source port is stored away in TftpRmtPort so that all subsequent + * TFTP_DAT packets will be compared to the initial source port. If no + * match, then respond with a TFTP error or ICMP PortUnreachable message. + * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then + * if the block number is not 1, generate a error. */ static int SendTFTPRRQ(uchar *ipadd,uchar *eadd,char *filename,char *mode,uchar *loc) { - uchar *tftpdat; - ushort ip_len; - struct ether_header *te; - struct ip *ti; - struct Udphdr *tu; - - TftpChopCount = 0; - tftpGotoState(TFTPSENTRRQ); - TftpAddr = loc; - TftpCount = 0; - - /* Retrieve an ethernet buffer from the driver and populate the - * ethernet level of packet: - */ - te = (struct ether_header *) getXmitBuffer(); - memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); - memcpy((char *)&te->ether_dhost,(char *)eadd,6); - te->ether_type = ecs(ETHERTYPE_IP); - - /* Move to the IP portion of the packet and populate it appropriately: */ - ti = (struct ip *) (te + 1); - ti->ip_vhl = IP_HDR_VER_LEN; - ti->ip_tos = 0; - ip_len = sizeof(struct ip) + - sizeof(struct Udphdr) + strlen(filename) + strlen(mode) + 4; - ti->ip_len = ecs(ip_len); - ti->ip_id = ipId(); - ti->ip_off = 0; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); - memcpy((char *)&ti->ip_dst.s_addr,(char *)ipadd,4); - - /* Now udp... */ - tu = (struct Udphdr *) (ti + 1); - tu->uh_sport = getTftpSrcPort(); - self_ecs(tu->uh_sport); - tu->uh_dport = ecs(TftpPort); - tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); - - /* Finally, the TFTP specific stuff... */ - tftpdat = (uchar *)(tu+1); - *(ushort *)(tftpdat) = ecs(TFTP_RRQ); - strcpy((char *)tftpdat+2,(char *)filename); - strcpy((char *)tftpdat+2+strlen((char *)filename)+1,mode); - - if (!strcmp(mode,"netascii")) - TftpWrqMode = MODE_NETASCII; - else - TftpWrqMode = MODE_OCTET; - - storePktAndSend(ti, te,TFTPACKSIZE+strlen(filename)+strlen(mode)); + uchar *tftpdat; + ushort ip_len; + struct ether_header *te; + struct ip *ti; + struct Udphdr *tu; + + TftpChopCount = 0; + tftpGotoState(TFTPSENTRRQ); + TftpAddr = loc; + TftpCount = 0; + + /* Retrieve an ethernet buffer from the driver and populate the + * ethernet level of packet: + */ + te = (struct ether_header *) getXmitBuffer(); + memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); + memcpy((char *)&te->ether_dhost,(char *)eadd,6); + te->ether_type = ecs(ETHERTYPE_IP); + + /* Move to the IP portion of the packet and populate it appropriately: */ + ti = (struct ip *)(te + 1); + ti->ip_vhl = IP_HDR_VER_LEN; + ti->ip_tos = 0; + ip_len = sizeof(struct ip) + + sizeof(struct Udphdr) + strlen(filename) + strlen(mode) + 4; + ti->ip_len = ecs(ip_len); + ti->ip_id = ipId(); + ti->ip_off = 0; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); + memcpy((char *)&ti->ip_dst.s_addr,(char *)ipadd,4); + + /* Now udp... */ + tu = (struct Udphdr *)(ti + 1); + tu->uh_sport = getTftpSrcPort(); + self_ecs(tu->uh_sport); + tu->uh_dport = ecs(TftpPort); + tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); + + /* Finally, the TFTP specific stuff... */ + tftpdat = (uchar *)(tu+1); + *(ushort *)(tftpdat) = ecs(TFTP_RRQ); + strcpy((char *)tftpdat+2,(char *)filename); + strcpy((char *)tftpdat+2+strlen((char *)filename)+1,mode); + + if(!strcmp(mode,"netascii")) { + TftpWrqMode = MODE_NETASCII; + } else { + TftpWrqMode = MODE_OCTET; + } + + storePktAndSend(ti, te,TFTPACKSIZE+strlen(filename)+strlen(mode)); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf("\n Sent TFTP_RRQ (file=%s)\n",filename); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf("\n Sent TFTP_RRQ (file=%s)\n",filename); + } #endif - return(0); + return(0); } /* SendTFTPWRQ(): SSADDED - * Pass the ether and ip address of the TFTP server, along with the - * filename and mode to start up a target-initiated TFTP download. - * The initial TftpState value is TFTPSENTRRQ, this is done so that incoming - * TFTP_DAT packets can be verified... - * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then - * the block number should be 1. If this is true, then that server's - * source port is stored away in TftpRmtPort so that all subsequent - * TFTP_DAT packets will be compared to the initial source port. If no - * match, then respond with a TFTP error or ICMP PortUnreachable message. - * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then - * if the block number is not 1, generate a error. + * Pass the ether and ip address of the TFTP server, along with the + * filename and mode to start up a target-initiated TFTP download. + * The initial TftpState value is TFTPSENTRRQ, this is done so that incoming + * TFTP_DAT packets can be verified... + * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then + * the block number should be 1. If this is true, then that server's + * source port is stored away in TftpRmtPort so that all subsequent + * TFTP_DAT packets will be compared to the initial source port. If no + * match, then respond with a TFTP error or ICMP PortUnreachable message. + * - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then + * if the block number is not 1, generate a error. */ static int SendTFTPWRQ(uchar *ipadd,uchar *eadd,char *filename,char *mode) { - uchar *tftpdat; - ushort ip_len; - struct ether_header *te; - struct ip *ti; - struct Udphdr *tu; - - TftpChopCount = 0; - - /* Retrieve an ethernet buffer from the driver and populate the - * ethernet level of packet: - */ - te = (struct ether_header *) getXmitBuffer(); - memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); - memcpy((char *)&te->ether_dhost,(char *)eadd,6); - te->ether_type = ecs(ETHERTYPE_IP); - - /* Move to the IP portion of the packet and populate it appropriately: */ - ti = (struct ip *) (te + 1); - ti->ip_vhl = IP_HDR_VER_LEN; - ti->ip_tos = 0; - ip_len = sizeof(struct ip) + - sizeof(struct Udphdr) + strlen(filename) + strlen(mode) + 4; - ti->ip_len = ecs(ip_len); - ti->ip_id = ipId(); - ti->ip_off = 0; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); - memcpy((char *)&ti->ip_dst.s_addr,(char *)ipadd,4); - - /* Now udp... */ - tu = (struct Udphdr *) (ti + 1); - tu->uh_sport = getTftpSrcPort(); - self_ecs(tu->uh_sport); - tu->uh_dport = ecs(TftpPort); - tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); - - /* Finally, the TFTP specific stuff... */ - tftpdat = (uchar *)(tu+1); - *(ushort *)(tftpdat) = ecs(TFTP_WRQ); - strcpy((char *)tftpdat+2,(char *)filename); - strcpy((char *)tftpdat+2+strlen((char *)filename)+1,mode); - - if (!strcmp(mode,"netascii")) - TftpWrqMode = MODE_NETASCII; - else - TftpWrqMode = MODE_OCTET; - - storePktAndSend(ti, te,TFTPACKSIZE+strlen(filename)+strlen(mode)); + uchar *tftpdat; + ushort ip_len; + struct ether_header *te; + struct ip *ti; + struct Udphdr *tu; + + TftpChopCount = 0; + + /* Retrieve an ethernet buffer from the driver and populate the + * ethernet level of packet: + */ + te = (struct ether_header *) getXmitBuffer(); + memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); + memcpy((char *)&te->ether_dhost,(char *)eadd,6); + te->ether_type = ecs(ETHERTYPE_IP); + + /* Move to the IP portion of the packet and populate it appropriately: */ + ti = (struct ip *)(te + 1); + ti->ip_vhl = IP_HDR_VER_LEN; + ti->ip_tos = 0; + ip_len = sizeof(struct ip) + + sizeof(struct Udphdr) + strlen(filename) + strlen(mode) + 4; + ti->ip_len = ecs(ip_len); + ti->ip_id = ipId(); + ti->ip_off = 0; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); + memcpy((char *)&ti->ip_dst.s_addr,(char *)ipadd,4); + + /* Now udp... */ + tu = (struct Udphdr *)(ti + 1); + tu->uh_sport = getTftpSrcPort(); + self_ecs(tu->uh_sport); + tu->uh_dport = ecs(TftpPort); + tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); + + /* Finally, the TFTP specific stuff... */ + tftpdat = (uchar *)(tu+1); + *(ushort *)(tftpdat) = ecs(TFTP_WRQ); + strcpy((char *)tftpdat+2,(char *)filename); + strcpy((char *)tftpdat+2+strlen((char *)filename)+1,mode); + + if(!strcmp(mode,"netascii")) { + TftpWrqMode = MODE_NETASCII; + } else { + TftpWrqMode = MODE_OCTET; + } + + storePktAndSend(ti, te,TFTPACKSIZE+strlen(filename)+strlen(mode)); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf("\n Sent TFTP_WRQ (file=%s)\n",filename); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf("\n Sent TFTP_WRQ (file=%s)\n",filename); + } #endif - tftpGotoState(TFTPSENTWRQ); - return(0); + tftpGotoState(TFTPSENTWRQ); + return(0); } //ss END OF ADDED SendTRTPWRQ @@ -1186,46 +1205,47 @@ SendTFTPWRQ(uchar *ipadd,uchar *eadd,char *filename,char *mode) static int SendTFTPAck(struct ether_header *re,ushort block) { - uchar *tftpdat; - ushort ip_len; - struct ether_header *te; - struct ip *ti, *ri; - struct Udphdr *tu, *ru; - - te = EtherCopy(re); - - ti = (struct ip *) (te + 1); - ri = (struct ip *) (re + 1); - ti->ip_vhl = ri->ip_vhl; - ti->ip_tos = ri->ip_tos; - ip_len = sizeof(struct ip) + sizeof(struct Udphdr) + 4; - ti->ip_len = ecs(ip_len); - ti->ip_id = ipId(); - ti->ip_off = ri->ip_off; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - - tu = (struct Udphdr *) (ti + 1); - ru = (struct Udphdr *) (ri + 1); - tu->uh_sport = ru->uh_dport; - tu->uh_dport = ru->uh_sport; - tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); - - tftpdat = (uchar *)(tu+1); - *(ushort *)(tftpdat) = ecs(TFTP_ACK); - *(ushort *)(tftpdat+2) = ecs(block); - - storePktAndSend(ti,te,TFTPACKSIZE); + uchar *tftpdat; + ushort ip_len; + struct ether_header *te; + struct ip *ti, *ri; + struct Udphdr *tu, *ru; + + te = EtherCopy(re); + + ti = (struct ip *)(te + 1); + ri = (struct ip *)(re + 1); + ti->ip_vhl = ri->ip_vhl; + ti->ip_tos = ri->ip_tos; + ip_len = sizeof(struct ip) + sizeof(struct Udphdr) + 4; + ti->ip_len = ecs(ip_len); + ti->ip_id = ipId(); + ti->ip_off = ri->ip_off; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + + tu = (struct Udphdr *)(ti + 1); + ru = (struct Udphdr *)(ri + 1); + tu->uh_sport = ru->uh_dport; + tu->uh_dport = ru->uh_sport; + tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); + + tftpdat = (uchar *)(tu+1); + *(ushort *)(tftpdat) = ecs(TFTP_ACK); + *(ushort *)(tftpdat+2) = ecs(block); + + storePktAndSend(ti,te,TFTPACKSIZE); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Sent TFTP_ACK (blk#%d)\n",block); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" Sent TFTP_ACK (blk#%d)\n",block); + } #endif - return(0); + return(0); } /* SendTFTPErr(): @@ -1233,66 +1253,69 @@ SendTFTPAck(struct ether_header *re,ushort block) static int SendTFTPErr(struct ether_header *re,short errno,int changestate,char *fmt, ...) { - va_list argp; - short len, tftplen, hdrlen; - uchar *tftpmsg; - struct ether_header *te; - struct ip *ti, *ri; - struct Udphdr *tu, *ru; - static char errmsg[128]; - - if (changestate) - tftpGotoState(TFTPERROR); - - va_start(argp,fmt); - vsnprintf(errmsg,sizeof(errmsg),fmt,argp); - va_end(argp); + va_list argp; + short len, tftplen, hdrlen; + uchar *tftpmsg; + struct ether_header *te; + struct ip *ti, *ri; + struct Udphdr *tu, *ru; + static char errmsg[128]; + + if(changestate) { + tftpGotoState(TFTPERROR); + } + + va_start(argp,fmt); + vsnprintf(errmsg,sizeof(errmsg),fmt,argp); + va_end(argp); #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) - printf("TFTP err: %s\n",errmsg); + if((EtherVerbose & SHOW_TFTP_STATE) || (!MFLAGS_NOTFTPPRN())) { + printf("TFTP err: %s\n",errmsg); + } #endif - tftplen = strlen(errmsg) + 1 + 4; - hdrlen = sizeof(struct ip) + sizeof(struct Udphdr); - len = tftplen + hdrlen ; - - te = EtherCopy(re); - - ti = (struct ip *) (te + 1); - ri = (struct ip *) (re + 1); - ti->ip_vhl = ri->ip_vhl; - ti->ip_tos = ri->ip_tos; - ti->ip_len = ecs(len); - ti->ip_id = ipId(); - ti->ip_off = ri->ip_off; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - - tu = (struct Udphdr *) (ti + 1); - ru = (struct Udphdr *) (ri + 1); - tu->uh_sport = ru->uh_dport; - tu->uh_dport = ru->uh_sport; - tu->uh_ulen = sizeof(struct Udphdr) + tftplen; - self_ecs(tu->uh_ulen); - - tftpmsg = (uchar *)(tu+1); - *(ushort *)(tftpmsg) = ecs(TFTP_ERR); - * (ushort *)(tftpmsg+2) = ecs(errno); - strcpy((char *)tftpmsg+4,(char *)errmsg); - - storePktAndSend(ti,te,TFTPACKSIZE + strlen(errmsg) + 1); + tftplen = strlen(errmsg) + 1 + 4; + hdrlen = sizeof(struct ip) + sizeof(struct Udphdr); + len = tftplen + hdrlen ; + + te = EtherCopy(re); + + ti = (struct ip *)(te + 1); + ri = (struct ip *)(re + 1); + ti->ip_vhl = ri->ip_vhl; + ti->ip_tos = ri->ip_tos; + ti->ip_len = ecs(len); + ti->ip_id = ipId(); + ti->ip_off = ri->ip_off; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + + tu = (struct Udphdr *)(ti + 1); + ru = (struct Udphdr *)(ri + 1); + tu->uh_sport = ru->uh_dport; + tu->uh_dport = ru->uh_sport; + tu->uh_ulen = sizeof(struct Udphdr) + tftplen; + self_ecs(tu->uh_ulen); + + tftpmsg = (uchar *)(tu+1); + *(ushort *)(tftpmsg) = ecs(TFTP_ERR); + * (ushort *)(tftpmsg+2) = ecs(errno); + strcpy((char *)tftpmsg+4,(char *)errmsg); + + storePktAndSend(ti,te,TFTPACKSIZE + strlen(errmsg) + 1); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Sent TFTP Err#%d (%s) \n",errno,errmsg); + if(EtherVerbose & SHOW_TFTP_STATE) { + printf(" Sent TFTP Err#%d (%s) \n",errno,errmsg); + } #endif - return(0); + return(0); } /* SendTFTPData(): @@ -1300,57 +1323,58 @@ SendTFTPErr(struct ether_header *re,short errno,int changestate,char *fmt, ...) static int SendTFTPData(struct ether_header *re,ushort block,uchar *data,int count) { - int len, tftplen, hdrlen; - uchar *tftpmsg; - struct ether_header *te; - struct ip *ti, *ri; - struct Udphdr *tu, *ru; - - if (count > TFTP_DATAMAX) - count = TFTP_DATAMAX; - - tftplen = count + 2 + 2; /* sizeof (data + opcode + blockno) */ - hdrlen = sizeof(struct ip) + sizeof(struct Udphdr); - len = tftplen + hdrlen ; - - te = EtherCopy(re); - - ti = (struct ip *) (te + 1); - ri = (struct ip *) (re + 1); - ti->ip_vhl = ri->ip_vhl; - ti->ip_tos = ri->ip_tos; - ti->ip_len = ecs(len); - ti->ip_id = ipId(); - ti->ip_off = ri->ip_off; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - - tu = (struct Udphdr *) (ti + 1); - ru = (struct Udphdr *) (ri + 1); - tu->uh_sport = ru->uh_dport; - tu->uh_dport = ru->uh_sport; - tu->uh_ulen = sizeof(struct Udphdr) + tftplen; - self_ecs(tu->uh_ulen); - - tftpmsg = (uchar *)(tu+1); - *(ushort *)(tftpmsg) = ecs(TFTP_DAT); - *(ushort *)(tftpmsg+2) = ecs(block); - memcpy((char *)tftpmsg+4,(char *)data,count); - - len+=sizeof(struct ether_header); - - storePktAndSend(ti,te,len); + int len, tftplen, hdrlen; + uchar *tftpmsg; + struct ether_header *te; + struct ip *ti, *ri; + struct Udphdr *tu, *ru; + + if(count > TFTP_DATAMAX) { + count = TFTP_DATAMAX; + } + + tftplen = count + 2 + 2; /* sizeof (data + opcode + blockno) */ + hdrlen = sizeof(struct ip) + sizeof(struct Udphdr); + len = tftplen + hdrlen ; + + te = EtherCopy(re); + + ti = (struct ip *)(te + 1); + ri = (struct ip *)(re + 1); + ti->ip_vhl = ri->ip_vhl; + ti->ip_tos = ri->ip_tos; + ti->ip_len = ecs(len); + ti->ip_id = ipId(); + ti->ip_off = ri->ip_off; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + + tu = (struct Udphdr *)(ti + 1); + ru = (struct Udphdr *)(ri + 1); + tu->uh_sport = ru->uh_dport; + tu->uh_dport = ru->uh_sport; + tu->uh_ulen = sizeof(struct Udphdr) + tftplen; + self_ecs(tu->uh_ulen); + + tftpmsg = (uchar *)(tu+1); + *(ushort *)(tftpmsg) = ecs(TFTP_DAT); + *(ushort *)(tftpmsg+2) = ecs(block); + memcpy((char *)tftpmsg+4,(char *)data,count); + + len+=sizeof(struct ether_header); + + storePktAndSend(ti,te,len); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_TFTP_STATE) - printf(" Sent TFTP data blk#%d (%d bytes @ 0x%lx) \n", - block,count,(ulong)data); + if(EtherVerbose & SHOW_TFTP_STATE) + printf(" Sent TFTP data blk#%d (%d bytes @ 0x%lx) \n", + block,count,(ulong)data); #endif - return(0); + return(0); } #if 0 @@ -1361,182 +1385,185 @@ THIS IS NOT YET TESTED * return the requested tokens. * * The syntax of fullname can be... - * - name - * - name,flags - * - name,flags,info - * - name,,info + * - name + * - name,flags + * - name,flags,info + * - name,,info * * Return 0 if successful, -1 if failure. */ int parseLongFilename(char *fullname,char *name, char *flags, char *info) { - char *comma, *cp; - - /* Parse the fullname string looking for commas to determine what - * information is in the string. Then, based on the presence of - * the commas, populate the incoming pointers with the appropriate - * portion of the fullname string. - * If the pointer is NULL, then just skip over that portion of the - * algorithm. - */ - cp = fullname; - comma = strchr(cp,','); - if (comma) { - if (name) { - while(cp != comma) - *name++ = *cp++; - *name = 0; - } - cp++; - comma = strchr(cp,','); - if (comma) { - if (flags) { - while(cp != comma) - *flags++ = *cp++; - *flags = 0; - } - cp++; - if (info) { - strcpy(info,cp); - } - } - else { - if (flags) - strcpy(flags,cp); - } - } - else { - if (name) - strcpy(name,fullname); - } - return(0); + char *comma, *cp; + + /* Parse the fullname string looking for commas to determine what + * information is in the string. Then, based on the presence of + * the commas, populate the incoming pointers with the appropriate + * portion of the fullname string. + * If the pointer is NULL, then just skip over that portion of the + * algorithm. + */ + cp = fullname; + comma = strchr(cp,','); + if(comma) { + if(name) { + while(cp != comma) { + *name++ = *cp++; + } + *name = 0; + } + cp++; + comma = strchr(cp,','); + if(comma) { + if(flags) { + while(cp != comma) { + *flags++ = *cp++; + } + *flags = 0; + } + cp++; + if(info) { + strcpy(info,cp); + } + } else { + if(flags) { + strcpy(flags,cp); + } + } + } else { + if(name) { + strcpy(name,fullname); + } + } + return(0); } #endif /* Tftp(): - * Initiate a tftp transfer at the target (target is client). - * Command line: - * tftp [options] {IP} {get|put} {file|addr} [len]... - * tftp [options] {IP} get file dest_addr - * tftp [options] {IP} put addr dest_file len - * Currently, only "get" is supported. + * Initiate a tftp transfer at the target (target is client). + * Command line: + * tftp [options] {IP} {get|put} {file|addr} [len]... + * tftp [options] {IP} get file dest_addr + * tftp [options] {IP} put addr dest_file len + * Currently, only "get" is supported. */ char *TftpHelp[] = { - "Trivial file transfer protocol", - "-[aF:f:i:vV] [on|off|IP] {get|put filename [addr]} ss", + "Trivial file transfer protocol", + "-[aF:f:i:vV] [on|off|IP] {get|put filename [addr]} ss", #if INCLUDE_VERBOSEHELP - " -a use netascii mode", - " -F {file} name of tfs file to copy to", - " -f {flgs} file flags (see tfs)", - " -i {info} file info (see tfs)", - " -v verbosity = ticker", - " -V verbosity = state", + " -a use netascii mode", + " -F {file} name of tfs file to copy to", + " -f {flgs} file flags (see tfs)", + " -i {info} file info (see tfs)", + " -v verbosity = ticker", + " -V verbosity = state", #endif - 0, + 0, }; int Tftp(int argc,char *argv[]) { - int opt, verbose; - char *mode, *file, *info, *flags; - ulong addr; - - verbose = 0; - file = (char *)0; - info = (char *)0; - flags = (char *)0; - mode = "octet"; - while ((opt=getopt(argc,argv,"aF:f:i:vV")) != -1) { - switch(opt) { - case 'a': - mode = "netascii"; - break; - case 'f': - flags = optarg; - break; - case 'F': - file = optarg; - break; - case 'i': - info = optarg; - break; - case 'v': - verbose |= SHOW_TFTP_TICKER; - break; - case 'V': - verbose |= SHOW_TFTP_STATE; - break; - default: - return(CMD_PARAM_ERROR); - } - } - if (argc < (optind+1)) - return(CMD_PARAM_ERROR); - - if (argc == optind+1) { - if (!strcmp(argv[optind],"on")) { - TftpTurnedOff = 0; - TftpGetActive = 0; - TftpPutActive = 0; //ss ADDED - } - else if (!strcmp(argv[optind],"off")) { - TftpTurnedOff = 1; - TftpGetActive = 0; - tftpGotoState(TFTPIDLE); - TftpPutActive = 0; //ss ADDED - } - else - return(CMD_PARAM_ERROR); - return(CMD_SUCCESS); - } - - /* If either the info or flags field has been specified, but the */ - /* filename is not specified, error here... */ - if ((info || flags) && (!file)) { - printf("Filename missing\n"); - return(CMD_FAILURE); - } - - if (!strcmp(argv[optind+1],"get")) { - - if (argc == optind+4) - addr = (ulong)strtol(argv[optind+3],0,0); - else if (argc == optind+3) - addr = getAppRamStart(); - else - return(CMD_PARAM_ERROR); - - TFTPVERBOSE(EtherVerbose |= verbose); - tftpGet(addr,argv[optind],mode,argv[optind+2],file,flags,info); - TFTPVERBOSE(EtherVerbose &= ~verbose); - } - else if (!strcmp(argv[optind+1],"put")) { - - if (argc == (optind+3)) - file = argv[optind+2]; - else if (argc == (optind+4)) - file = argv[optind+3]; - else - return(CMD_PARAM_ERROR); - - TFTPVERBOSE(EtherVerbose |= verbose); - tftpPut(argv[optind],mode,file,argv[optind+2],flags,info); - TFTPVERBOSE(EtherVerbose &= ~verbose); - - } - else - return(CMD_PARAM_ERROR); - - return(CMD_SUCCESS); + int opt, verbose; + char *mode, *file, *info, *flags; + ulong addr; + + verbose = 0; + file = (char *)0; + info = (char *)0; + flags = (char *)0; + mode = "octet"; + while((opt=getopt(argc,argv,"aF:f:i:vV")) != -1) { + switch(opt) { + case 'a': + mode = "netascii"; + break; + case 'f': + flags = optarg; + break; + case 'F': + file = optarg; + break; + case 'i': + info = optarg; + break; + case 'v': + verbose |= SHOW_TFTP_TICKER; + break; + case 'V': + verbose |= SHOW_TFTP_STATE; + break; + default: + return(CMD_PARAM_ERROR); + } + } + if(argc < (optind+1)) { + return(CMD_PARAM_ERROR); + } + + if(argc == optind+1) { + if(!strcmp(argv[optind],"on")) { + TftpTurnedOff = 0; + TftpGetActive = 0; + TftpPutActive = 0; //ss ADDED + } else if(!strcmp(argv[optind],"off")) { + TftpTurnedOff = 1; + TftpGetActive = 0; + tftpGotoState(TFTPIDLE); + TftpPutActive = 0; //ss ADDED + } else { + return(CMD_PARAM_ERROR); + } + return(CMD_SUCCESS); + } + + /* If either the info or flags field has been specified, but the */ + /* filename is not specified, error here... */ + if((info || flags) && (!file)) { + printf("Filename missing\n"); + return(CMD_FAILURE); + } + + if(!strcmp(argv[optind+1],"get")) { + + if(argc == optind+4) { + addr = (ulong)strtol(argv[optind+3],0,0); + } else if(argc == optind+3) { + addr = getAppRamStart(); + } else { + return(CMD_PARAM_ERROR); + } + + TFTPVERBOSE(EtherVerbose |= verbose); + tftpGet(addr,argv[optind],mode,argv[optind+2],file,flags,info); + TFTPVERBOSE(EtherVerbose &= ~verbose); + } else if(!strcmp(argv[optind+1],"put")) { + + if(argc == (optind+3)) { + file = argv[optind+2]; + } else if(argc == (optind+4)) { + file = argv[optind+3]; + } else { + return(CMD_PARAM_ERROR); + } + + TFTPVERBOSE(EtherVerbose |= verbose); + tftpPut(argv[optind],mode,file,argv[optind+2],flags,info); + TFTPVERBOSE(EtherVerbose &= ~verbose); + + } else { + return(CMD_PARAM_ERROR); + } + + return(CMD_SUCCESS); } void ShowTftpStats(void) { - printf("Current TFTP state: %s\n",tftpStringState(TftpState)); + printf("Current TFTP state: %s\n",tftpStringState(TftpState)); } #endif |