+#ifdef CONFIG_MCAST_TFTP
+/* Credits: atftp project.
+ */
+
+/* pick up BcastAddr, Port, and whether I am [now] the master-client. *
+ * Frame:
+ * +-------+-----------+---+-------~~-------+---+
+ * | opc | multicast | 0 | addr, port, mc | 0 |
+ * +-------+-----------+---+-------~~-------+---+
+ * The multicast addr/port becomes what I listen to, and if 'mc' is '1' then
+ * I am the new master-client so must send ACKs to DataBlocks. If I am not
+ * master-client, I'm a passive client, gathering what DataBlocks I may and
+ * making note of which ones I got in my bitmask.
+ * In theory, I never go from master->passive..
+ * .. this comes in with pkt already pointing just past opc
+ */
+static void parse_multicast_oack(char *pkt, int len)
+{
+ int i;
+ IPaddr_t addr;
+ char *mc_adr, *port, *mc;
+
+ mc_adr=port=mc=NULL;
+ /* march along looking for 'multicast\0', which has to start at least
+ * 14 bytes back from the end.
+ */
+ for (i=0;i<len-14;i++)
+ if (strcmp (pkt+i,"multicast") == 0)
+ break;
+ if (i >= (len-14)) /* non-Multicast OACK, ign. */
+ return;
+
+ i+=10; /* strlen multicast */
+ mc_adr = pkt+i;
+ for (;i<len;i++) {
+ if (*(pkt+i) == ',') {
+ *(pkt+i) = '\0';
+ if (port) {
+ mc = pkt+i+1;
+ break;
+ } else {
+ port = pkt+i+1;
+ }
+ }
+ }
+ if (!port || !mc_adr || !mc ) return;
+ if (Multicast && MasterClient) {
+ printf ("I got a OACK as master Client, WRONG!\n");
+ return;
+ }
+ /* ..I now accept packets destined for this MCAST addr, port */
+ if (!Multicast) {
+ if (Bitmap) {
+ printf ("Internal failure! no mcast.\n");
+ free(Bitmap);
+ Bitmap=NULL;
+ ProhibitMcast=1;
+ return ;
+ }
+ /* I malloc instead of pre-declare; so that if the file ends
+ * up being too big for this bitmap I can retry
+ */
+ if (!(Bitmap = malloc (Mapsize))) {
+ printf ("No Bitmap, no multicast. Sorry.\n");
+ ProhibitMcast=1;
+ return;
+ }
+ memset (Bitmap,0,Mapsize);
+ PrevBitmapHole = 0;
+ Multicast = 1;
+ }
+ addr = string_to_ip(mc_adr);
+ if (Mcast_addr != addr) {
+ if (Mcast_addr)
+ eth_mcast_join(Mcast_addr, 0);
+ if (eth_mcast_join(Mcast_addr=addr, 1)) {
+ printf ("Fail to set mcast, revert to TFTP\n");
+ ProhibitMcast=1;
+ mcast_cleanup();
+ NetStartAgain();
+ }
+ }
+ MasterClient = (unsigned char)simple_strtoul((char *)mc,NULL,10);
+ Mcast_port = (unsigned short)simple_strtoul(port,NULL,10);
+ printf ("Multicast: %s:%d [%d]\n", mc_adr, Mcast_port, MasterClient);
+ return;
+}
+
+#endif /* Multicast TFTP */