net/tftp.c: cosmetic: fix lines over 80 characters
[platform/kernel/u-boot.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  */
6
7 #include <common.h>
8 #include <command.h>
9 #include <net.h>
10 #include "tftp.h"
11 #include "bootp.h"
12
13 /* Well known TFTP port # */
14 #define WELL_KNOWN_PORT 69
15 /* Millisecs to timeout for lost pkt */
16 #define TIMEOUT         5000UL
17 #ifndef CONFIG_NET_RETRY_COUNT
18 /* # of timeouts before giving up */
19 # define TIMEOUT_COUNT  10
20 #else
21 # define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT * 2)
22 #endif
23 /* Number of "loading" hashes per line (for checking the image size) */
24 #define HASHES_PER_LINE 65
25
26 /*
27  *      TFTP operations.
28  */
29 #define TFTP_RRQ        1
30 #define TFTP_WRQ        2
31 #define TFTP_DATA       3
32 #define TFTP_ACK        4
33 #define TFTP_ERROR      5
34 #define TFTP_OACK       6
35
36 static ulong TftpTimeoutMSecs = TIMEOUT;
37 static int TftpTimeoutCountMax = TIMEOUT_COUNT;
38
39 /*
40  * These globals govern the timeout behavior when attempting a connection to a
41  * TFTP server. TftpRRQTimeoutMSecs specifies the number of milliseconds to
42  * wait for the server to respond to initial connection. Second global,
43  * TftpRRQTimeoutCountMax, gives the number of such connection retries.
44  * TftpRRQTimeoutCountMax must be non-negative and TftpRRQTimeoutMSecs must be
45  * positive. The globals are meant to be set (and restored) by code needing
46  * non-standard timeout behavior when initiating a TFTP transfer.
47  */
48 ulong TftpRRQTimeoutMSecs = TIMEOUT;
49 int TftpRRQTimeoutCountMax = TIMEOUT_COUNT;
50
51 enum {
52         TFTP_ERR_UNDEFINED           = 0,
53         TFTP_ERR_FILE_NOT_FOUND      = 1,
54         TFTP_ERR_ACCESS_DENIED       = 2,
55         TFTP_ERR_DISK_FULL           = 3,
56         TFTP_ERR_UNEXPECTED_OPCODE   = 4,
57         TFTP_ERR_UNKNOWN_TRANSFER_ID  = 5,
58         TFTP_ERR_FILE_ALREADY_EXISTS = 6,
59 };
60
61 static IPaddr_t TftpServerIP;
62 /* The UDP port at their end */
63 static int      TftpServerPort;
64 /* The UDP port at our end */
65 static int      TftpOurPort;
66 static int      TftpTimeoutCount;
67 /* packet sequence number */
68 static ulong    TftpBlock;
69 /* last packet sequence number received */
70 static ulong    TftpLastBlock;
71 /* count of sequence number wraparounds */
72 static ulong    TftpBlockWrap;
73 /* memory offset due to wrapping */
74 static ulong    TftpBlockWrapOffset;
75 static int      TftpState;
76 #ifdef CONFIG_TFTP_TSIZE
77 /* The file size reported by the server */
78 static int      TftpTsize;
79 /* The number of hashes we printed */
80 static short    TftpNumchars;
81 #endif
82
83 #define STATE_RRQ       1
84 #define STATE_DATA      2
85 #define STATE_TOO_LARGE 3
86 #define STATE_BAD_MAGIC 4
87 #define STATE_OACK      5
88
89 /* default TFTP block size */
90 #define TFTP_BLOCK_SIZE         512
91 /* sequence number is 16 bit */
92 #define TFTP_SEQUENCE_SIZE      ((ulong)(1<<16))
93
94 #define DEFAULT_NAME_LEN        (8 + 4 + 1)
95 static char default_filename[DEFAULT_NAME_LEN];
96
97 #ifndef CONFIG_TFTP_FILE_NAME_MAX_LEN
98 #define MAX_LEN 128
99 #else
100 #define MAX_LEN CONFIG_TFTP_FILE_NAME_MAX_LEN
101 #endif
102
103 static char tftp_filename[MAX_LEN];
104
105 #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
106 extern flash_info_t flash_info[];
107 #endif
108
109 /* 512 is poor choice for ethernet, MTU is typically 1500.
110  * Minus eth.hdrs thats 1468.  Can get 2x better throughput with
111  * almost-MTU block sizes.  At least try... fall back to 512 if need be.
112  * (but those using CONFIG_IP_DEFRAG may want to set a larger block in cfg file)
113  */
114 #ifdef CONFIG_TFTP_BLOCKSIZE
115 #define TFTP_MTU_BLOCKSIZE CONFIG_TFTP_BLOCKSIZE
116 #else
117 #define TFTP_MTU_BLOCKSIZE 1468
118 #endif
119
120 static unsigned short TftpBlkSize=TFTP_BLOCK_SIZE;
121 static unsigned short TftpBlkSizeOption=TFTP_MTU_BLOCKSIZE;
122
123 #ifdef CONFIG_MCAST_TFTP
124 #include <malloc.h>
125 #define MTFTP_BITMAPSIZE        0x1000
126 static unsigned *Bitmap;
127 static int PrevBitmapHole,Mapsize=MTFTP_BITMAPSIZE;
128 static uchar ProhibitMcast=0, MasterClient=0;
129 static uchar Multicast=0;
130 extern IPaddr_t Mcast_addr;
131 static int Mcast_port;
132 static ulong TftpEndingBlock; /* can get 'last' block before done..*/
133
134 static void parse_multicast_oack(char *pkt,int len);
135
136 static void
137 mcast_cleanup(void)
138 {
139         if (Mcast_addr) eth_mcast_join(Mcast_addr, 0);
140         if (Bitmap) free(Bitmap);
141         Bitmap=NULL;
142         Mcast_addr = Multicast = Mcast_port = 0;
143         TftpEndingBlock = -1;
144 }
145
146 #endif  /* CONFIG_MCAST_TFTP */
147
148 static __inline__ void
149 store_block (unsigned block, uchar * src, unsigned len)
150 {
151         ulong offset = block * TftpBlkSize + TftpBlockWrapOffset;
152         ulong newsize = offset + len;
153 #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
154         int i, rc = 0;
155
156         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; i++) {
157                 /* start address in flash? */
158                 if (flash_info[i].flash_id == FLASH_UNKNOWN)
159                         continue;
160                 if (load_addr + offset >= flash_info[i].start[0]) {
161                         rc = 1;
162                         break;
163                 }
164         }
165
166         if (rc) { /* Flash is destination for this packet */
167                 rc = flash_write ((char *)src, (ulong)(load_addr+offset), len);
168                 if (rc) {
169                         flash_perror (rc);
170                         NetState = NETLOOP_FAIL;
171                         return;
172                 }
173         }
174         else
175 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
176         {
177                 (void)memcpy((void *)(load_addr + offset), src, len);
178         }
179 #ifdef CONFIG_MCAST_TFTP
180         if (Multicast)
181                 ext2_set_bit(block, Bitmap);
182 #endif
183
184         if (NetBootFileXferSize < newsize)
185                 NetBootFileXferSize = newsize;
186 }
187
188 static void TftpSend (void);
189 static void TftpTimeout (void);
190
191 /**********************************************************************/
192
193 static void
194 TftpSend (void)
195 {
196         volatile uchar *        pkt;
197         volatile uchar *        xp;
198         int                     len = 0;
199         volatile ushort *s;
200
201 #ifdef CONFIG_MCAST_TFTP
202         /* Multicast TFTP.. non-MasterClients do not ACK data. */
203         if (Multicast
204          && (TftpState == STATE_DATA)
205          && (MasterClient == 0))
206                 return;
207 #endif
208         /*
209          *      We will always be sending some sort of packet, so
210          *      cobble together the packet headers now.
211          */
212         pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
213
214         switch (TftpState) {
215
216         case STATE_RRQ:
217                 xp = pkt;
218                 s = (ushort *)pkt;
219                 *s++ = htons(TFTP_RRQ);
220                 pkt = (uchar *)s;
221                 strcpy ((char *)pkt, tftp_filename);
222                 pkt += strlen(tftp_filename) + 1;
223                 strcpy ((char *)pkt, "octet");
224                 pkt += 5 /*strlen("octet")*/ + 1;
225                 strcpy ((char *)pkt, "timeout");
226                 pkt += 7 /*strlen("timeout")*/ + 1;
227                 sprintf((char *)pkt, "%lu", TftpTimeoutMSecs / 1000);
228                 debug("send option \"timeout %s\"\n", (char *)pkt);
229                 pkt += strlen((char *)pkt) + 1;
230 #ifdef CONFIG_TFTP_TSIZE
231                 memcpy((char *)pkt, "tsize\0000\0", 8);
232                 pkt += 8;
233 #endif
234                 /* try for more effic. blk size */
235                 pkt += sprintf((char *)pkt,"blksize%c%d%c",
236                                 0,TftpBlkSizeOption,0);
237 #ifdef CONFIG_MCAST_TFTP
238                 /* Check all preconditions before even trying the option */
239                 if (!ProhibitMcast
240                  && (Bitmap=malloc(Mapsize))
241                  && eth_get_dev()->mcast) {
242                         free(Bitmap);
243                         Bitmap=NULL;
244                         pkt += sprintf((char *)pkt,"multicast%c%c",0,0);
245                 }
246 #endif /* CONFIG_MCAST_TFTP */
247                 len = pkt - xp;
248                 break;
249
250         case STATE_OACK:
251 #ifdef CONFIG_MCAST_TFTP
252                 /* My turn!  Start at where I need blocks I missed.*/
253                 if (Multicast)
254                         TftpBlock=ext2_find_next_zero_bit(Bitmap,(Mapsize*8),0);
255                 /*..falling..*/
256 #endif
257         case STATE_DATA:
258                 xp = pkt;
259                 s = (ushort *)pkt;
260                 *s++ = htons(TFTP_ACK);
261                 *s++ = htons(TftpBlock);
262                 pkt = (uchar *)s;
263                 len = pkt - xp;
264                 break;
265
266         case STATE_TOO_LARGE:
267                 xp = pkt;
268                 s = (ushort *)pkt;
269                 *s++ = htons(TFTP_ERROR);
270                 *s++ = htons(3);
271                 pkt = (uchar *)s;
272                 strcpy ((char *)pkt, "File too large");
273                 pkt += 14 /*strlen("File too large")*/ + 1;
274                 len = pkt - xp;
275                 break;
276
277         case STATE_BAD_MAGIC:
278                 xp = pkt;
279                 s = (ushort *)pkt;
280                 *s++ = htons(TFTP_ERROR);
281                 *s++ = htons(2);
282                 pkt = (uchar *)s;
283                 strcpy ((char *)pkt, "File has bad magic");
284                 pkt += 18 /*strlen("File has bad magic")*/ + 1;
285                 len = pkt - xp;
286                 break;
287         }
288
289         NetSendUDPPacket(NetServerEther, TftpServerIP, TftpServerPort,
290                          TftpOurPort, len);
291 }
292
293
294 static void
295 TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
296             unsigned len)
297 {
298         ushort proto;
299         ushort *s;
300         int i;
301
302         if (dest != TftpOurPort) {
303 #ifdef CONFIG_MCAST_TFTP
304                 if (Multicast
305                  && (!Mcast_port || (dest != Mcast_port)))
306 #endif
307                 return;
308         }
309         if (TftpState != STATE_RRQ && src != TftpServerPort) {
310                 return;
311         }
312
313         if (len < 2) {
314                 return;
315         }
316         len -= 2;
317         /* warning: don't use increment (++) in ntohs() macros!! */
318         s = (ushort *)pkt;
319         proto = *s++;
320         pkt = (uchar *)s;
321         switch (ntohs(proto)) {
322
323         case TFTP_RRQ:
324         case TFTP_WRQ:
325         case TFTP_ACK:
326                 break;
327         default:
328                 break;
329
330         case TFTP_OACK:
331                 debug("Got OACK: %s %s\n",
332                         pkt,
333                         pkt + strlen((char *)pkt) + 1);
334                 TftpState = STATE_OACK;
335                 TftpServerPort = src;
336                 /*
337                  * Check for 'blksize' option.
338                  * Careful: "i" is signed, "len" is unsigned, thus
339                  * something like "len-8" may give a *huge* number
340                  */
341                 for (i=0; i+8<len; i++) {
342                         if (strcmp ((char*)pkt+i,"blksize") == 0) {
343                                 TftpBlkSize = (unsigned short)
344                                         simple_strtoul((char*)pkt+i+8,NULL,10);
345                                 debug("Blocksize ack: %s, %d\n",
346                                         (char*)pkt+i+8,TftpBlkSize);
347                         }
348 #ifdef CONFIG_TFTP_TSIZE
349                         if (strcmp ((char*)pkt+i,"tsize") == 0) {
350                                 TftpTsize = simple_strtoul((char*)pkt+i+6,
351                                                            NULL, 10);
352                                 debug("size = %s, %d\n",
353                                          (char*)pkt+i+6, TftpTsize);
354                         }
355 #endif
356                 }
357 #ifdef CONFIG_MCAST_TFTP
358                 parse_multicast_oack((char *)pkt,len-1);
359                 if ((Multicast) && (!MasterClient))
360                         TftpState = STATE_DATA; /* passive.. */
361                 else
362 #endif
363                 TftpSend (); /* Send ACK */
364                 break;
365         case TFTP_DATA:
366                 if (len < 2)
367                         return;
368                 len -= 2;
369                 TftpBlock = ntohs(*(ushort *)pkt);
370
371                 /*
372                  * RFC1350 specifies that the first data packet will
373                  * have sequence number 1. If we receive a sequence
374                  * number of 0 this means that there was a wrap
375                  * around of the (16 bit) counter.
376                  */
377                 if (TftpBlock == 0) {
378                         TftpBlockWrap++;
379                         TftpBlockWrapOffset +=
380                                 TftpBlkSize * TFTP_SEQUENCE_SIZE;
381                         printf ("\n\t %lu MB received\n\t ",
382                                 TftpBlockWrapOffset>>20);
383                 }
384 #ifdef CONFIG_TFTP_TSIZE
385                 else if (TftpTsize) {
386                         while (TftpNumchars <
387                                NetBootFileXferSize * 50 / TftpTsize) {
388                                 putc('#');
389                                 TftpNumchars++;
390                         }
391                 }
392 #endif
393                 else {
394                         if (((TftpBlock - 1) % 10) == 0) {
395                                 putc ('#');
396                         } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
397                                 puts ("\n\t ");
398                         }
399                 }
400
401                 if (TftpState == STATE_RRQ)
402                         debug("Server did not acknowledge timeout option!\n");
403
404                 if (TftpState == STATE_RRQ || TftpState == STATE_OACK) {
405                         /* first block received */
406                         TftpState = STATE_DATA;
407                         TftpServerPort = src;
408                         TftpLastBlock = 0;
409                         TftpBlockWrap = 0;
410                         TftpBlockWrapOffset = 0;
411
412 #ifdef CONFIG_MCAST_TFTP
413                         if (Multicast) { /* start!=1 common if mcast */
414                                 TftpLastBlock = TftpBlock - 1;
415                         } else
416 #endif
417                         if (TftpBlock != 1) {   /* Assertion */
418                                 printf ("\nTFTP error: "
419                                         "First block is not block 1 (%ld)\n"
420                                         "Starting again\n\n",
421                                         TftpBlock);
422                                 NetStartAgain ();
423                                 break;
424                         }
425                 }
426
427                 if (TftpBlock == TftpLastBlock) {
428                         /*
429                          *      Same block again; ignore it.
430                          */
431                         break;
432                 }
433
434                 TftpLastBlock = TftpBlock;
435                 TftpTimeoutCountMax = TIMEOUT_COUNT;
436                 NetSetTimeout (TftpTimeoutMSecs, TftpTimeout);
437
438                 store_block (TftpBlock - 1, pkt + 2, len);
439
440                 /*
441                  *      Acknoledge the block just received, which will prompt
442                  *      the server for the next one.
443                  */
444 #ifdef CONFIG_MCAST_TFTP
445                 /* if I am the MasterClient, actively calculate what my next
446                  * needed block is; else I'm passive; not ACKING
447                  */
448                 if (Multicast) {
449                         if (len < TftpBlkSize)  {
450                                 TftpEndingBlock = TftpBlock;
451                         } else if (MasterClient) {
452                                 TftpBlock = PrevBitmapHole =
453                                         ext2_find_next_zero_bit(
454                                                 Bitmap,
455                                                 (Mapsize*8),
456                                                 PrevBitmapHole);
457                                 if (TftpBlock > ((Mapsize*8) - 1)) {
458                                         printf ("tftpfile too big\n");
459                                         /* try to double it and retry */
460                                         Mapsize<<=1;
461                                         mcast_cleanup();
462                                         NetStartAgain ();
463                                         return;
464                                 }
465                                 TftpLastBlock = TftpBlock;
466                         }
467                 }
468 #endif
469                 TftpSend ();
470
471 #ifdef CONFIG_MCAST_TFTP
472                 if (Multicast) {
473                         if (MasterClient && (TftpBlock >= TftpEndingBlock)) {
474                                 puts ("\nMulticast tftp done\n");
475                                 mcast_cleanup();
476                                 NetState = NETLOOP_SUCCESS;
477                         }
478                 }
479                 else
480 #endif
481                 if (len < TftpBlkSize) {
482                         /*
483                          *      We received the whole thing.  Try to
484                          *      run it.
485                          */
486 #ifdef CONFIG_TFTP_TSIZE
487                         /* Print hash marks for the last packet received */
488                         while (TftpTsize && TftpNumchars < 49) {
489                                 putc('#');
490                                 TftpNumchars++;
491                         }
492 #endif
493                         puts ("\ndone\n");
494                         NetState = NETLOOP_SUCCESS;
495                 }
496                 break;
497
498         case TFTP_ERROR:
499                 printf ("\nTFTP error: '%s' (%d)\n",
500                                         pkt + 2, ntohs(*(ushort *)pkt));
501
502                 switch (ntohs(*(ushort *)pkt)) {
503                 case TFTP_ERR_FILE_NOT_FOUND:
504                 case TFTP_ERR_ACCESS_DENIED:
505                         puts("Not retrying...\n");
506                         eth_halt();
507                         NetState = NETLOOP_FAIL;
508                         break;
509                 case TFTP_ERR_UNDEFINED:
510                 case TFTP_ERR_DISK_FULL:
511                 case TFTP_ERR_UNEXPECTED_OPCODE:
512                 case TFTP_ERR_UNKNOWN_TRANSFER_ID:
513                 case TFTP_ERR_FILE_ALREADY_EXISTS:
514                 default:
515                         puts("Starting again\n\n");
516 #ifdef CONFIG_MCAST_TFTP
517                         mcast_cleanup();
518 #endif
519                         NetStartAgain();
520                         break;
521                 }
522                 break;
523         }
524 }
525
526
527 static void
528 TftpTimeout (void)
529 {
530         if (++TftpTimeoutCount > TftpTimeoutCountMax) {
531                 puts ("\nRetry count exceeded; starting again\n");
532 #ifdef CONFIG_MCAST_TFTP
533                 mcast_cleanup();
534 #endif
535                 NetStartAgain ();
536         } else {
537                 puts ("T ");
538                 NetSetTimeout (TftpTimeoutMSecs, TftpTimeout);
539                 TftpSend ();
540         }
541 }
542
543
544 void
545 TftpStart (void)
546 {
547         char *ep;             /* Environment pointer */
548
549         /*
550          * Allow the user to choose TFTP blocksize and timeout.
551          * TFTP protocol has a minimal timeout of 1 second.
552          */
553         if ((ep = getenv("tftpblocksize")) != NULL)
554                 TftpBlkSizeOption = simple_strtol(ep, NULL, 10);
555
556         if ((ep = getenv("tftptimeout")) != NULL)
557                 TftpTimeoutMSecs = simple_strtol(ep, NULL, 10);
558
559         if (TftpTimeoutMSecs < 1000) {
560                 printf("TFTP timeout (%ld ms) too low, "
561                         "set minimum = 1000 ms\n",
562                         TftpTimeoutMSecs);
563                 TftpTimeoutMSecs = 1000;
564         }
565
566         debug("TFTP blocksize = %i, timeout = %ld ms\n",
567                 TftpBlkSizeOption, TftpTimeoutMSecs);
568
569         TftpServerIP = NetServerIP;
570         if (BootFile[0] == '\0') {
571                 sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
572                         NetOurIP & 0xFF,
573                         (NetOurIP >>  8) & 0xFF,
574                         (NetOurIP >> 16) & 0xFF,
575                         (NetOurIP >> 24) & 0xFF );
576
577                 strncpy(tftp_filename, default_filename, MAX_LEN);
578                 tftp_filename[MAX_LEN-1] = 0;
579
580                 printf ("*** Warning: no boot file name; using '%s'\n",
581                         tftp_filename);
582         } else {
583                 char *p = strchr (BootFile, ':');
584
585                 if (p == NULL) {
586                         strncpy(tftp_filename, BootFile, MAX_LEN);
587                         tftp_filename[MAX_LEN-1] = 0;
588                 } else {
589                         TftpServerIP = string_to_ip (BootFile);
590                         strncpy(tftp_filename, p + 1, MAX_LEN);
591                         tftp_filename[MAX_LEN-1] = 0;
592                 }
593         }
594
595 #if defined(CONFIG_NET_MULTI)
596         printf ("Using %s device\n", eth_get_name());
597 #endif
598         printf("TFTP from server %pI4"
599                 "; our IP address is %pI4", &TftpServerIP, &NetOurIP);
600
601         /* Check if we need to send across this subnet */
602         if (NetOurGatewayIP && NetOurSubnetMask) {
603             IPaddr_t OurNet     = NetOurIP    & NetOurSubnetMask;
604             IPaddr_t ServerNet  = TftpServerIP & NetOurSubnetMask;
605
606             if (OurNet != ServerNet)
607                 printf("; sending through gateway %pI4", &NetOurGatewayIP);
608         }
609         putc ('\n');
610
611         printf ("Filename '%s'.", tftp_filename);
612
613         if (NetBootFileSize) {
614                 printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9);
615                 print_size (NetBootFileSize<<9, "");
616         }
617
618         putc ('\n');
619
620         printf ("Load address: 0x%lx\n", load_addr);
621
622         puts ("Loading: *\b");
623
624         TftpTimeoutCountMax = TftpRRQTimeoutCountMax;
625
626         NetSetTimeout (TftpTimeoutMSecs, TftpTimeout);
627         NetSetHandler (TftpHandler);
628
629         TftpServerPort = WELL_KNOWN_PORT;
630         TftpTimeoutCount = 0;
631         TftpState = STATE_RRQ;
632         /* Use a pseudo-random port unless a specific port is set */
633         TftpOurPort = 1024 + (get_timer(0) % 3072);
634
635 #ifdef CONFIG_TFTP_PORT
636         if ((ep = getenv("tftpdstp")) != NULL) {
637                 TftpServerPort = simple_strtol(ep, NULL, 10);
638         }
639         if ((ep = getenv("tftpsrcp")) != NULL) {
640                 TftpOurPort= simple_strtol(ep, NULL, 10);
641         }
642 #endif
643         TftpBlock = 0;
644
645         /* zero out server ether in case the server ip has changed */
646         memset(NetServerEther, 0, 6);
647         /* Revert TftpBlkSize to dflt */
648         TftpBlkSize = TFTP_BLOCK_SIZE;
649 #ifdef CONFIG_MCAST_TFTP
650         mcast_cleanup();
651 #endif
652 #ifdef CONFIG_TFTP_TSIZE
653         TftpTsize = 0;
654         TftpNumchars = 0;
655 #endif
656
657         TftpSend ();
658 }
659
660 #ifdef CONFIG_MCAST_TFTP
661 /* Credits: atftp project.
662  */
663
664 /* pick up BcastAddr, Port, and whether I am [now] the master-client. *
665  * Frame:
666  *    +-------+-----------+---+-------~~-------+---+
667  *    |  opc  | multicast | 0 | addr, port, mc | 0 |
668  *    +-------+-----------+---+-------~~-------+---+
669  * The multicast addr/port becomes what I listen to, and if 'mc' is '1' then
670  * I am the new master-client so must send ACKs to DataBlocks.  If I am not
671  * master-client, I'm a passive client, gathering what DataBlocks I may and
672  * making note of which ones I got in my bitmask.
673  * In theory, I never go from master->passive..
674  * .. this comes in with pkt already pointing just past opc
675  */
676 static void parse_multicast_oack(char *pkt, int len)
677 {
678  int i;
679  IPaddr_t addr;
680  char *mc_adr, *port,  *mc;
681
682         mc_adr=port=mc=NULL;
683         /* march along looking for 'multicast\0', which has to start at least
684          * 14 bytes back from the end.
685          */
686         for (i=0;i<len-14;i++)
687                 if (strcmp (pkt+i,"multicast") == 0)
688                         break;
689         if (i >= (len-14)) /* non-Multicast OACK, ign. */
690                 return;
691
692         i+=10; /* strlen multicast */
693         mc_adr = pkt+i;
694         for (;i<len;i++) {
695                 if (*(pkt+i) == ',') {
696                         *(pkt+i) = '\0';
697                         if (port) {
698                                 mc = pkt+i+1;
699                                 break;
700                         } else {
701                                 port = pkt+i+1;
702                         }
703                 }
704         }
705         if (!port || !mc_adr || !mc ) return;
706         if (Multicast && MasterClient) {
707                 printf ("I got a OACK as master Client, WRONG!\n");
708                 return;
709         }
710         /* ..I now accept packets destined for this MCAST addr, port */
711         if (!Multicast) {
712                 if (Bitmap) {
713                         printf ("Internal failure! no mcast.\n");
714                         free(Bitmap);
715                         Bitmap=NULL;
716                         ProhibitMcast=1;
717                         return ;
718                 }
719                 /* I malloc instead of pre-declare; so that if the file ends
720                  * up being too big for this bitmap I can retry
721                  */
722                 if (!(Bitmap = malloc (Mapsize))) {
723                         printf ("No Bitmap, no multicast. Sorry.\n");
724                         ProhibitMcast=1;
725                         return;
726                 }
727                 memset (Bitmap,0,Mapsize);
728                 PrevBitmapHole = 0;
729                 Multicast = 1;
730         }
731         addr = string_to_ip(mc_adr);
732         if (Mcast_addr != addr) {
733                 if (Mcast_addr)
734                         eth_mcast_join(Mcast_addr, 0);
735                 if (eth_mcast_join(Mcast_addr=addr, 1)) {
736                         printf ("Fail to set mcast, revert to TFTP\n");
737                         ProhibitMcast=1;
738                         mcast_cleanup();
739                         NetStartAgain();
740                 }
741         }
742         MasterClient = (unsigned char)simple_strtoul((char *)mc,NULL,10);
743         Mcast_port = (unsigned short)simple_strtoul(port,NULL,10);
744         printf ("Multicast: %s:%d [%d]\n", mc_adr, Mcast_port, MasterClient);
745         return;
746 }
747
748 #endif /* Multicast TFTP */