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
83 #if defined(CONFIG_CMD_HTTPD)
87 #if defined(CONFIG_CMD_SNTP)
91 #if defined(CONFIG_CMD_HTTPD)
92 #include "../httpd/uipopt.h"
93 #include "../httpd/uip.h"
94 #include "../httpd/uip_arp.h"
97 #if defined(CONFIG_CMD_NET)
99 DECLARE_GLOBAL_DATA_PTR;
101 #define ARP_TIMEOUT 5 /* Seconds before trying ARP again */
103 #ifndef CONFIG_NET_RETRY_COUNT
104 #define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
106 #define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
109 #if defined(CONFIG_CMD_HTTPD)
110 unsigned char *webfailsafe_data_pointer = NULL;
111 int webfailsafe_is_running = 0;
112 int webfailsafe_ready_for_upgrade = 0;
113 int webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
115 void NetReceiveHttpd(volatile uchar * inpkt, int len);
117 extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
120 /** BOOTP EXTENTIONS **/
121 IPaddr_t NetOurSubnetMask = 0; /* Our subnet mask (0=unknown) */
122 IPaddr_t NetOurGatewayIP = 0; /* Our gateways IP address */
123 IPaddr_t NetOurDNSIP = 0; /* Our DNS IP address */
125 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
126 IPaddr_t NetOurDNS2IP = 0; /* Our 2nd DNS IP address */
129 char NetOurNISDomain[32] = {0,}; /* Our NIS domain */
130 char NetOurHostName[32] = {0,}; /* Our hostname */
131 char NetOurRootPath[64] = {0,}; /* Our bootpath */
132 ushort NetBootFileSize = 0; /* Our bootfile size in blocks */
133 /** END OF BOOTP EXTENTIONS **/
135 ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
136 uchar NetOurEther[6]; /* Our ethernet address */
137 uchar NetServerEther[6] = {0, 0, 0, 0, 0, 0}; /* Boot server enet address */
138 IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
139 IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */
140 volatile uchar *NetRxPkt; /* Current receive packet */
141 int NetRxPktLen; /* Current rx packet length */
142 unsigned NetIPID; /* IP packet ID */
144 uchar NetBcastAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* Ethernet bcast address */
145 uchar NetEtherNullAddr[6] = {0, 0, 0, 0, 0, 0};
147 int NetState; /* Network loop state */
149 #ifdef CONFIG_NET_MULTI
150 int NetRestartWrap = 0; /* Tried all network devices */
151 static int NetRestarted = 0; /* Network loop restarted */
152 static int NetDevExists = 0; /* At least one device configured */
155 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
156 ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */
157 ushort NetOurNativeVLAN = 0xFFFF; /* ditto */
159 char BootFile[128]; /* Boot File name */
161 #if defined(CONFIG_CMD_PING)
162 IPaddr_t NetPingIP; /* the ip address to ping */
163 static void PingStart(void);
164 #endif /* CONFIG_CMD_PING */
166 #if defined(CONFIG_CMD_SNTP)
167 IPaddr_t NetNtpServerIP; /* NTP server IP address */
168 int NetTimeOffset = 0; /* offset time from UTC */
169 #endif /* CONFIG_CMD_SNTP */
171 #ifdef CONFIG_NETCONSOLE
173 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
174 #endif /* CONFIG_NETCONSOLE */
176 volatile uchar PktBuf[(PKTBUFSRX + 1) * PKTSIZE_ALIGN + PKTALIGN];
177 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
179 static rxhand_f *packetHandler; /* Current RX packet handler */
180 static thand_f *timeHandler; /* Current timeout handler */
181 static ulong timeStart; /* Time base value */
182 static ulong timeDelta; /* Current timeout value */
183 volatile uchar *NetTxPacket = 0; /* THE transmit packet */
185 static int net_check_prereq(proto_t protocol);
187 /**********************************************************************/
189 IPaddr_t NetArpWaitPacketIP;
190 IPaddr_t NetArpWaitReplyIP;
192 uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */
193 uchar *NetArpWaitTxPacket; /* THE transmit packet */
194 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
195 ulong NetArpWaitTimerStart;
198 int NetArpWaitTxPacketSize;
200 void ArpRequest(void){
206 printf("ARP broadcast %d\n", NetArpWaitTry);
210 pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
214 arp->ar_hrd = htons(ARP_ETHER);
215 arp->ar_pro = htons(PROT_IP);
218 arp->ar_op = htons(ARPOP_REQUEST);
220 memcpy(&arp->ar_data[0], NetOurEther, 6); /* source ET addr */
221 NetWriteIP((uchar *)&arp->ar_data[6], NetOurIP); /* source IP addr */
223 for(i = 10; i < 16; ++i){
224 arp->ar_data[i] = 0; /* dest ET addr = 0 */
227 if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)){
228 if(NetOurGatewayIP == 0){
229 printf_wrn("gatewayip needed but not set\n");
230 NetArpWaitReplyIP = NetArpWaitPacketIP;
232 NetArpWaitReplyIP = NetOurGatewayIP;
235 NetArpWaitReplyIP = NetArpWaitPacketIP;
238 NetWriteIP((uchar *)&arp->ar_data[16], NetArpWaitReplyIP);
239 (void)eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
242 void ArpTimeoutCheck(void){
246 if(!NetArpWaitPacketIP){
252 /* check for arp timeout */
253 if((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ){
256 if(NetArpWaitTry >= ARP_TIMEOUT_COUNT){
257 printf_err("ARP retry count exceeded, starting again\n");
261 NetArpWaitTimerStart = t;
267 /**********************************************************************/
269 * Main network processing loop.
271 int NetLoop(proto_t protocol){
274 #ifdef CONFIG_NET_MULTI
279 /* XXX problem with bss workaround */
280 NetArpWaitPacketMAC = NULL;
281 NetArpWaitTxPacket = NULL;
282 NetArpWaitPacketIP = 0;
283 NetArpWaitReplyIP = 0;
284 NetArpWaitTxPacket = NULL;
290 * Setup packet buffers, aligned correctly.
292 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
293 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
295 for(i = 0; i < PKTBUFSRX; i++){
296 NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
300 if(!NetArpWaitTxPacket){
301 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
302 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
303 NetArpWaitTxPacketSize = 0;
306 if(eth_is_on_demand_init() || protocol != NETCONS){
308 #ifdef CONFIG_NET_MULTI
316 eth_init_state_only(bd);
322 #ifdef CONFIG_NET_MULTI
323 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
325 memcpy(NetOurEther, bd->bi_enetaddr, 6);
328 NetState = NETLOOP_CONTINUE;
331 * Start the ball rolling with the given start function. From
332 * here on, this code is a state machine driven by received
333 * packets and timer events.
337 #if defined(CONFIG_CMD_NFS)
340 #if defined(CONFIG_CMD_PING)
343 #if defined(CONFIG_CMD_SNTP)
349 NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
351 NetOurGatewayIP = getenv_IPaddr("gatewayip");
352 NetOurSubnetMask = getenv_IPaddr("netmask");
353 NetOurVLAN = getenv_VLAN("vlan");
354 NetOurNativeVLAN = getenv_VLAN("nvlan");
357 #if defined(CONFIG_CMD_NFS)
363 NetServerIP = getenv_IPaddr("serverip");
365 #if defined(CONFIG_CMD_PING)
370 #if defined(CONFIG_CMD_SNTP)
384 * initialize our IP addr to 0 in order to accept ANY
385 * IP addr assigned to us by the BOOTP / RARP server
388 NetServerIP = getenv_IPaddr("serverip");
389 NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */
390 NetOurNativeVLAN = getenv_VLAN("nvlan");
393 NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */
394 NetOurNativeVLAN = getenv_VLAN("nvlan");
401 switch(net_check_prereq(protocol)){
403 /* network not configured */
407 #ifdef CONFIG_NET_MULTI
409 /* network device not configured */
411 #endif /* CONFIG_NET_MULTI */
414 #ifdef CONFIG_NET_MULTI
417 NetBootFileXferSize = 0;
422 /* always use ARP to get server ethernet address */
426 #if defined(CONFIG_CMD_DHCP)
428 /* Start with a clean slate... */
431 NetServerIP = getenv_IPaddr("serverip");
432 DhcpRequest(); /* Basically same as BOOTP */
435 #endif /* CONFIG_CMD_DHCP */
437 #if defined(CONFIG_CMD_PING)
443 #if defined(CONFIG_CMD_NFS)
449 #ifdef CONFIG_NETCONSOLE
455 #if defined(CONFIG_CMD_SNTP)
469 * Main packet reception loop. Loop receiving packets until
470 * someone sets `NetState' to a state that terminates.
474 * Check the ethernet for a new packet. The ethernet
475 * receive routine will process it.
480 * Abort if ctrl-c was pressed.
485 /* Invalidate the last protocol */
486 eth_set_last_protocol(BOOTP);
495 * Check for a timeout, and run the timeout handler
498 if(timeHandler && ((get_timer(0) - timeStart) > timeDelta)){
501 timeHandler = (thand_f *)0;
507 case NETLOOP_RESTART:
508 #ifdef CONFIG_NET_MULTI
513 case NETLOOP_SUCCESS:
514 if(NetBootFileXferSize > 0){
516 printf("\nBytes transferred: %ld (0x%lx)\n", NetBootFileXferSize, NetBootFileXferSize);
518 sprintf(buf, "0x%lX", NetBootFileXferSize);
519 setenv("filesize", buf);
521 sprintf(buf, "0x%lX", (unsigned long)load_addr);
522 setenv("fileaddr", buf);
525 if(protocol != NETCONS){
528 eth_halt_state_only();
531 eth_set_last_protocol(protocol);
533 return(NetBootFileXferSize);
536 /* Invalidate the last protocol */
537 eth_set_last_protocol(BOOTP);
543 /**********************************************************************/
545 static void startAgainTimeout(void){
546 NetState = NETLOOP_RESTART;
549 static void startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
550 /* Totally ignore the packet */
553 void NetStartAgain(void){
555 int noretry = 0, once = 0;
558 if((nretry = getenv("netretry")) != NULL){
559 noretry = (strcmp(nretry, "no") == 0);
560 once = (strcmp(nretry, "once") == 0);
565 NetState = NETLOOP_FAIL;
569 #ifndef CONFIG_NET_MULTI
570 NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
571 NetSetHandler(startAgainHandler);
572 #else /* !CONFIG_NET_MULTI*/
574 eth_try_another(!NetRestarted);
579 if(NetDevExists && !once){
580 NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
581 NetSetHandler(startAgainHandler);
583 NetState = NETLOOP_FAIL;
586 NetState = NETLOOP_RESTART;
588 #endif /* CONFIG_NET_MULTI */
591 /**********************************************************************/
596 void NetSetHandler(rxhand_f * f){
600 void NetSetTimeout(ulong iv, thand_f * f){
602 timeHandler = (thand_f *)0;
605 timeStart = get_timer(0);
610 void NetSendPacket(volatile uchar * pkt, int len){
611 (void)eth_send(pkt, len);
614 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len){
617 /* convert to new style broadcast */
622 /* if broadcast, make the ether address a broadcast and don't do ARP */
623 if(dest == 0xFFFFFFFF){
624 ether = NetBcastAddr;
627 /* if MAC address was not discovered yet, save the packet and do an ARP request */
628 if(memcmp(ether, NetEtherNullAddr, 6) == 0){
631 printf("Sending ARP for %08lx\n", dest);
633 NetArpWaitPacketIP = dest;
634 NetArpWaitPacketMAC = ether;
636 pkt = NetArpWaitTxPacket;
637 pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
639 NetSetIP(pkt, dest, dport, sport, len);
640 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
642 /* size of the waiting packet */
643 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
645 /* and do the ARP request */
647 NetArpWaitTimerStart = get_timer(0);
650 return(1); /* waiting */
654 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]);
657 pkt = (uchar *)NetTxPacket;
658 pkt += NetSetEther(pkt, ether, PROT_IP);
659 NetSetIP(pkt, dest, dport, sport, len);
660 (void)eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
662 return(0); /* transmitted */
665 #if defined(CONFIG_CMD_PING)
666 static ushort PingSeqNo;
674 /* XXX always send arp request */
676 memcpy(mac, NetEtherNullAddr, 6);
679 printf("Sending ARP for %08lx\n", NetPingIP);
682 NetArpWaitPacketIP = NetPingIP;
683 NetArpWaitPacketMAC = mac;
685 pkt = NetArpWaitTxPacket;
686 pkt += NetSetEther(pkt, mac, PROT_IP);
688 ip = (volatile IP_t *)pkt;
691 * Construct an IP and ICMP header. (need to set no fragment bit - XXX)
693 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
695 ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8);
696 ip->ip_id = htons(NetIPID++);
697 ip->ip_off = htons(0x4000); /* No fragmentation */
699 ip->ip_p = 0x01; /* ICMP */
702 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
703 NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */
705 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
707 s = &ip->udp_src; /* XXX ICMP starts here */
709 s[0] = htons(0x0800); /* echo-request, code */
710 s[1] = 0; /* checksum */
711 s[2] = 0; /* identifier */
712 s[3] = htons(PingSeqNo++); /* sequence number */
713 s[1] = ~NetCksum((uchar *)s, 8/2);
715 /* size of the waiting packet */
716 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
718 /* and do the ARP request */
720 NetArpWaitTimerStart = get_timer(0);
723 return(1); /* waiting */
726 static void PingTimeout(void){
728 NetState = NETLOOP_FAIL; /* we did not get the reply */
731 static void PingHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){
733 volatile IP_t *ip = (volatile IP_t *)pkt;
735 tmp = NetReadIP((void *)&ip->ip_src);
737 if(tmp != NetPingIP){
741 NetState = NETLOOP_SUCCESS;
744 static void PingStart(void){
746 #if defined(CONFIG_NET_MULTI)
747 printf("Using %s device\n", eth_get_name());
748 #endif /* CONFIG_NET_MULTI */
750 NetSetTimeout(10 * CFG_HZ, PingTimeout);
751 NetSetHandler(PingHandler);
755 #endif /* CONFIG_CMD_PING */
757 void NetReceive(volatile uchar * inpkt, int len){
764 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
767 printf("Packet received\n");
770 #if defined(CONFIG_CMD_HTTPD)
771 if(webfailsafe_is_running){
772 NetReceiveHttpd(inpkt, len);
779 et = (Ethernet_t *)inpkt;
781 /* too small packet? */
782 if(len < ETHER_HDR_SIZE){
786 myvlanid = ntohs(NetOurVLAN);
788 if(myvlanid == (ushort)-1){
789 myvlanid = VLAN_NONE;
792 mynvlanid = ntohs(NetOurNativeVLAN);
794 if(mynvlanid == (ushort)-1){
795 mynvlanid = VLAN_NONE;
798 x = ntohs(et->et_protlen);
801 printf("Packet received\n");
806 * Got a 802 packet. Check the other protocol field.
808 x = ntohs(et->et_prot);
810 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
811 len -= E802_HDR_SIZE;
813 } else if(x != PROT_VLAN){ /* normal packet */
814 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
815 len -= ETHER_HDR_SIZE;
817 } else { /* VLAN packet */
818 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
821 printf("VLAN packet received\n");
823 /* too small packet? */
824 if(len < VLAN_ETHER_HDR_SIZE){
828 /* if no VLAN active */
829 if((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE){
833 cti = ntohs(vet->vet_tag);
834 vlanid = cti & VLAN_IDMASK;
835 x = ntohs(vet->vet_type);
837 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
838 len -= VLAN_ETHER_HDR_SIZE;
842 printf("Receive from protocol 0x%x\n", x);
845 if((myvlanid & VLAN_IDMASK) != VLAN_NONE){
846 if(vlanid == VLAN_NONE){
847 vlanid = (mynvlanid & VLAN_IDMASK);
850 if(vlanid != (myvlanid & VLAN_IDMASK)){
859 * We have to deal with two types of ARP packets:
860 * - REQUEST packets will be answered by sending our
861 * IP address - if we know it.
862 * - REPLY packates are expected only after we asked
863 * for the TFTP server's or the gateway's ethernet
864 * address; so if we receive such a packet, we set
865 * the server ethernet address
872 if(len < ARP_HDR_SIZE){
873 printf_err("bad length %d < %d\n", len, ARP_HDR_SIZE);
877 if(ntohs(arp->ar_hrd) != ARP_ETHER){
881 if(ntohs(arp->ar_pro) != PROT_IP){
885 if(arp->ar_hln != 6){
889 if(arp->ar_pln != 4){
897 if(NetReadIP(&arp->ar_data[16]) != NetOurIP){
901 switch(ntohs(arp->ar_op)){
902 case ARPOP_REQUEST: /* reply with our IP address */
904 puts("Got ARP REQUEST, return our IP\n");
907 pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
908 arp->ar_op = htons(ARPOP_REPLY);
909 memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
910 NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
911 memcpy(&arp->ar_data[0], NetOurEther, 6);
912 NetCopyIP(&arp->ar_data[6], &NetOurIP);
913 (void)eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
917 case ARPOP_REPLY: /* arp reply */
918 /* are we waiting for a reply */
919 if(!NetArpWaitPacketIP || !NetArpWaitPacketMAC){
923 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]);
926 tmp = NetReadIP(&arp->ar_data[6]);
928 /* matched waiting packet's address */
929 if(tmp == NetArpWaitReplyIP){
933 /* save address for later use */
934 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
936 #ifdef CONFIG_NETCONSOLE
937 (*packetHandler)(0,0,0,0);
939 /* modify header, and transmit it */
940 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
941 (void)eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
943 /* no arp request pending now */
944 NetArpWaitPacketIP = 0;
945 NetArpWaitTxPacketSize = 0;
946 NetArpWaitPacketMAC = NULL;
953 printf_err("unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
964 if(len < ARP_HDR_SIZE){
965 printf_err("bad length %d < %d\n", len, ARP_HDR_SIZE);
969 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)){
970 printf_err("invalid RARP header\n");
972 NetCopyIP(&NetOurIP, &arp->ar_data[16]);
973 if(NetServerIP == 0){
974 NetCopyIP(&NetServerIP, &arp->ar_data[6]);
976 memcpy(NetServerEther, &arp->ar_data[0], 6);
977 (*packetHandler)(0, 0, 0, 0);
986 if(len < IP_HDR_SIZE){
987 debug("## Error: len bad %d < %d\n", len, IP_HDR_SIZE);
991 if(len < ntohs(ip->ip_len)){
992 printf_err("len bad %d < %d\n", len, ntohs(ip->ip_len));
996 len = ntohs(ip->ip_len);
998 printf("Len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
1000 if((ip->ip_hl_v & 0xf0) != 0x40){
1004 if(ip->ip_off & htons(0x1fff)){ /* Can't deal w/ fragments */
1008 if(!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)){
1011 printf_err("checksum bad\n");
1016 tmp = NetReadIP(&ip->ip_dst);
1018 if(NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF){
1022 * watch for ICMP host redirects
1024 * There is no real handler code (yet). We just watch
1025 * for ICMP host redirect messages. In case anybody
1026 * sees these messages: please contact me
1027 * (wd@denx.de), or - even better - send me the
1028 * necessary fixes :-)
1030 * Note: in all cases where I have seen this so far
1031 * it was a problem with the router configuration,
1032 * for instance when a router was configured in the
1033 * BOOTP reply, but the TFTP server was on the same
1034 * subnet. So this is probably a warning that your
1035 * configuration might be wrong. But I'm not really
1036 * sure if there aren't any other situations.
1038 if(ip->ip_p == IPPROTO_ICMP){
1039 ICMP_t *icmph = (ICMP_t *) & (ip->udp_src);
1041 switch(icmph->type){
1043 if(icmph->code != ICMP_REDIR_HOST){
1047 puts(" ICMP Host Redirect to ");
1048 print_IPaddr(icmph->un.gateway);
1052 #if defined(CONFIG_CMD_PING)
1053 case ICMP_ECHO_REPLY:
1055 * IP header OK. Pass the packet to the current handler.
1057 /* XXX point to ip packet */
1058 (*packetHandler)((uchar *)ip, 0, 0, 0);
1064 } else if(ip->ip_p != IPPROTO_UDP){ /* Only UDP packets */
1068 #ifdef CONFIG_UDP_CHECKSUM
1069 if(ip->udp_xsum != 0){
1075 xsum += (ntohs(ip->udp_len));
1076 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1077 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
1078 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1079 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
1081 sumlen = ntohs(ip->udp_len);
1082 sumptr = (ushort *)&(ip->udp_src);
1087 sumdata = *sumptr++;
1088 xsum += ntohs(sumdata);
1095 sumdata = *(unsigned char *)sumptr;
1096 sumdata = (sumdata << 8) & 0xff00;
1100 while((xsum >> 16) != 0){
1101 xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
1104 if((xsum != 0x00000000) && (xsum != 0x0000ffff)){
1105 printf_err("UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
1111 #ifdef CONFIG_NETCONSOLE
1112 nc_input_packet((uchar *)ip +IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8);
1115 * IP header OK. Pass the packet to the current handler.
1117 (*packetHandler)((uchar *)ip + IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8);
1122 /**********************************************************************/
1124 static int net_check_prereq(proto_t protocol){
1127 #if defined(CONFIG_CMD_PING)
1130 printf_err("ping address not given\n");
1135 #if defined(CONFIG_CMD_SNTP)
1137 if(NetNtpServerIP == 0){
1138 printf_err("NTP server address not given\n");
1143 #if defined(CONFIG_CMD_NFS)
1149 if(NetServerIP == 0){
1150 printf_err("serverip not set\n");
1153 #if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP)
1157 printf_err("ipaddr not set\n");
1166 if(memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0){
1167 #ifdef CONFIG_NET_MULTI
1168 extern int eth_get_dev_index(void);
1169 int num = eth_get_dev_index();
1173 printf_err("no ethernet found\n");
1176 printf_err("ethaddr not set\n");
1179 printf_err("eth%daddr not set\n", num);
1186 printf_err("ethaddr not set\n");
1197 /**********************************************************************/
1199 int NetCksumOk(uchar * ptr, int len){
1200 return(!((NetCksum(ptr, len) + 1) & 0xfffe));
1203 unsigned NetCksum(uchar * ptr, int len){
1205 ushort *p = (ushort *)ptr;
1213 xsum = (xsum & 0xffff) + (xsum >> 16);
1214 xsum = (xsum & 0xffff) + (xsum >> 16);
1216 return(xsum & 0xffff);
1219 int NetEthHdrSize(void){
1222 myvlanid = ntohs(NetOurVLAN);
1224 if(myvlanid == (ushort) -1){
1225 myvlanid = VLAN_NONE;
1228 return(((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE);
1231 int NetSetEther(volatile uchar * xet, uchar * addr, uint prot){
1232 Ethernet_t *et = (Ethernet_t *)xet;
1235 myvlanid = ntohs(NetOurVLAN);
1237 if(myvlanid == (ushort) -1){
1238 myvlanid = VLAN_NONE;
1241 memcpy(et->et_dest, addr, 6);
1242 memcpy(et->et_src, NetOurEther, 6);
1244 if((myvlanid & VLAN_IDMASK) == VLAN_NONE){
1245 et->et_protlen = htons(prot);
1247 return(ETHER_HDR_SIZE);
1249 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1251 vet->vet_vlan_type = htons(PROT_VLAN);
1252 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1253 vet->vet_type = htons(prot);
1254 return(VLAN_ETHER_HDR_SIZE);
1258 void NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len){
1259 volatile IP_t *ip = (IP_t *)xip;
1262 * If the data is an odd number of bytes, zero the
1263 * byte after the last byte so that the checksum
1267 xip[IP_HDR_SIZE + len] = 0;
1271 * Construct an IP and UDP header.
1272 * (need to set no fragment bit - XXX)
1274 ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
1276 ip->ip_len = htons(IP_HDR_SIZE + len);
1277 ip->ip_id = htons(NetIPID++);
1278 ip->ip_off = htons(0x4000); /* No fragmentation */
1280 ip->ip_p = 17; /* UDP */
1283 NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1284 NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
1286 ip->udp_src = htons(sport);
1287 ip->udp_dst = htons(dport);
1288 ip->udp_len = htons(8 + len);
1290 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1293 void copy_filename(char *dst, char *src, int size){
1294 if(*src && (*src == '"')){
1299 while((--size > 0) && *src && (*src != '"')){
1305 #endif /* CONFIG_CMD_NET */
1307 void ip_to_string(IPaddr_t x, char *s){
1309 sprintf(s, "%d.%d.%d.%d", (int)((x >> 24) & 0xff), (int)((x >> 16) & 0xff), (int)((x >> 8) & 0xff), (int)((x >> 0) & 0xff));
1312 IPaddr_t string_to_ip(char *s){
1321 for(addr = 0, i = 0; i < 4; ++i){
1322 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1324 addr |= (val & 0xFF);
1326 s = (*e) ? e + 1 : e;
1330 return(htonl(addr));
1333 void VLAN_to_string(ushort x, char *s){
1336 if(x == (ushort) -1){
1343 sprintf(s, "%d", x & VLAN_IDMASK);
1347 ushort string_to_VLAN(char *s){
1351 return(htons(VLAN_NONE));
1354 if(*s < '0' || *s > '9'){
1357 id = (ushort) simple_strtoul(s, NULL, 10);
1363 void print_IPaddr(IPaddr_t x){
1366 ip_to_string(x, tmp);
1371 IPaddr_t getenv_IPaddr(char *var){
1372 return(string_to_ip(getenv(var)));
1375 ushort getenv_VLAN(char *var){
1376 return(string_to_VLAN(getenv(var)));
1380 /**********************************************************************************
1384 #if defined(CONFIG_CMD_HTTPD)
1386 void NetSendHttpd(void){
1387 volatile uchar *tmpbuf = NetTxPacket;
1390 for(i = 0; i < 40 + UIP_LLH_LEN; i++){
1391 tmpbuf[i] = uip_buf[i];
1394 for(; i < uip_len; i++){
1395 tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
1398 eth_send(NetTxPacket, uip_len);
1401 void NetReceiveHttpd(volatile uchar * inpkt, int len){
1402 struct uip_eth_hdr *eth_hdr = (struct uip_eth_hdr *)uip_buf;
1404 memcpy(uip_buf, (const void *)inpkt, len);
1407 if(eth_hdr->type == htons(UIP_ETHTYPE_IP)){
1415 } else if(eth_hdr->type == htons(UIP_ETHTYPE_ARP)){
1424 /* *************************************
1426 * HTTP web server for web failsafe mode
1428 ***************************************/
1429 int NetLoopHttpd(void){
1431 unsigned short int ip[2];
1432 unsigned char ethinit_attempt = 0;
1433 struct uip_eth_addr eaddr;
1435 #ifdef CONFIG_NET_MULTI
1440 /* XXX problem with bss workaround */
1441 NetArpWaitPacketMAC = NULL;
1442 NetArpWaitTxPacket = NULL;
1443 NetArpWaitPacketIP = 0;
1444 NetArpWaitReplyIP = 0;
1445 NetArpWaitTxPacket = NULL;
1450 // Setup packet buffers, aligned correctly.
1451 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
1452 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
1454 for(i = 0; i < PKTBUFSRX; i++){
1455 NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
1459 if(!NetArpWaitTxPacket){
1460 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
1461 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
1462 NetArpWaitTxPacketSize = 0;
1470 #ifdef CONFIG_NET_MULTI
1474 while(ethinit_attempt < 10){
1476 ethinit_attempt = 0;
1485 if(ethinit_attempt > 0){
1487 printf_err("couldn't initialize eth (cable disconnected?)!\n\n");
1492 #ifdef CONFIG_NET_MULTI
1493 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
1495 eth_getenv_enetaddr("ethaddr", NetOurEther);
1498 eaddr.addr[0] = NetOurEther[0];
1499 eaddr.addr[1] = NetOurEther[1];
1500 eaddr.addr[2] = NetOurEther[2];
1501 eaddr.addr[3] = NetOurEther[3];
1502 eaddr.addr[4] = NetOurEther[4];
1503 eaddr.addr[5] = NetOurEther[5];
1506 uip_setethaddr(eaddr);
1508 // set ip and other addresses
1509 // TODO: do we need this with uIP stack?
1510 NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
1512 NetOurGatewayIP = getenv_IPaddr("gatewayip");
1513 NetOurSubnetMask = getenv_IPaddr("netmask");
1514 NetOurVLAN = getenv_VLAN("vlan");
1515 NetOurNativeVLAN = getenv_VLAN("nvlan");
1518 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));
1522 // set local host ip address
1523 ip[0] = ((bd->bi_ip_addr & 0xFFFF0000) >> 16);
1524 ip[1] = (bd->bi_ip_addr & 0x0000FFFF);
1526 uip_sethostaddr(ip);
1528 // set network mask (255.255.255.0 -> local network)
1529 ip[0] = ((0xFFFFFF00 & 0xFFFF0000) >> 16);
1530 ip[1] = (0xFFFFFF00 & 0x0000FFFF);
1534 // should we also set default router ip address?
1537 // show current progress of the process
1538 do_http_progress(WEBFAILSAFE_PROGRESS_START);
1540 webfailsafe_is_running = 1;
1561 if (led_off == 1024)
1572 * Check the ethernet for a new packet.
1573 * The ethernet receive routine will process it.
1579 // if CTRL+C was pressed -> return!
1583 // reset global variables to default state
1584 webfailsafe_is_running = 0;
1585 webfailsafe_ready_for_upgrade = 0;
1586 webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
1588 /* Invalidate the last protocol */
1589 eth_set_last_protocol(BOOTP);
1593 printf("\nWeb failsafe mode aborted!\n\n");
1597 // until upload is not completed, get back to the start of the loop
1598 if(!webfailsafe_ready_for_upgrade){
1602 // stop eth interface
1606 do_http_progress(WEBFAILSAFE_PROGRESS_UPLOAD_READY);
1608 // try to make upgrade!
1609 if(do_http_upgrade(NetBootFileXferSize, webfailsafe_upgrade_type) >= 0){
1612 do_http_progress(WEBFAILSAFE_PROGRESS_UPGRADE_READY);
1616 /* reset the board */
1617 do_reset(NULL, 0, 0, NULL);
1622 // reset global variables to default state
1623 webfailsafe_is_running = 0;
1624 webfailsafe_ready_for_upgrade = 0;
1625 webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;
1627 NetBootFileXferSize = 0;
1629 do_http_progress(WEBFAILSAFE_PROGRESS_UPGRADE_FAILED);
1638 #endif /* CONFIG_CMD_HTTPD */