2 * Copied from Linux Monitor (LiMon) - Networking.
4 * Copyright 1994 - 2000 Neil Russell.
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
8 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
14 * The user interface supports commands for BOOTP, RARP, and TFTP.
15 * Also, we support ARP internally. Depending on available data,
16 * these interact as follows:
20 * Prerequisites: - own ethernet address
21 * We want: - own IP address
22 * - TFTP server IP address
28 * Prerequisites: - own ethernet address
29 * We want: - own IP address
30 * - TFTP server IP address
35 * Prerequisites: - own ethernet address
37 * - TFTP server IP address
38 * We want: - TFTP server ethernet address
43 * Prerequisites: - own ethernet address
44 * We want: - IP, Netmask, ServerIP, Gateway IP
45 * - bootfilename, lease time
50 * Prerequisites: - own ethernet address
52 * - TFTP server IP address
53 * - TFTP server ethernet address
54 * - name of bootfile (if unknown, we use a default name
55 * derived from our own IP address)
56 * We want: - load the boot file
61 * Prerequisites: - own ethernet address
63 * - name of bootfile (if unknown, we use a default name
64 * derived from our own IP address)
65 * We want: - load the boot file
70 * Prerequisites: - own ethernet address
72 * We want: - network time
85 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
89 #include "../httpd/uipopt.h"
90 #include "../httpd/uip.h"
91 #include "../httpd/uip_arp.h"
93 #if (CONFIG_COMMANDS & CFG_CMD_NET)
95 DECLARE_GLOBAL_DATA_PTR;
97 #define ARP_TIMEOUT 5 /* Seconds before trying ARP again */
99 #ifndef CONFIG_NET_RETRY_COUNT
100 #define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
102 #define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
105 unsigned char *webfailsafe_data_pointer = NULL;
106 int webfailsafe_is_running = 0;
107 int webfailsafe_ready_for_upgrade = 0;
108 int webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
110 void NetReceiveHttpd(volatile uchar * inpkt, int len);
112 extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
114 /** BOOTP EXTENTIONS **/
115 IPaddr_t NetOurSubnetMask = 0; /* Our subnet mask (0=unknown) */
116 IPaddr_t NetOurGatewayIP = 0; /* Our gateways IP address */
117 IPaddr_t NetOurDNSIP = 0; /* Our DNS IP address */
119 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
120 IPaddr_t NetOurDNS2IP = 0; /* Our 2nd DNS IP address */
123 char NetOurNISDomain[32] = {0,}; /* Our NIS domain */
124 char NetOurHostName[32] = {0,}; /* Our hostname */
125 char NetOurRootPath[64] = {0,}; /* Our bootpath */
126 ushort NetBootFileSize = 0; /* Our bootfile size in blocks */
127 /** END OF BOOTP EXTENTIONS **/
129 ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
130 uchar NetOurEther[6]; /* Our ethernet address */
131 uchar NetServerEther[6] = {0, 0, 0, 0, 0, 0}; /* Boot server enet address */
132 IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
133 IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */
134 volatile uchar *NetRxPkt; /* Current receive packet */
135 int NetRxPktLen; /* Current rx packet length */
136 unsigned NetIPID; /* IP packet ID */
138 uchar NetBcastAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* Ethernet bcast address */
139 uchar NetEtherNullAddr[6] = {0, 0, 0, 0, 0, 0};
141 int NetState; /* Network loop state */
143 #ifdef CONFIG_NET_MULTI
144 int NetRestartWrap = 0; /* Tried all network devices */
145 static int NetRestarted = 0; /* Network loop restarted */
146 static int NetDevExists = 0; /* At least one device configured */
149 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
150 ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */
151 ushort NetOurNativeVLAN = 0xFFFF; /* ditto */
153 char BootFile[128]; /* Boot File name */
155 #if (CONFIG_COMMANDS & CFG_CMD_PING)
156 IPaddr_t NetPingIP; /* the ip address to ping */
157 static void PingStart(void);
158 #endif /* CFG_CMD_PING */
160 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
161 IPaddr_t NetNtpServerIP; /* NTP server IP address */
162 int NetTimeOffset = 0; /* offset time from UTC */
163 #endif /* CFG_CMD_SNTP */
165 #ifdef CONFIG_NETCONSOLE
167 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
168 #endif /* CONFIG_NETCONSOLE */
170 volatile uchar PktBuf[(PKTBUFSRX + 1) * PKTSIZE_ALIGN + PKTALIGN];
171 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
173 static rxhand_f *packetHandler; /* Current RX packet handler */
174 static thand_f *timeHandler; /* Current timeout handler */
175 static ulong timeStart; /* Time base value */
176 static ulong timeDelta; /* Current timeout value */
177 volatile uchar *NetTxPacket = 0; /* THE transmit packet */
179 static int net_check_prereq(proto_t protocol);
181 /**********************************************************************/
183 IPaddr_t NetArpWaitPacketIP;
184 IPaddr_t NetArpWaitReplyIP;
186 uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */
187 uchar *NetArpWaitTxPacket; /* THE transmit packet */
188 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
189 ulong NetArpWaitTimerStart;
192 int NetArpWaitTxPacketSize;
194 void ArpRequest(void){
200 printf("ARP broadcast %d\n", NetArpWaitTry);
204 pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
208 arp->ar_hrd = htons(ARP_ETHER);
209 arp->ar_pro = htons(PROT_IP);
212 arp->ar_op = htons(ARPOP_REQUEST);
214 memcpy(&arp->ar_data[0], NetOurEther, 6); /* source ET addr */
215 NetWriteIP((uchar *)&arp->ar_data[6], NetOurIP); /* source IP addr */
217 for(i = 10; i < 16; ++i){
218 arp->ar_data[i] = 0; /* dest ET addr = 0 */
221 if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)){
222 if(NetOurGatewayIP == 0){
223 puts("** Warning: gatewayip needed but not set\n");
224 NetArpWaitReplyIP = NetArpWaitPacketIP;
226 NetArpWaitReplyIP = NetOurGatewayIP;
229 NetArpWaitReplyIP = NetArpWaitPacketIP;
232 NetWriteIP((uchar *)&arp->ar_data[16], NetArpWaitReplyIP);
233 (void)eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
236 void ArpTimeoutCheck(void){
240 if(!NetArpWaitPacketIP){
246 /* check for arp timeout */
247 if((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ){
250 if(NetArpWaitTry >= ARP_TIMEOUT_COUNT){
251 puts("## Error: ARP retry count exceeded, starting again\n");
255 NetArpWaitTimerStart = t;
261 /**********************************************************************/
263 * Main network processing loop.
265 int NetLoop(proto_t protocol){
268 #ifdef CONFIG_NET_MULTI
273 /* XXX problem with bss workaround */
274 NetArpWaitPacketMAC = NULL;
275 NetArpWaitTxPacket = NULL;
276 NetArpWaitPacketIP = 0;
277 NetArpWaitReplyIP = 0;
278 NetArpWaitTxPacket = NULL;
284 * Setup packet buffers, aligned correctly.
286 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
287 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
289 for(i = 0; i < PKTBUFSRX; i++){
290 NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
294 if(!NetArpWaitTxPacket){
295 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
296 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
297 NetArpWaitTxPacketSize = 0;
300 if(eth_is_on_demand_init() || protocol != NETCONS){
302 #ifdef CONFIG_NET_MULTI
310 eth_init_state_only(bd);
316 #ifdef CONFIG_NET_MULTI
317 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
319 memcpy(NetOurEther, bd->bi_enetaddr, 6);
322 NetState = NETLOOP_CONTINUE;
325 * Start the ball rolling with the given start function. From
326 * here on, this code is a state machine driven by received
327 * packets and timer events.
331 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
334 #if (CONFIG_COMMANDS & CFG_CMD_PING)
337 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
342 NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
344 NetOurGatewayIP = getenv_IPaddr("gatewayip");
345 NetOurSubnetMask = getenv_IPaddr("netmask");
346 NetOurVLAN = getenv_VLAN("vlan");
347 NetOurNativeVLAN = getenv_VLAN("nvlan");
350 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
355 NetServerIP = getenv_IPaddr("serverip");
357 #if (CONFIG_COMMANDS & CFG_CMD_PING)
362 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
376 * initialize our IP addr to 0 in order to accept ANY
377 * IP addr assigned to us by the BOOTP / RARP server
380 NetServerIP = getenv_IPaddr("serverip");
381 NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */
382 NetOurNativeVLAN = getenv_VLAN("nvlan");
385 NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */
386 NetOurNativeVLAN = getenv_VLAN("nvlan");
393 switch(net_check_prereq(protocol)){
395 /* network not configured */
399 #ifdef CONFIG_NET_MULTI
401 /* network device not configured */
403 #endif /* CONFIG_NET_MULTI */
406 #ifdef CONFIG_NET_MULTI
411 /* always use ARP to get server ethernet address */
415 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
417 /* Start with a clean slate... */
420 NetServerIP = getenv_IPaddr("serverip");
421 DhcpRequest(); /* Basically same as BOOTP */
424 #endif /* CFG_CMD_DHCP */
426 #if (CONFIG_COMMANDS & CFG_CMD_PING)
432 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
438 #ifdef CONFIG_NETCONSOLE
444 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
454 NetBootFileXferSize = 0;
459 * Main packet reception loop. Loop receiving packets until
460 * someone sets `NetState' to a state that terminates.
464 * Check the ethernet for a new packet. The ethernet
465 * receive routine will process it.
470 * Abort if ctrl-c was pressed.
475 /* Invalidate the last protocol */
476 eth_set_last_protocol(BOOTP);
485 * Check for a timeout, and run the timeout handler
488 if(timeHandler && ((get_timer(0) - timeStart) > timeDelta)){
491 timeHandler = (thand_f *)0;
497 case NETLOOP_RESTART:
498 #ifdef CONFIG_NET_MULTI
503 case NETLOOP_SUCCESS:
504 if(NetBootFileXferSize > 0){
506 printf("\nBytes transferred: %ld (0x%lx)\n", NetBootFileXferSize, NetBootFileXferSize);
508 sprintf(buf, "%lx", NetBootFileXferSize);
509 setenv("filesize", buf);
511 sprintf(buf, "%lX", (unsigned long)load_addr);
512 setenv("fileaddr", buf);
515 if(protocol != NETCONS){
518 eth_halt_state_only();
521 eth_set_last_protocol(protocol);
523 return(NetBootFileXferSize);
526 /* Invalidate the last protocol */
527 eth_set_last_protocol(BOOTP);
533 /**********************************************************************/
535 static void startAgainTimeout(void){
536 NetState = NETLOOP_RESTART;
539 static void startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
540 /* Totally ignore the packet */
543 void NetStartAgain(void){
545 int noretry = 0, once = 0;
548 if((nretry = getenv("netretry")) != NULL){
549 noretry = (strcmp(nretry, "no") == 0);
550 once = (strcmp(nretry, "once") == 0);
555 NetState = NETLOOP_FAIL;
559 #ifndef CONFIG_NET_MULTI
560 NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
561 NetSetHandler(startAgainHandler);
562 #else /* !CONFIG_NET_MULTI*/
564 eth_try_another(!NetRestarted);
569 if(NetDevExists && !once){
570 NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
571 NetSetHandler(startAgainHandler);
573 NetState = NETLOOP_FAIL;
576 NetState = NETLOOP_RESTART;
578 #endif /* CONFIG_NET_MULTI */
581 /**********************************************************************/
586 void NetSetHandler(rxhand_f * f){
590 void NetSetTimeout(ulong iv, thand_f * f){
592 timeHandler = (thand_f *)0;
595 timeStart = get_timer(0);
600 void NetSendPacket(volatile uchar * pkt, int len){
601 (void)eth_send(pkt, len);
604 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len){
607 /* convert to new style broadcast */
612 /* if broadcast, make the ether address a broadcast and don't do ARP */
613 if(dest == 0xFFFFFFFF){
614 ether = NetBcastAddr;
617 /* if MAC address was not discovered yet, save the packet and do an ARP request */
618 if(memcmp(ether, NetEtherNullAddr, 6) == 0){
621 printf("Sending ARP for %08lx\n", dest);
623 NetArpWaitPacketIP = dest;
624 NetArpWaitPacketMAC = ether;
626 pkt = NetArpWaitTxPacket;
627 pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
629 NetSetIP(pkt, dest, dport, sport, len);
630 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
632 /* size of the waiting packet */
633 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
635 /* and do the ARP request */
637 NetArpWaitTimerStart = get_timer(0);
640 return(1); /* waiting */
644 printf("Sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n", dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
647 pkt = (uchar *)NetTxPacket;
648 pkt += NetSetEther(pkt, ether, PROT_IP);
649 NetSetIP(pkt, dest, dport, sport, len);
650 (void)eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
652 return(0); /* transmitted */
655 #if (CONFIG_COMMANDS & CFG_CMD_PING)
656 static ushort PingSeqNo;
664 /* XXX always send arp request */
666 memcpy(mac, NetEtherNullAddr, 6);
669 printf("Sending ARP for %08lx\n", NetPingIP);
672 NetArpWaitPacketIP = NetPingIP;
673 NetArpWaitPacketMAC = mac;
675 pkt = NetArpWaitTxPacket;
676 pkt += NetSetEther(pkt, mac, PROT_IP);
678 ip = (volatile IP_t *)pkt;
681 * Construct an IP and ICMP header. (need to set no fragment bit - XXX)
683 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
685 ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8);
686 ip->ip_id = htons(NetIPID++);
687 ip->ip_off = htons(0x4000); /* No fragmentation */
689 ip->ip_p = 0x01; /* ICMP */
692 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
693 NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */
695 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
697 s = &ip->udp_src; /* XXX ICMP starts here */
699 s[0] = htons(0x0800); /* echo-request, code */
700 s[1] = 0; /* checksum */
701 s[2] = 0; /* identifier */
702 s[3] = htons(PingSeqNo++); /* sequence number */
703 s[1] = ~NetCksum((uchar *)s, 8/2);
705 /* size of the waiting packet */
706 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
708 /* and do the ARP request */
710 NetArpWaitTimerStart = get_timer(0);
713 return(1); /* waiting */
716 static void PingTimeout(void){
718 NetState = NETLOOP_FAIL; /* we did not get the reply */
721 static void PingHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
723 volatile IP_t *ip = (volatile IP_t *)pkt;
725 tmp = NetReadIP((void *)&ip->ip_src);
727 if(tmp != NetPingIP){
731 NetState = NETLOOP_SUCCESS;
734 static void PingStart(void){
736 #if defined(CONFIG_NET_MULTI)
737 printf("Using %s device\n", eth_get_name());
738 #endif /* CONFIG_NET_MULTI */
740 NetSetTimeout(10 * CFG_HZ, PingTimeout);
741 NetSetHandler(PingHandler);
745 #endif /* CFG_CMD_PING */
747 void NetReceive(volatile uchar * inpkt, int len){
754 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
757 printf("Packet received\n");
760 if(webfailsafe_is_running){
761 NetReceiveHttpd(inpkt, len);
767 et = (Ethernet_t *)inpkt;
769 /* too small packet? */
770 if(len < ETHER_HDR_SIZE){
774 myvlanid = ntohs(NetOurVLAN);
776 if(myvlanid == (ushort)-1){
777 myvlanid = VLAN_NONE;
780 mynvlanid = ntohs(NetOurNativeVLAN);
782 if(mynvlanid == (ushort)-1){
783 mynvlanid = VLAN_NONE;
786 x = ntohs(et->et_protlen);
789 printf("Packet received\n");
794 * Got a 802 packet. Check the other protocol field.
796 x = ntohs(et->et_prot);
798 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
799 len -= E802_HDR_SIZE;
801 } else if(x != PROT_VLAN){ /* normal packet */
802 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
803 len -= ETHER_HDR_SIZE;
805 } else { /* VLAN packet */
806 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
809 printf("VLAN packet received\n");
811 /* too small packet? */
812 if(len < VLAN_ETHER_HDR_SIZE){
816 /* if no VLAN active */
817 if((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE){
821 cti = ntohs(vet->vet_tag);
822 vlanid = cti & VLAN_IDMASK;
823 x = ntohs(vet->vet_type);
825 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
826 len -= VLAN_ETHER_HDR_SIZE;
830 printf("Receive from protocol 0x%x\n", x);
833 if((myvlanid & VLAN_IDMASK) != VLAN_NONE){
834 if(vlanid == VLAN_NONE){
835 vlanid = (mynvlanid & VLAN_IDMASK);
838 if(vlanid != (myvlanid & VLAN_IDMASK)){
847 * We have to deal with two types of ARP packets:
848 * - REQUEST packets will be answered by sending our
849 * IP address - if we know it.
850 * - REPLY packates are expected only after we asked
851 * for the TFTP server's or the gateway's ethernet
852 * address; so if we receive such a packet, we set
853 * the server ethernet address
860 if(len < ARP_HDR_SIZE){
861 printf("## Error: bad length %d < %d\n", len, ARP_HDR_SIZE);
865 if(ntohs(arp->ar_hrd) != ARP_ETHER){
869 if(ntohs(arp->ar_pro) != PROT_IP){
873 if(arp->ar_hln != 6){
877 if(arp->ar_pln != 4){
885 if(NetReadIP(&arp->ar_data[16]) != NetOurIP){
889 switch(ntohs(arp->ar_op)){
890 case ARPOP_REQUEST: /* reply with our IP address */
892 puts("Got ARP REQUEST, return our IP\n");
895 pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
896 arp->ar_op = htons(ARPOP_REPLY);
897 memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
898 NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
899 memcpy(&arp->ar_data[0], NetOurEther, 6);
900 NetCopyIP(&arp->ar_data[6], &NetOurIP);
901 (void)eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
905 case ARPOP_REPLY: /* arp reply */
906 /* are we waiting for a reply */
907 if(!NetArpWaitPacketIP || !NetArpWaitPacketMAC){
911 printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", arp->ar_data[0], arp->ar_data[1], arp->ar_data[2], arp->ar_data[3], arp->ar_data[4], arp->ar_data[5]);
914 tmp = NetReadIP(&arp->ar_data[6]);
916 /* matched waiting packet's address */
917 if(tmp == NetArpWaitReplyIP){
921 /* save address for later use */
922 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
924 #ifdef CONFIG_NETCONSOLE
925 (*packetHandler)(0,0,0,0);
927 /* modify header, and transmit it */
928 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
929 (void)eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
931 /* no arp request pending now */
932 NetArpWaitPacketIP = 0;
933 NetArpWaitTxPacketSize = 0;
934 NetArpWaitPacketMAC = NULL;
941 printf("## Error: unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
952 if(len < ARP_HDR_SIZE){
953 printf("## Error: bad length %d < %d\n", len, ARP_HDR_SIZE);
957 if((ntohs(arp->ar_op) != RARPOP_REPLY) || (ntohs(arp->ar_hrd) != ARP_ETHER) || (ntohs(arp->ar_pro) != PROT_IP) || (arp->ar_hln != 6) || (arp->ar_pln != 4)){
958 puts("## Error: invalid RARP header\n");
960 NetCopyIP(&NetOurIP, &arp->ar_data[16]);
961 if(NetServerIP == 0){
962 NetCopyIP(&NetServerIP, &arp->ar_data[6]);
964 memcpy(NetServerEther, &arp->ar_data[0], 6);
965 (*packetHandler)(0, 0, 0, 0);
974 if(len < IP_HDR_SIZE){
975 debug("## Error: len bad %d < %d\n", len, IP_HDR_SIZE);
979 if(len < ntohs(ip->ip_len)){
980 printf("## Error: len bad %d < %d\n", len, ntohs(ip->ip_len));
984 len = ntohs(ip->ip_len);
986 printf("Len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
988 if((ip->ip_hl_v & 0xf0) != 0x40){
992 if(ip->ip_off & htons(0x1fff)){ /* Can't deal w/ fragments */
996 if(!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)){
998 puts("\n## Error: checksum bad\n");
1003 tmp = NetReadIP(&ip->ip_dst);
1005 if(NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF){
1009 * watch for ICMP host redirects
1011 * There is no real handler code (yet). We just watch
1012 * for ICMP host redirect messages. In case anybody
1013 * sees these messages: please contact me
1014 * (wd@denx.de), or - even better - send me the
1015 * necessary fixes :-)
1017 * Note: in all cases where I have seen this so far
1018 * it was a problem with the router configuration,
1019 * for instance when a router was configured in the
1020 * BOOTP reply, but the TFTP server was on the same
1021 * subnet. So this is probably a warning that your
1022 * configuration might be wrong. But I'm not really
1023 * sure if there aren't any other situations.
1025 if(ip->ip_p == IPPROTO_ICMP){
1026 ICMP_t *icmph = (ICMP_t *) & (ip->udp_src);
1028 switch(icmph->type){
1030 if(icmph->code != ICMP_REDIR_HOST){
1034 puts(" ICMP Host Redirect to ");
1035 print_IPaddr(icmph->un.gateway);
1039 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1040 case ICMP_ECHO_REPLY:
1042 * IP header OK. Pass the packet to the current handler.
1044 /* XXX point to ip packet */
1045 (*packetHandler)((uchar *)ip, 0, 0, 0);
1051 } else if(ip->ip_p != IPPROTO_UDP){ /* Only UDP packets */
1055 #ifdef CONFIG_UDP_CHECKSUM
1056 if(ip->udp_xsum != 0){
1062 xsum += (ntohs(ip->udp_len));
1063 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1064 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
1065 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1066 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
1068 sumlen = ntohs(ip->udp_len);
1069 sumptr = (ushort *)&(ip->udp_src);
1074 sumdata = *sumptr++;
1075 xsum += ntohs(sumdata);
1082 sumdata = *(unsigned char *)sumptr;
1083 sumdata = (sumdata << 8) & 0xff00;
1087 while((xsum >> 16) != 0){
1088 xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
1091 if((xsum != 0x00000000) && (xsum != 0x0000ffff)){
1092 printf("## Error: UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
1098 #ifdef CONFIG_NETCONSOLE
1099 nc_input_packet((uchar *)ip +IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8);
1102 * IP header OK. Pass the packet to the current handler.
1104 (*packetHandler)((uchar *)ip + IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8);
1109 /**********************************************************************/
1111 static int net_check_prereq(proto_t protocol){
1114 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1117 puts("## Error: ping address not given\n");
1122 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
1124 if(NetNtpServerIP == 0){
1125 puts("## Error: NTP server address not given\n");
1130 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
1135 if(NetServerIP == 0){
1136 puts("## Error: serverip not set\n");
1139 #if (CONFIG_COMMANDS & (CFG_CMD_PING | CFG_CMD_SNTP))
1143 puts("## Error: ipaddr not set\n");
1152 if(memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0){
1153 #ifdef CONFIG_NET_MULTI
1154 extern int eth_get_dev_index(void);
1155 int num = eth_get_dev_index();
1159 puts("## Error: no ethernet found\n");
1162 puts("## Error: ethaddr not set\n");
1165 printf("## Error: eth%daddr not set\n", num);
1172 puts("## Error: ethaddr not set\n");
1183 /**********************************************************************/
1185 int NetCksumOk(uchar * ptr, int len){
1186 return(!((NetCksum(ptr, len) + 1) & 0xfffe));
1189 unsigned NetCksum(uchar * ptr, int len){
1191 ushort *p = (ushort *)ptr;
1199 xsum = (xsum & 0xffff) + (xsum >> 16);
1200 xsum = (xsum & 0xffff) + (xsum >> 16);
1202 return(xsum & 0xffff);
1205 int NetEthHdrSize(void){
1208 myvlanid = ntohs(NetOurVLAN);
1210 if(myvlanid == (ushort) -1){
1211 myvlanid = VLAN_NONE;
1214 return(((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE);
1217 int NetSetEther(volatile uchar * xet, uchar * addr, uint prot){
1218 Ethernet_t *et = (Ethernet_t *)xet;
1221 myvlanid = ntohs(NetOurVLAN);
1223 if(myvlanid == (ushort) -1){
1224 myvlanid = VLAN_NONE;
1227 memcpy(et->et_dest, addr, 6);
1228 memcpy(et->et_src, NetOurEther, 6);
1230 if((myvlanid & VLAN_IDMASK) == VLAN_NONE){
1231 et->et_protlen = htons(prot);
1233 return(ETHER_HDR_SIZE);
1235 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1237 vet->vet_vlan_type = htons(PROT_VLAN);
1238 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1239 vet->vet_type = htons(prot);
1240 return(VLAN_ETHER_HDR_SIZE);
1244 void NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len){
1245 volatile IP_t *ip = (IP_t *)xip;
1248 * If the data is an odd number of bytes, zero the
1249 * byte after the last byte so that the checksum
1253 xip[IP_HDR_SIZE + len] = 0;
1257 * Construct an IP and UDP header.
1258 * (need to set no fragment bit - XXX)
1260 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
1262 ip->ip_len = htons(IP_HDR_SIZE + len);
1263 ip->ip_id = htons(NetIPID++);
1264 ip->ip_off = htons(0x4000); /* No fragmentation */
1266 ip->ip_p = 17; /* UDP */
1269 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1270 NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
1272 ip->udp_src = htons(sport);
1273 ip->udp_dst = htons(dport);
1274 ip->udp_len = htons(8 + len);
1276 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1279 void copy_filename(char *dst, char *src, int size){
1280 if(*src && (*src == '"')){
1285 while((--size > 0) && *src && (*src != '"')){
1291 #endif /* CFG_CMD_NET */
1293 void ip_to_string(IPaddr_t x, char *s){
1295 sprintf(s, "%d.%d.%d.%d", (int)((x >> 24) & 0xff), (int)((x >> 16) & 0xff), (int)((x >> 8) & 0xff), (int)((x >> 0) & 0xff));
1298 IPaddr_t string_to_ip(char *s){
1307 for(addr = 0, i = 0; i < 4; ++i){
1308 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1310 addr |= (val & 0xFF);
1312 s = (*e) ? e + 1 : e;
1316 return(htonl(addr));
1319 void VLAN_to_string(ushort x, char *s){
1322 if(x == (ushort) -1){
1329 sprintf(s, "%d", x & VLAN_IDMASK);
1333 ushort string_to_VLAN(char *s){
1337 return(htons(VLAN_NONE));
1340 if(*s < '0' || *s > '9'){
1343 id = (ushort) simple_strtoul(s, NULL, 10);
1349 void print_IPaddr(IPaddr_t x){
1352 ip_to_string(x, tmp);
1357 IPaddr_t getenv_IPaddr(char *var){
1358 return(string_to_ip(getenv(var)));
1361 ushort getenv_VLAN(char *var){
1362 return(string_to_VLAN(getenv(var)));
1366 /**********************************************************************************
1370 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
1372 void NetSendHttpd(void){
1373 volatile uchar *tmpbuf = NetTxPacket;
1376 for(i = 0; i < 40 + UIP_LLH_LEN; i++){
1377 tmpbuf[i] = uip_buf[i];
1380 for(; i < uip_len; i++){
1381 tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
1384 eth_send(NetTxPacket, uip_len);
1387 void NetReceiveHttpd(volatile uchar * inpkt, int len){
1388 memcpy(uip_buf, (const void *)inpkt, len);
1391 if(BUF->type == htons(UIP_ETHTYPE_IP)){
1399 } else if(BUF->type == htons(UIP_ETHTYPE_ARP)){
1408 /* *************************************
1410 * HTTP web server for web failsafe mode
1412 ***************************************/
1413 int NetLoopHttpd(void){
1415 unsigned short int ip[2];
1416 unsigned char ethinit_attempt = 0;
1417 struct uip_eth_addr eaddr;
1419 #ifdef CONFIG_NET_MULTI
1424 /* XXX problem with bss workaround */
1425 NetArpWaitPacketMAC = NULL;
1426 NetArpWaitTxPacket = NULL;
1427 NetArpWaitPacketIP = 0;
1428 NetArpWaitReplyIP = 0;
1429 NetArpWaitTxPacket = NULL;
1434 // Setup packet buffers, aligned correctly.
1435 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
1436 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
1438 for(i = 0; i < PKTBUFSRX; i++){
1439 NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
1443 if(!NetArpWaitTxPacket){
1444 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
1445 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
1446 NetArpWaitTxPacketSize = 0;
1454 #ifdef CONFIG_NET_MULTI
1458 while(ethinit_attempt < 10){
1460 ethinit_attempt = 0;
1469 if(ethinit_attempt > 0){
1471 printf("## Error: couldn't initialize eth (cable disconnected?)!\n\n");
1476 #ifdef CONFIG_NET_MULTI
1477 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
1479 eth_getenv_enetaddr("ethaddr", NetOurEther);
1482 eaddr.addr[0] = NetOurEther[0];
1483 eaddr.addr[1] = NetOurEther[1];
1484 eaddr.addr[2] = NetOurEther[2];
1485 eaddr.addr[3] = NetOurEther[3];
1486 eaddr.addr[4] = NetOurEther[4];
1487 eaddr.addr[5] = NetOurEther[5];
1490 uip_setethaddr(eaddr);
1492 // set ip and other addresses
1493 // TODO: do we need this with uIP stack?
1494 NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
1496 NetOurGatewayIP = getenv_IPaddr("gatewayip");
1497 NetOurSubnetMask = getenv_IPaddr("netmask");
1498 NetOurVLAN = getenv_VLAN("vlan");
1499 NetOurNativeVLAN = getenv_VLAN("nvlan");
1502 printf("HTTP server is starting at IP: %ld.%ld.%ld.%ld\n", (bd->bi_ip_addr & 0xff000000) >> 24, (bd->bi_ip_addr & 0x00ff0000) >> 16, (bd->bi_ip_addr & 0x0000ff00) >> 8, (bd->bi_ip_addr & 0x000000ff));
1506 // set local host ip address
1507 ip[0] = ((bd->bi_ip_addr & 0xFFFF0000) >> 16);
1508 ip[1] = (bd->bi_ip_addr & 0x0000FFFF);
1510 uip_sethostaddr(ip);
1512 // set network mask (255.255.255.0 -> local network)
1513 ip[0] = ((0xFFFFFF00 & 0xFFFF0000) >> 16);
1514 ip[1] = (0xFFFFFF00 & 0x0000FFFF);
1518 // should we also set default router ip address?
1521 // show current progress of the process
1522 do_http_progress(WEBFAILSAFE_PROGRESS_START);
1524 webfailsafe_is_running = 1;
1530 * Check the ethernet for a new packet.
1531 * The ethernet receive routine will process it.
1537 // if CTRL+C was pressed -> return!
1541 // reset global variables to default state
1542 webfailsafe_is_running = 0;
1543 webfailsafe_ready_for_upgrade = 0;
1544 webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
1546 /* Invalidate the last protocol */
1547 eth_set_last_protocol(BOOTP);
1549 printf("\nWeb failsafe mode aborted!\n\n");
1553 // until upload is not completed, get back to the start of the loop
1554 if(!webfailsafe_ready_for_upgrade){
1558 // stop eth interface
1562 do_http_progress(WEBFAILSAFE_PROGRESS_UPLOAD_READY);
1564 // try to make upgrade!
1565 if(do_http_upgrade(NetBootFileXferSize, webfailsafe_upgrade_type) >= 0){
1568 do_http_progress(WEBFAILSAFE_PROGRESS_UPGRADE_READY);
1572 /* reset the board */
1573 do_reset(NULL, 0, 0, NULL);
1578 // reset global variables to default state
1579 webfailsafe_is_running = 0;
1580 webfailsafe_ready_for_upgrade = 0;
1581 webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
1583 NetBootFileXferSize = 0;
1585 do_http_progress(WEBFAILSAFE_PROGRESS_UPGRADE_FAILED);