]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - net/tftp.c
net: Refactor to protect access to the NetState variable
[karo-tx-uboot.git] / net / tftp.c
1 /*
2  * Copyright 1994, 1995, 2000 Neil Russell.
3  * (See License)
4  * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
5  * Copyright 2011 Comelit Group SpA,
6  *                Luca Ceresoli <luca.ceresoli@comelit.it>
7  */
8
9 #include <common.h>
10 #include <command.h>
11 #include <net.h>
12 #include "tftp.h"
13 #include "bootp.h"
14 #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
15 #include <flash.h>
16 #endif
17
18 /* Well known TFTP port # */
19 #define WELL_KNOWN_PORT 69
20 /* Millisecs to timeout for lost pkt */
21 #define TIMEOUT         5000UL
22 #ifndef CONFIG_NET_RETRY_COUNT
23 /* # of timeouts before giving up */
24 # define TIMEOUT_COUNT  10
25 #else
26 # define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT * 2)
27 #endif
28 /* Number of "loading" hashes per line (for checking the image size) */
29 #define HASHES_PER_LINE 65
30
31 /*
32  *      TFTP operations.
33  */
34 #define TFTP_RRQ        1
35 #define TFTP_WRQ        2
36 #define TFTP_DATA       3
37 #define TFTP_ACK        4
38 #define TFTP_ERROR      5
39 #define TFTP_OACK       6
40
41 static ulong TftpTimeoutMSecs = TIMEOUT;
42 static int TftpTimeoutCountMax = TIMEOUT_COUNT;
43
44 /*
45  * These globals govern the timeout behavior when attempting a connection to a
46  * TFTP server. TftpRRQTimeoutMSecs specifies the number of milliseconds to
47  * wait for the server to respond to initial connection. Second global,
48  * TftpRRQTimeoutCountMax, gives the number of such connection retries.
49  * TftpRRQTimeoutCountMax must be non-negative and TftpRRQTimeoutMSecs must be
50  * positive. The globals are meant to be set (and restored) by code needing
51  * non-standard timeout behavior when initiating a TFTP transfer.
52  */
53 ulong TftpRRQTimeoutMSecs = TIMEOUT;
54 int TftpRRQTimeoutCountMax = TIMEOUT_COUNT;
55
56 enum {
57         TFTP_ERR_UNDEFINED           = 0,
58         TFTP_ERR_FILE_NOT_FOUND      = 1,
59         TFTP_ERR_ACCESS_DENIED       = 2,
60         TFTP_ERR_DISK_FULL           = 3,
61         TFTP_ERR_UNEXPECTED_OPCODE   = 4,
62         TFTP_ERR_UNKNOWN_TRANSFER_ID  = 5,
63         TFTP_ERR_FILE_ALREADY_EXISTS = 6,
64 };
65
66 static IPaddr_t TftpRemoteIP;
67 /* The UDP port at their end */
68 static int      TftpRemotePort;
69 /* The UDP port at our end */
70 static int      TftpOurPort;
71 static int      TftpTimeoutCount;
72 /* packet sequence number */
73 static ulong    TftpBlock;
74 /* last packet sequence number received */
75 static ulong    TftpLastBlock;
76 /* count of sequence number wraparounds */
77 static ulong    TftpBlockWrap;
78 /* memory offset due to wrapping */
79 static ulong    TftpBlockWrapOffset;
80 static int      TftpState;
81 #ifdef CONFIG_TFTP_TSIZE
82 /* The file size reported by the server */
83 static int      TftpTsize;
84 /* The number of hashes we printed */
85 static short    TftpNumchars;
86 #endif
87 #ifdef CONFIG_CMD_TFTPPUT
88 static int      TftpWriting;    /* 1 if writing, else 0 */
89 static int      TftpFinalBlock; /* 1 if we have sent the last block */
90 #else
91 #define TftpWriting     0
92 #endif
93
94 #define STATE_SEND_RRQ  1
95 #define STATE_DATA      2
96 #define STATE_TOO_LARGE 3
97 #define STATE_BAD_MAGIC 4
98 #define STATE_OACK      5
99 #define STATE_RECV_WRQ  6
100 #define STATE_SEND_WRQ  7
101
102 /* default TFTP block size */
103 #define TFTP_BLOCK_SIZE         512
104 /* sequence number is 16 bit */
105 #define TFTP_SEQUENCE_SIZE      ((ulong)(1<<16))
106
107 #define DEFAULT_NAME_LEN        (8 + 4 + 1)
108 static char default_filename[DEFAULT_NAME_LEN];
109
110 #ifndef CONFIG_TFTP_FILE_NAME_MAX_LEN
111 #define MAX_LEN 128
112 #else
113 #define MAX_LEN CONFIG_TFTP_FILE_NAME_MAX_LEN
114 #endif
115
116 static char tftp_filename[MAX_LEN];
117
118 /* 512 is poor choice for ethernet, MTU is typically 1500.
119  * Minus eth.hdrs thats 1468.  Can get 2x better throughput with
120  * almost-MTU block sizes.  At least try... fall back to 512 if need be.
121  * (but those using CONFIG_IP_DEFRAG may want to set a larger block in cfg file)
122  */
123 #ifdef CONFIG_TFTP_BLOCKSIZE
124 #define TFTP_MTU_BLOCKSIZE CONFIG_TFTP_BLOCKSIZE
125 #else
126 #define TFTP_MTU_BLOCKSIZE 1468
127 #endif
128
129 static unsigned short TftpBlkSize = TFTP_BLOCK_SIZE;
130 static unsigned short TftpBlkSizeOption = TFTP_MTU_BLOCKSIZE;
131
132 #ifdef CONFIG_MCAST_TFTP
133 #include <malloc.h>
134 #define MTFTP_BITMAPSIZE        0x1000
135 static unsigned *Bitmap;
136 static int PrevBitmapHole, Mapsize = MTFTP_BITMAPSIZE;
137 static uchar ProhibitMcast, MasterClient;
138 static uchar Multicast;
139 static int Mcast_port;
140 static ulong TftpEndingBlock; /* can get 'last' block before done..*/
141
142 static void parse_multicast_oack(char *pkt, int len);
143
144 static void
145 mcast_cleanup(void)
146 {
147         if (Mcast_addr)
148                 eth_mcast_join(Mcast_addr, 0);
149         if (Bitmap)
150                 free(Bitmap);
151         Bitmap = NULL;
152         Mcast_addr = Multicast = Mcast_port = 0;
153         TftpEndingBlock = -1;
154 }
155
156 #endif  /* CONFIG_MCAST_TFTP */
157
158 static inline void
159 store_block(unsigned block, uchar *src, unsigned len)
160 {
161         ulong offset = block * TftpBlkSize + TftpBlockWrapOffset;
162         ulong newsize = offset + len;
163 #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
164         int i, rc = 0;
165
166         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
167                 /* start address in flash? */
168                 if (flash_info[i].flash_id == FLASH_UNKNOWN)
169                         continue;
170                 if (load_addr + offset >= flash_info[i].start[0]) {
171                         rc = 1;
172                         break;
173                 }
174         }
175
176         if (rc) { /* Flash is destination for this packet */
177                 rc = flash_write((char *)src, (ulong)(load_addr+offset), len);
178                 if (rc) {
179                         flash_perror(rc);
180                         net_set_state(NETLOOP_FAIL);
181                         return;
182                 }
183         } else
184 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
185         {
186                 (void)memcpy((void *)(load_addr + offset), src, len);
187         }
188 #ifdef CONFIG_MCAST_TFTP
189         if (Multicast)
190                 ext2_set_bit(block, Bitmap);
191 #endif
192
193         if (NetBootFileXferSize < newsize)
194                 NetBootFileXferSize = newsize;
195 }
196
197 /* Clear our state ready for a new transfer */
198 static void new_transfer(void)
199 {
200         TftpLastBlock = 0;
201         TftpBlockWrap = 0;
202         TftpBlockWrapOffset = 0;
203 #ifdef CONFIG_CMD_TFTPPUT
204         TftpFinalBlock = 0;
205 #endif
206 }
207
208 #ifdef CONFIG_CMD_TFTPPUT
209 /**
210  * Load the next block from memory to be sent over tftp.
211  *
212  * @param block Block number to send
213  * @param dst   Destination buffer for data
214  * @param len   Number of bytes in block (this one and every other)
215  * @return number of bytes loaded
216  */
217 static int load_block(unsigned block, uchar *dst, unsigned len)
218 {
219         /* We may want to get the final block from the previous set */
220         ulong offset = ((int)block - 1) * len + TftpBlockWrapOffset;
221         ulong tosend = len;
222
223         tosend = min(NetBootFileXferSize - offset, tosend);
224         (void)memcpy(dst, (void *)(save_addr + offset), tosend);
225         debug("%s: block=%d, offset=%ld, len=%d, tosend=%ld\n", __func__,
226                 block, offset, len, tosend);
227         return tosend;
228 }
229 #endif
230
231 static void TftpSend(void);
232 static void TftpTimeout(void);
233
234 /**********************************************************************/
235
236 static void show_block_marker(void)
237 {
238 #ifdef CONFIG_TFTP_TSIZE
239         if (TftpTsize) {
240                 ulong pos = TftpBlock * TftpBlkSize + TftpBlockWrapOffset;
241
242                 while (TftpNumchars < pos * 50 / TftpTsize) {
243                         putc('#');
244                         TftpNumchars++;
245                 }
246         } else
247 #endif
248         {
249                 if (((TftpBlock - 1) % 10) == 0)
250                         putc('#');
251                 else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0)
252                         puts("\n\t ");
253         }
254 }
255
256 /**
257  * restart the current transfer due to an error
258  *
259  * @param msg   Message to print for user
260  */
261 static void restart(const char *msg)
262 {
263         printf("\n%s; starting again\n", msg);
264 #ifdef CONFIG_MCAST_TFTP
265         mcast_cleanup();
266 #endif
267         NetStartAgain();
268 }
269
270 /*
271  * Check if the block number has wrapped, and update progress
272  *
273  * TODO: The egregious use of global variables in this file should be tidied.
274  */
275 static void update_block_number(void)
276 {
277         /*
278          * RFC1350 specifies that the first data packet will
279          * have sequence number 1. If we receive a sequence
280          * number of 0 this means that there was a wrap
281          * around of the (16 bit) counter.
282          */
283         if (TftpBlock == 0) {
284                 TftpBlockWrap++;
285                 TftpBlockWrapOffset += TftpBlkSize * TFTP_SEQUENCE_SIZE;
286                 TftpTimeoutCount = 0; /* we've done well, reset thhe timeout */
287         } else {
288                 show_block_marker();
289         }
290 }
291
292 /* The TFTP get or put is complete */
293 static void tftp_complete(void)
294 {
295 #ifdef CONFIG_TFTP_TSIZE
296         /* Print hash marks for the last packet received */
297         while (TftpTsize && TftpNumchars < 49) {
298                 putc('#');
299                 TftpNumchars++;
300         }
301 #endif
302         puts("\ndone\n");
303         net_set_state(NETLOOP_SUCCESS);
304 }
305
306 static void
307 TftpSend(void)
308 {
309         uchar *pkt;
310         uchar *xp;
311         int len = 0;
312         ushort *s;
313
314 #ifdef CONFIG_MCAST_TFTP
315         /* Multicast TFTP.. non-MasterClients do not ACK data. */
316         if (Multicast
317          && (TftpState == STATE_DATA)
318          && (MasterClient == 0))
319                 return;
320 #endif
321         /*
322          *      We will always be sending some sort of packet, so
323          *      cobble together the packet headers now.
324          */
325         pkt = NetTxPacket + NetEthHdrSize() + IP_UDP_HDR_SIZE;
326
327         switch (TftpState) {
328         case STATE_SEND_RRQ:
329         case STATE_SEND_WRQ:
330                 xp = pkt;
331                 s = (ushort *)pkt;
332 #ifdef CONFIG_CMD_TFTPPUT
333                 *s++ = htons(TftpState == STATE_SEND_RRQ ? TFTP_RRQ :
334                         TFTP_WRQ);
335 #else
336                 *s++ = htons(TFTP_RRQ);
337 #endif
338                 pkt = (uchar *)s;
339                 strcpy((char *)pkt, tftp_filename);
340                 pkt += strlen(tftp_filename) + 1;
341                 strcpy((char *)pkt, "octet");
342                 pkt += 5 /*strlen("octet")*/ + 1;
343                 strcpy((char *)pkt, "timeout");
344                 pkt += 7 /*strlen("timeout")*/ + 1;
345                 sprintf((char *)pkt, "%lu", TftpTimeoutMSecs / 1000);
346                 debug("send option \"timeout %s\"\n", (char *)pkt);
347                 pkt += strlen((char *)pkt) + 1;
348 #ifdef CONFIG_TFTP_TSIZE
349                 pkt += sprintf((char *)pkt, "tsize%c%lu%c",
350                                 0, NetBootFileXferSize, 0);
351 #endif
352                 /* try for more effic. blk size */
353                 pkt += sprintf((char *)pkt, "blksize%c%d%c",
354                                 0, TftpBlkSizeOption, 0);
355 #ifdef CONFIG_MCAST_TFTP
356                 /* Check all preconditions before even trying the option */
357                 if (!ProhibitMcast) {
358                         Bitmap = malloc(Mapsize);
359                         if (Bitmap && eth_get_dev()->mcast) {
360                                 free(Bitmap);
361                                 Bitmap = NULL;
362                                 pkt += sprintf((char *)pkt, "multicast%c%c",
363                                         0, 0);
364                         }
365                 }
366 #endif /* CONFIG_MCAST_TFTP */
367                 len = pkt - xp;
368                 break;
369
370         case STATE_OACK:
371 #ifdef CONFIG_MCAST_TFTP
372                 /* My turn!  Start at where I need blocks I missed.*/
373                 if (Multicast)
374                         TftpBlock = ext2_find_next_zero_bit(Bitmap,
375                                                             (Mapsize*8), 0);
376                 /*..falling..*/
377 #endif
378
379         case STATE_RECV_WRQ:
380         case STATE_DATA:
381                 xp = pkt;
382                 s = (ushort *)pkt;
383                 s[0] = htons(TFTP_ACK);
384                 s[1] = htons(TftpBlock);
385                 pkt = (uchar *)(s + 2);
386 #ifdef CONFIG_CMD_TFTPPUT
387                 if (TftpWriting) {
388                         int toload = TftpBlkSize;
389                         int loaded = load_block(TftpBlock, pkt, toload);
390
391                         s[0] = htons(TFTP_DATA);
392                         pkt += loaded;
393                         TftpFinalBlock = (loaded < toload);
394                 }
395 #endif
396                 len = pkt - xp;
397                 break;
398
399         case STATE_TOO_LARGE:
400                 xp = pkt;
401                 s = (ushort *)pkt;
402                 *s++ = htons(TFTP_ERROR);
403                         *s++ = htons(3);
404
405                 pkt = (uchar *)s;
406                 strcpy((char *)pkt, "File too large");
407                 pkt += 14 /*strlen("File too large")*/ + 1;
408                 len = pkt - xp;
409                 break;
410
411         case STATE_BAD_MAGIC:
412                 xp = pkt;
413                 s = (ushort *)pkt;
414                 *s++ = htons(TFTP_ERROR);
415                 *s++ = htons(2);
416                 pkt = (uchar *)s;
417                 strcpy((char *)pkt, "File has bad magic");
418                 pkt += 18 /*strlen("File has bad magic")*/ + 1;
419                 len = pkt - xp;
420                 break;
421         }
422
423         NetSendUDPPacket(NetServerEther, TftpRemoteIP, TftpRemotePort,
424                          TftpOurPort, len);
425 }
426
427 #ifdef CONFIG_CMD_TFTPPUT
428 static void icmp_handler(unsigned type, unsigned code, unsigned dest,
429                          IPaddr_t sip, unsigned src, uchar *pkt, unsigned len)
430 {
431         if (type == ICMP_NOT_REACH && code == ICMP_NOT_REACH_PORT) {
432                 /* Oh dear the other end has gone away */
433                 restart("TFTP server died");
434         }
435 }
436 #endif
437
438 static void
439 TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
440             unsigned len)
441 {
442         ushort proto;
443         ushort *s;
444         int i;
445
446         if (dest != TftpOurPort) {
447 #ifdef CONFIG_MCAST_TFTP
448                 if (Multicast
449                  && (!Mcast_port || (dest != Mcast_port)))
450 #endif
451                         return;
452         }
453         if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort &&
454             TftpState != STATE_RECV_WRQ && TftpState != STATE_SEND_WRQ)
455                 return;
456
457         if (len < 2)
458                 return;
459         len -= 2;
460         /* warning: don't use increment (++) in ntohs() macros!! */
461         s = (ushort *)pkt;
462         proto = *s++;
463         pkt = (uchar *)s;
464         switch (ntohs(proto)) {
465
466         case TFTP_RRQ:
467                 break;
468
469         case TFTP_ACK:
470 #ifdef CONFIG_CMD_TFTPPUT
471                 if (TftpWriting) {
472                         if (TftpFinalBlock) {
473                                 tftp_complete();
474                         } else {
475                                 /*
476                                  * Move to the next block. We want our block
477                                  * count to wrap just like the other end!
478                                  */
479                                 int block = ntohs(*s);
480                                 int ack_ok = (TftpBlock == block);
481
482                                 TftpBlock = (unsigned short)(block + 1);
483                                 update_block_number();
484                                 if (ack_ok)
485                                         TftpSend(); /* Send next data block */
486                         }
487                 }
488 #endif
489                 break;
490
491         default:
492                 break;
493
494 #ifdef CONFIG_CMD_TFTPSRV
495         case TFTP_WRQ:
496                 debug("Got WRQ\n");
497                 TftpRemoteIP = sip;
498                 TftpRemotePort = src;
499                 TftpOurPort = 1024 + (get_timer(0) % 3072);
500                 new_transfer();
501                 TftpSend(); /* Send ACK(0) */
502                 break;
503 #endif
504
505         case TFTP_OACK:
506                 debug("Got OACK: %s %s\n",
507                         pkt,
508                         pkt + strlen((char *)pkt) + 1);
509                 TftpState = STATE_OACK;
510                 TftpRemotePort = src;
511                 /*
512                  * Check for 'blksize' option.
513                  * Careful: "i" is signed, "len" is unsigned, thus
514                  * something like "len-8" may give a *huge* number
515                  */
516                 for (i = 0; i+8 < len; i++) {
517                         if (strcmp((char *)pkt+i, "blksize") == 0) {
518                                 TftpBlkSize = (unsigned short)
519                                         simple_strtoul((char *)pkt+i+8, NULL,
520                                                        10);
521                                 debug("Blocksize ack: %s, %d\n",
522                                         (char *)pkt+i+8, TftpBlkSize);
523                         }
524 #ifdef CONFIG_TFTP_TSIZE
525                         if (strcmp((char *)pkt+i, "tsize") == 0) {
526                                 TftpTsize = simple_strtoul((char *)pkt+i+6,
527                                                            NULL, 10);
528                                 debug("size = %s, %d\n",
529                                          (char *)pkt+i+6, TftpTsize);
530                         }
531 #endif
532                 }
533 #ifdef CONFIG_MCAST_TFTP
534                 parse_multicast_oack((char *)pkt, len-1);
535                 if ((Multicast) && (!MasterClient))
536                         TftpState = STATE_DATA; /* passive.. */
537                 else
538 #endif
539 #ifdef CONFIG_CMD_TFTPPUT
540                 if (TftpWriting) {
541                         /* Get ready to send the first block */
542                         TftpState = STATE_DATA;
543                         TftpBlock++;
544                 }
545 #endif
546                 TftpSend(); /* Send ACK or first data block */
547                 break;
548         case TFTP_DATA:
549                 if (len < 2)
550                         return;
551                 len -= 2;
552                 TftpBlock = ntohs(*(ushort *)pkt);
553
554                 update_block_number();
555
556                 if (TftpState == STATE_SEND_RRQ)
557                         debug("Server did not acknowledge timeout option!\n");
558
559                 if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK ||
560                     TftpState == STATE_RECV_WRQ) {
561                         /* first block received */
562                         TftpState = STATE_DATA;
563                         TftpRemotePort = src;
564                         new_transfer();
565
566 #ifdef CONFIG_MCAST_TFTP
567                         if (Multicast) { /* start!=1 common if mcast */
568                                 TftpLastBlock = TftpBlock - 1;
569                         } else
570 #endif
571                         if (TftpBlock != 1) {   /* Assertion */
572                                 printf("\nTFTP error: "
573                                        "First block is not block 1 (%ld)\n"
574                                        "Starting again\n\n",
575                                         TftpBlock);
576                                 NetStartAgain();
577                                 break;
578                         }
579                 }
580
581                 if (TftpBlock == TftpLastBlock) {
582                         /*
583                          *      Same block again; ignore it.
584                          */
585                         break;
586                 }
587
588                 TftpLastBlock = TftpBlock;
589                 TftpTimeoutCountMax = TIMEOUT_COUNT;
590                 NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
591
592                 store_block(TftpBlock - 1, pkt + 2, len);
593
594                 /*
595                  *      Acknowledge the block just received, which will prompt
596                  *      the remote for the next one.
597                  */
598 #ifdef CONFIG_MCAST_TFTP
599                 /* if I am the MasterClient, actively calculate what my next
600                  * needed block is; else I'm passive; not ACKING
601                  */
602                 if (Multicast) {
603                         if (len < TftpBlkSize)  {
604                                 TftpEndingBlock = TftpBlock;
605                         } else if (MasterClient) {
606                                 TftpBlock = PrevBitmapHole =
607                                         ext2_find_next_zero_bit(
608                                                 Bitmap,
609                                                 (Mapsize*8),
610                                                 PrevBitmapHole);
611                                 if (TftpBlock > ((Mapsize*8) - 1)) {
612                                         printf("tftpfile too big\n");
613                                         /* try to double it and retry */
614                                         Mapsize <<= 1;
615                                         mcast_cleanup();
616                                         NetStartAgain();
617                                         return;
618                                 }
619                                 TftpLastBlock = TftpBlock;
620                         }
621                 }
622 #endif
623                 TftpSend();
624
625 #ifdef CONFIG_MCAST_TFTP
626                 if (Multicast) {
627                         if (MasterClient && (TftpBlock >= TftpEndingBlock)) {
628                                 puts("\nMulticast tftp done\n");
629                                 mcast_cleanup();
630                                 net_set_state(NETLOOP_SUCCESS);
631                         }
632                 } else
633 #endif
634                 if (len < TftpBlkSize)
635                         tftp_complete();
636                 break;
637
638         case TFTP_ERROR:
639                 printf("\nTFTP error: '%s' (%d)\n",
640                        pkt + 2, ntohs(*(ushort *)pkt));
641
642                 switch (ntohs(*(ushort *)pkt)) {
643                 case TFTP_ERR_FILE_NOT_FOUND:
644                 case TFTP_ERR_ACCESS_DENIED:
645                         puts("Not retrying...\n");
646                         eth_halt();
647                         net_set_state(NETLOOP_FAIL);
648                         break;
649                 case TFTP_ERR_UNDEFINED:
650                 case TFTP_ERR_DISK_FULL:
651                 case TFTP_ERR_UNEXPECTED_OPCODE:
652                 case TFTP_ERR_UNKNOWN_TRANSFER_ID:
653                 case TFTP_ERR_FILE_ALREADY_EXISTS:
654                 default:
655                         puts("Starting again\n\n");
656 #ifdef CONFIG_MCAST_TFTP
657                         mcast_cleanup();
658 #endif
659                         NetStartAgain();
660                         break;
661                 }
662                 break;
663         }
664 }
665
666
667 static void
668 TftpTimeout(void)
669 {
670         if (++TftpTimeoutCount > TftpTimeoutCountMax) {
671                 restart("Retry count exceeded");
672         } else {
673                 puts("T ");
674                 NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
675                 if (TftpState != STATE_RECV_WRQ)
676                         TftpSend();
677         }
678 }
679
680
681 void TftpStart(enum proto_t protocol)
682 {
683         char *ep;             /* Environment pointer */
684
685         /*
686          * Allow the user to choose TFTP blocksize and timeout.
687          * TFTP protocol has a minimal timeout of 1 second.
688          */
689         ep = getenv("tftpblocksize");
690         if (ep != NULL)
691                 TftpBlkSizeOption = simple_strtol(ep, NULL, 10);
692
693         ep = getenv("tftptimeout");
694         if (ep != NULL)
695                 TftpTimeoutMSecs = simple_strtol(ep, NULL, 10);
696
697         if (TftpTimeoutMSecs < 1000) {
698                 printf("TFTP timeout (%ld ms) too low, "
699                         "set minimum = 1000 ms\n",
700                         TftpTimeoutMSecs);
701                 TftpTimeoutMSecs = 1000;
702         }
703
704         debug("TFTP blocksize = %i, timeout = %ld ms\n",
705                 TftpBlkSizeOption, TftpTimeoutMSecs);
706
707         TftpRemoteIP = NetServerIP;
708         if (BootFile[0] == '\0') {
709                 sprintf(default_filename, "%02X%02X%02X%02X.img",
710                         NetOurIP & 0xFF,
711                         (NetOurIP >>  8) & 0xFF,
712                         (NetOurIP >> 16) & 0xFF,
713                         (NetOurIP >> 24) & 0xFF);
714
715                 strncpy(tftp_filename, default_filename, MAX_LEN);
716                 tftp_filename[MAX_LEN-1] = 0;
717
718                 printf("*** Warning: no boot file name; using '%s'\n",
719                         tftp_filename);
720         } else {
721                 char *p = strchr(BootFile, ':');
722
723                 if (p == NULL) {
724                         strncpy(tftp_filename, BootFile, MAX_LEN);
725                         tftp_filename[MAX_LEN-1] = 0;
726                 } else {
727                         TftpRemoteIP = string_to_ip(BootFile);
728                         strncpy(tftp_filename, p + 1, MAX_LEN);
729                         tftp_filename[MAX_LEN-1] = 0;
730                 }
731         }
732
733         printf("Using %s device\n", eth_get_name());
734         printf("TFTP %s server %pI4; our IP address is %pI4",
735 #ifdef CONFIG_CMD_TFTPPUT
736                protocol == TFTPPUT ? "to" : "from",
737 #else
738                 "from",
739 #endif
740                 &TftpRemoteIP, &NetOurIP);
741
742         /* Check if we need to send across this subnet */
743         if (NetOurGatewayIP && NetOurSubnetMask) {
744                 IPaddr_t OurNet = NetOurIP    & NetOurSubnetMask;
745                 IPaddr_t RemoteNet      = TftpRemoteIP & NetOurSubnetMask;
746
747                 if (OurNet != RemoteNet)
748                         printf("; sending through gateway %pI4",
749                                &NetOurGatewayIP);
750         }
751         putc('\n');
752
753         printf("Filename '%s'.", tftp_filename);
754
755         if (NetBootFileSize) {
756                 printf(" Size is 0x%x Bytes = ", NetBootFileSize<<9);
757                 print_size(NetBootFileSize<<9, "");
758         }
759
760         putc('\n');
761 #ifdef CONFIG_CMD_TFTPPUT
762         TftpWriting = (protocol == TFTPPUT);
763         if (TftpWriting) {
764                 printf("Save address: 0x%lx\n", save_addr);
765                 printf("Save size:    0x%lx\n", save_size);
766                 NetBootFileXferSize = save_size;
767                 puts("Saving: *\b");
768                 TftpState = STATE_SEND_WRQ;
769                 new_transfer();
770         } else
771 #endif
772         {
773                 printf("Load address: 0x%lx\n", load_addr);
774                 puts("Loading: *\b");
775                 TftpState = STATE_SEND_RRQ;
776         }
777
778         TftpTimeoutCountMax = TftpRRQTimeoutCountMax;
779
780         NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
781         NetSetHandler(TftpHandler);
782 #ifdef CONFIG_CMD_TFTPPUT
783         net_set_icmp_handler(icmp_handler);
784 #endif
785         TftpRemotePort = WELL_KNOWN_PORT;
786         TftpTimeoutCount = 0;
787         /* Use a pseudo-random port unless a specific port is set */
788         TftpOurPort = 1024 + (get_timer(0) % 3072);
789
790 #ifdef CONFIG_TFTP_PORT
791         ep = getenv("tftpdstp");
792         if (ep != NULL)
793                 TftpRemotePort = simple_strtol(ep, NULL, 10);
794         ep = getenv("tftpsrcp");
795         if (ep != NULL)
796                 TftpOurPort = simple_strtol(ep, NULL, 10);
797 #endif
798         TftpBlock = 0;
799
800         /* zero out server ether in case the server ip has changed */
801         memset(NetServerEther, 0, 6);
802         /* Revert TftpBlkSize to dflt */
803         TftpBlkSize = TFTP_BLOCK_SIZE;
804 #ifdef CONFIG_MCAST_TFTP
805         mcast_cleanup();
806 #endif
807 #ifdef CONFIG_TFTP_TSIZE
808         TftpTsize = 0;
809         TftpNumchars = 0;
810 #endif
811
812         TftpSend();
813 }
814
815 #ifdef CONFIG_CMD_TFTPSRV
816 void
817 TftpStartServer(void)
818 {
819         tftp_filename[0] = 0;
820
821         printf("Using %s device\n", eth_get_name());
822         printf("Listening for TFTP transfer on %pI4\n", &NetOurIP);
823         printf("Load address: 0x%lx\n", load_addr);
824
825         puts("Loading: *\b");
826
827         TftpTimeoutCountMax = TIMEOUT_COUNT;
828         TftpTimeoutCount = 0;
829         TftpTimeoutMSecs = TIMEOUT;
830         NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
831
832         /* Revert TftpBlkSize to dflt */
833         TftpBlkSize = TFTP_BLOCK_SIZE;
834         TftpBlock = 0;
835         TftpOurPort = WELL_KNOWN_PORT;
836
837 #ifdef CONFIG_TFTP_TSIZE
838         TftpTsize = 0;
839         TftpNumchars = 0;
840 #endif
841
842         TftpState = STATE_RECV_WRQ;
843         NetSetHandler(TftpHandler);
844 }
845 #endif /* CONFIG_CMD_TFTPSRV */
846
847 #ifdef CONFIG_MCAST_TFTP
848 /* Credits: atftp project.
849  */
850
851 /* pick up BcastAddr, Port, and whether I am [now] the master-client. *
852  * Frame:
853  *    +-------+-----------+---+-------~~-------+---+
854  *    |  opc  | multicast | 0 | addr, port, mc | 0 |
855  *    +-------+-----------+---+-------~~-------+---+
856  * The multicast addr/port becomes what I listen to, and if 'mc' is '1' then
857  * I am the new master-client so must send ACKs to DataBlocks.  If I am not
858  * master-client, I'm a passive client, gathering what DataBlocks I may and
859  * making note of which ones I got in my bitmask.
860  * In theory, I never go from master->passive..
861  * .. this comes in with pkt already pointing just past opc
862  */
863 static void parse_multicast_oack(char *pkt, int len)
864 {
865         int i;
866         IPaddr_t addr;
867         char *mc_adr, *port,  *mc;
868
869         mc_adr = port = mc = NULL;
870         /* march along looking for 'multicast\0', which has to start at least
871          * 14 bytes back from the end.
872          */
873         for (i = 0; i < len-14; i++)
874                 if (strcmp(pkt+i, "multicast") == 0)
875                         break;
876         if (i >= (len-14)) /* non-Multicast OACK, ign. */
877                 return;
878
879         i += 10; /* strlen multicast */
880         mc_adr = pkt+i;
881         for (; i < len; i++) {
882                 if (*(pkt+i) == ',') {
883                         *(pkt+i) = '\0';
884                         if (port) {
885                                 mc = pkt+i+1;
886                                 break;
887                         } else {
888                                 port = pkt+i+1;
889                         }
890                 }
891         }
892         if (!port || !mc_adr || !mc)
893                 return;
894         if (Multicast && MasterClient) {
895                 printf("I got a OACK as master Client, WRONG!\n");
896                 return;
897         }
898         /* ..I now accept packets destined for this MCAST addr, port */
899         if (!Multicast) {
900                 if (Bitmap) {
901                         printf("Internal failure! no mcast.\n");
902                         free(Bitmap);
903                         Bitmap = NULL;
904                         ProhibitMcast = 1;
905                         return ;
906                 }
907                 /* I malloc instead of pre-declare; so that if the file ends
908                  * up being too big for this bitmap I can retry
909                  */
910                 Bitmap = malloc(Mapsize);
911                 if (!Bitmap) {
912                         printf("No Bitmap, no multicast. Sorry.\n");
913                         ProhibitMcast = 1;
914                         return;
915                 }
916                 memset(Bitmap, 0, Mapsize);
917                 PrevBitmapHole = 0;
918                 Multicast = 1;
919         }
920         addr = string_to_ip(mc_adr);
921         if (Mcast_addr != addr) {
922                 if (Mcast_addr)
923                         eth_mcast_join(Mcast_addr, 0);
924                 Mcast_addr = addr;
925                 if (eth_mcast_join(Mcast_addr, 1)) {
926                         printf("Fail to set mcast, revert to TFTP\n");
927                         ProhibitMcast = 1;
928                         mcast_cleanup();
929                         NetStartAgain();
930                 }
931         }
932         MasterClient = (unsigned char)simple_strtoul((char *)mc, NULL, 10);
933         Mcast_port = (unsigned short)simple_strtoul(port, NULL, 10);
934         printf("Multicast: %s:%d [%d]\n", mc_adr, Mcast_port, MasterClient);
935         return;
936 }
937
938 #endif /* Multicast TFTP */