+
+ tftp_state = STATE_RECV_WRQ;
+ net_set_udp_handler(tftp_handler);
+
+ /* zero out server ether in case the server ip has changed */
+ memset(net_server_ethaddr, 0, 6);
+}
+#endif /* CONFIG_CMD_TFTPSRV */
+
+#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;
+ struct in_addr addr;
+ char *mc_adr;
+ char *port;
+ char *mc;
+
+ mc_adr = NULL;
+ port = NULL;
+ 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 (tftp_mcast_active && tftp_mcast_master_client) {
+ printf("I got a OACK as master Client, WRONG!\n");
+ return;
+ }
+ /* ..I now accept packets destined for this MCAST addr, port */
+ if (!tftp_mcast_active) {
+ if (tftp_mcast_bitmap) {
+ printf("Internal failure! no mcast.\n");
+ free(tftp_mcast_bitmap);
+ tftp_mcast_bitmap = NULL;
+ tftp_mcast_disabled = 1;
+ return;
+ }
+ /* I malloc instead of pre-declare; so that if the file ends
+ * up being too big for this bitmap I can retry
+ */
+ tftp_mcast_bitmap = malloc(tftp_mcast_bitmap_size);
+ if (!tftp_mcast_bitmap) {
+ printf("No bitmap, no multicast. Sorry.\n");
+ tftp_mcast_disabled = 1;
+ return;
+ }
+ memset(tftp_mcast_bitmap, 0, tftp_mcast_bitmap_size);
+ tftp_mcast_prev_hole = 0;
+ tftp_mcast_active = 1;
+ }
+ addr = string_to_ip(mc_adr);
+ if (net_mcast_addr.s_addr != addr.s_addr) {
+ if (net_mcast_addr.s_addr)
+ eth_mcast_join(net_mcast_addr, 0);
+ net_mcast_addr = addr;
+ if (eth_mcast_join(net_mcast_addr, 1)) {
+ printf("Fail to set mcast, revert to TFTP\n");
+ tftp_mcast_disabled = 1;
+ mcast_cleanup();
+ net_start_again();
+ }
+ }
+ tftp_mcast_master_client = simple_strtoul((char *)mc, NULL, 10);
+ tftp_mcast_port = (unsigned short)simple_strtoul(port, NULL, 10);
+ printf("Multicast: %s:%d [%d]\n", mc_adr, tftp_mcast_port,
+ tftp_mcast_master_client);
+ return;
+}
+
+#endif /* Multicast TFTP */