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
80 #include <linux/compiler.h>
85 #ifdef CONFIG_CMD_RARP
89 #ifdef CONFIG_STATUS_LED
90 #include <status_led.h>
93 #if defined(CONFIG_CMD_SNTP)
97 #if defined(CONFIG_CMD_DNS)
102 DECLARE_GLOBAL_DATA_PTR;
104 /** BOOTP EXTENTIONS **/
106 /* Our subnet mask (0=unknown) */
107 IPaddr_t NetOurSubnetMask;
108 /* Our gateways IP address */
109 IPaddr_t NetOurGatewayIP;
110 /* Our DNS IP address */
111 IPaddr_t NetOurDNSIP;
112 #if defined(CONFIG_BOOTP_DNS2)
113 /* Our 2nd DNS IP address */
114 IPaddr_t NetOurDNS2IP;
117 char NetOurNISDomain[32] = {0,};
119 char NetOurHostName[32] = {0,};
121 char NetOurRootPath[64] = {0,};
122 /* Our bootfile size in blocks */
123 ushort NetBootFileSize;
125 #ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */
129 /** END OF BOOTP EXTENTIONS **/
131 /* The actual transferred size of the bootfile (in bytes) */
132 ulong NetBootFileXferSize;
133 /* Our ethernet address */
134 uchar NetOurEther[6];
135 /* Boot server enet address */
136 uchar NetServerEther[6];
137 /* Our IP addr (0 = unknown) */
139 /* Server IP addr (0 = unknown) */
140 IPaddr_t NetServerIP;
141 /* Current receive packet */
143 /* Current rx packet length */
147 /* Ethernet bcast address */
148 uchar NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
149 uchar NetEtherNullAddr[6];
151 void (*push_packet)(void *, int len) = 0;
153 /* Network loop state */
155 /* Tried all network devices */
157 /* Network loop restarted */
158 static int NetRestarted;
159 /* At least one device configured */
160 static int NetDevExists;
162 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
163 /* default is without VLAN */
164 ushort NetOurVLAN = 0xFFFF;
166 ushort NetOurNativeVLAN = 0xFFFF;
171 #if defined(CONFIG_CMD_SNTP)
172 /* NTP server IP address */
173 IPaddr_t NetNtpServerIP;
174 /* offset time from UTC */
178 uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
181 uchar *NetRxPackets[PKTBUFSRX];
183 /* Current RX packet handler */
184 static rxhand_f *packetHandler;
185 #ifdef CONFIG_CMD_TFTPPUT
186 static rxhand_icmp_f *packet_icmp_handler; /* Current ICMP rx handler */
188 /* Current timeout handler */
189 static thand_f *timeHandler;
190 /* Time base value */
191 static ulong timeStart;
192 /* Current timeout value */
193 static ulong timeDelta;
194 /* THE transmit packet */
197 static int net_check_prereq(enum proto_t protocol);
199 static int NetTryCount;
201 /**********************************************************************/
204 * Check if autoload is enabled. If so, use either NFS or TFTP to download
207 void net_auto_load(void)
209 const char *s = getenv("autoload");
214 * Just use BOOTP/RARP to configure system;
215 * Do not use TFTP to load the bootfile.
217 NetState = NETLOOP_SUCCESS;
220 #if defined(CONFIG_CMD_NFS)
221 if (strcmp(s, "NFS") == 0) {
223 * Use NFS to load the bootfile.
233 static void NetInitLoop(enum proto_t protocol)
235 static int env_changed_id;
236 int env_id = get_env_id();
238 /* update only when the environment has changed */
239 if (env_changed_id != env_id) {
240 NetOurIP = getenv_IPaddr("ipaddr");
241 NetOurGatewayIP = getenv_IPaddr("gatewayip");
242 NetOurSubnetMask = getenv_IPaddr("netmask");
243 NetServerIP = getenv_IPaddr("serverip");
244 NetOurNativeVLAN = getenv_VLAN("nvlan");
245 NetOurVLAN = getenv_VLAN("vlan");
246 #if defined(CONFIG_CMD_DNS)
247 NetOurDNSIP = getenv_IPaddr("dnsip");
249 env_changed_id = env_id;
255 /**********************************************************************/
257 * Main network processing loop.
260 int NetLoop(enum proto_t protocol)
276 * Setup packet buffers, aligned correctly.
278 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
279 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
280 for (i = 0; i < PKTBUFSRX; i++)
281 NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
284 bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
287 if (eth_init(bd) < 0) {
293 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
295 NetState = NETLOOP_CONTINUE;
298 * Start the ball rolling with the given start function. From
299 * here on, this code is a state machine driven by received
300 * packets and timer events.
302 NetInitLoop(protocol);
304 switch (net_check_prereq(protocol)) {
306 /* network not configured */
311 /* network device not configured */
316 NetBootFileXferSize = 0;
319 #ifdef CONFIG_CMD_TFTPPUT
322 /* always use ARP to get server ethernet address */
325 #ifdef CONFIG_CMD_TFTPSRV
330 #if defined(CONFIG_CMD_DHCP)
334 DhcpRequest(); /* Basically same as BOOTP */
344 #if defined(CONFIG_CMD_RARP)
351 #if defined(CONFIG_CMD_PING)
356 #if defined(CONFIG_CMD_NFS)
361 #if defined(CONFIG_CMD_CDP)
366 #ifdef CONFIG_NETCONSOLE
371 #if defined(CONFIG_CMD_SNTP)
376 #if defined(CONFIG_CMD_DNS)
388 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
389 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
390 defined(CONFIG_STATUS_LED) && \
391 defined(STATUS_LED_RED)
393 * Echo the inverted link state to the fault LED.
395 if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
396 status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
398 status_led_set(STATUS_LED_RED, STATUS_LED_ON);
399 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
400 #endif /* CONFIG_MII, ... */
403 * Main packet reception loop. Loop receiving packets until
404 * someone sets `NetState' to a state that terminates.
408 #ifdef CONFIG_SHOW_ACTIVITY
412 * Check the ethernet for a new packet. The ethernet
413 * receive routine will process it.
418 * Abort if ctrl-c was pressed.
429 * Check for a timeout, and run the timeout handler
432 if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
435 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
436 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
437 defined(CONFIG_STATUS_LED) && \
438 defined(STATUS_LED_RED)
440 * Echo the inverted link state to the fault LED.
442 if (miiphy_link(eth_get_dev()->name,
443 CONFIG_SYS_FAULT_MII_ADDR)) {
444 status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
446 status_led_set(STATUS_LED_RED, STATUS_LED_ON);
448 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
449 #endif /* CONFIG_MII, ... */
451 timeHandler = (thand_f *)0;
458 case NETLOOP_RESTART:
462 case NETLOOP_SUCCESS:
463 if (NetBootFileXferSize > 0) {
465 printf("Bytes transferred = %ld (%lx hex)\n",
467 NetBootFileXferSize);
468 sprintf(buf, "%lX", NetBootFileXferSize);
469 setenv("filesize", buf);
471 sprintf(buf, "%lX", (unsigned long)load_addr);
472 setenv("fileaddr", buf);
475 ret = NetBootFileXferSize;
484 #ifdef CONFIG_CMD_TFTPPUT
485 /* Clear out the handlers */
487 net_set_icmp_handler(NULL);
492 /**********************************************************************/
495 startAgainTimeout(void)
497 NetState = NETLOOP_RESTART;
501 startAgainHandler(uchar *pkt, unsigned dest, IPaddr_t sip,
502 unsigned src, unsigned len)
504 /* Totally ignore the packet */
507 void NetStartAgain(void)
510 int retry_forever = 0;
511 unsigned long retrycnt = 0;
513 nretry = getenv("netretry");
515 if (!strcmp(nretry, "yes"))
517 else if (!strcmp(nretry, "no"))
519 else if (!strcmp(nretry, "once"))
522 retrycnt = simple_strtoul(nretry, NULL, 0);
526 if ((!retry_forever) && (NetTryCount >= retrycnt)) {
528 NetState = NETLOOP_FAIL;
535 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
536 eth_try_another(!NetRestarted);
539 if (NetRestartWrap) {
542 NetSetTimeout(10000UL, startAgainTimeout);
543 NetSetHandler(startAgainHandler);
545 NetState = NETLOOP_FAIL;
548 NetState = NETLOOP_RESTART;
552 /**********************************************************************/
560 return packetHandler;
565 NetSetHandler(rxhand_f *f)
570 #ifdef CONFIG_CMD_TFTPPUT
571 void net_set_icmp_handler(rxhand_icmp_f *f)
573 packet_icmp_handler = f;
578 NetSetTimeout(ulong iv, thand_f *f)
581 timeHandler = (thand_f *)0;
584 timeStart = get_timer(0);
591 NetSendPacket(uchar *pkt, int len)
593 (void) eth_send(pkt, len);
597 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
601 /* convert to new style broadcast */
605 /* if broadcast, make the ether address a broadcast and don't do ARP */
606 if (dest == 0xFFFFFFFF)
607 ether = NetBcastAddr;
610 * if MAC address was not discovered yet, save the packet and do
613 if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
615 debug("sending ARP for %08x\n", dest);
617 NetArpWaitPacketIP = dest;
618 NetArpWaitPacketMAC = ether;
620 pkt = NetArpWaitTxPacket;
621 pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
623 NetSetIP(pkt, dest, dport, sport, len);
624 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket +
625 (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
627 /* size of the waiting packet */
628 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) +
631 /* and do the ARP request */
633 NetArpWaitTimerStart = get_timer(0);
635 return 1; /* waiting */
638 debug("sending UDP to %08x/%pM\n", dest, ether);
640 pkt = (uchar *)NetTxPacket;
641 pkt += NetSetEther(pkt, ether, PROT_IP);
642 NetSetIP(pkt, dest, dport, sport, len);
643 (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
645 return 0; /* transmitted */
648 #ifdef CONFIG_IP_DEFRAG
650 * This function collects fragments in a single packet, according
651 * to the algorithm in RFC815. It returns NULL or the pointer to
652 * a complete packet, in static storage
654 #ifndef CONFIG_NET_MAXDEFRAG
655 #define CONFIG_NET_MAXDEFRAG 16384
658 * MAXDEFRAG, above, is chosen in the config file and is real data
659 * so we need to add the NFS overhead, which is more than TFTP.
660 * To use sizeof in the internal unnamed structures, we need a real
661 * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately).
662 * The compiler doesn't complain nor allocates the actual structure
664 static struct rpc_t rpc_specimen;
665 #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply))
667 #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE_NO_UDP)
670 * this is the packet being assembled, either data or frag control.
671 * Fragments go by 8 bytes, so this union must be 8 bytes long
674 /* first_byte is address of this structure */
675 u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */
676 u16 next_hole; /* index of next (in 8-b blocks), 0 == none */
677 u16 prev_hole; /* index of prev, 0 == none */
681 static IP_t *__NetDefragment(IP_t *ip, int *lenp)
683 static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
684 static u16 first_hole, total_len;
685 struct hole *payload, *thisfrag, *h, *newh;
686 IP_t *localip = (IP_t *)pkt_buff;
687 uchar *indata = (uchar *)ip;
688 int offset8, start, len, done = 0;
689 u16 ip_off = ntohs(ip->ip_off);
691 /* payload starts after IP header, this fragment is in there */
692 payload = (struct hole *)(pkt_buff + IP_HDR_SIZE_NO_UDP);
693 offset8 = (ip_off & IP_OFFS);
694 thisfrag = payload + offset8;
696 len = ntohs(ip->ip_len) - IP_HDR_SIZE_NO_UDP;
698 if (start + len > IP_MAXUDP) /* fragment extends too far */
701 if (!total_len || localip->ip_id != ip->ip_id) {
702 /* new (or different) packet, reset structs */
704 payload[0].last_byte = ~0;
705 payload[0].next_hole = 0;
706 payload[0].prev_hole = 0;
708 /* any IP header will work, copy the first we received */
709 memcpy(localip, ip, IP_HDR_SIZE_NO_UDP);
713 * What follows is the reassembly algorithm. We use the payload
714 * array as a linked list of hole descriptors, as each hole starts
715 * at a multiple of 8 bytes. However, last byte can be whatever value,
716 * so it is represented as byte count, not as 8-byte blocks.
719 h = payload + first_hole;
720 while (h->last_byte < start) {
722 /* no hole that far away */
725 h = payload + h->next_hole;
728 /* last fragment may be 1..7 bytes, the "+7" forces acceptance */
729 if (offset8 + ((len + 7) / 8) <= h - payload) {
730 /* no overlap with holes (dup fragment?) */
734 if (!(ip_off & IP_FLAGS_MFRAG)) {
735 /* no more fragmentss: truncate this (last) hole */
736 total_len = start + len;
737 h->last_byte = start + len;
741 * There is some overlap: fix the hole list. This code doesn't
742 * deal with a fragment that overlaps with two different holes
743 * (thus being a superset of a previously-received fragment).
746 if ((h >= thisfrag) && (h->last_byte <= start + len)) {
747 /* complete overlap with hole: remove hole */
748 if (!h->prev_hole && !h->next_hole) {
749 /* last remaining hole */
751 } else if (!h->prev_hole) {
753 first_hole = h->next_hole;
754 payload[h->next_hole].prev_hole = 0;
755 } else if (!h->next_hole) {
757 payload[h->prev_hole].next_hole = 0;
759 /* in the middle of the list */
760 payload[h->next_hole].prev_hole = h->prev_hole;
761 payload[h->prev_hole].next_hole = h->next_hole;
764 } else if (h->last_byte <= start + len) {
765 /* overlaps with final part of the hole: shorten this hole */
766 h->last_byte = start;
768 } else if (h >= thisfrag) {
769 /* overlaps with initial part of the hole: move this hole */
770 newh = thisfrag + (len / 8);
774 payload[h->next_hole].prev_hole = (h - payload);
776 payload[h->prev_hole].next_hole = (h - payload);
778 first_hole = (h - payload);
781 /* fragment sits in the middle: split the hole */
782 newh = thisfrag + (len / 8);
784 h->last_byte = start;
785 h->next_hole = (newh - payload);
786 newh->prev_hole = (h - payload);
788 payload[newh->next_hole].prev_hole = (newh - payload);
791 /* finally copy this fragment and possibly return whole packet */
792 memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE_NO_UDP, len);
796 localip->ip_len = htons(total_len);
797 *lenp = total_len + IP_HDR_SIZE_NO_UDP;
801 static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
803 u16 ip_off = ntohs(ip->ip_off);
804 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
805 return ip; /* not a fragment */
806 return __NetDefragment(ip, lenp);
809 #else /* !CONFIG_IP_DEFRAG */
811 static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
813 u16 ip_off = ntohs(ip->ip_off);
814 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
815 return ip; /* not a fragment */
821 * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
824 * @parma ip IP packet containing the ICMP
826 static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et)
828 ICMP_t *icmph = (ICMP_t *)&ip->udp_src;
830 switch (icmph->type) {
832 if (icmph->code != ICMP_REDIR_HOST)
834 printf(" ICMP Host Redirect to %pI4 ",
838 #if defined(CONFIG_CMD_PING)
839 ping_receive(et, ip, len);
841 #ifdef CONFIG_CMD_TFTPPUT
842 if (packet_icmp_handler)
843 packet_icmp_handler(icmph->type, icmph->code,
844 ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
845 icmph->un.data, ntohs(ip->udp_len));
852 NetReceive(uchar *inpkt, int len)
856 #ifdef CONFIG_CMD_RARP
862 #if defined(CONFIG_CMD_CDP)
865 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
867 debug("packet received\n");
870 NetRxPacketLen = len;
871 et = (Ethernet_t *)inpkt;
873 /* too small packet? */
874 if (len < ETHER_HDR_SIZE)
879 (*push_packet)(inpkt, len);
884 #if defined(CONFIG_CMD_CDP)
885 /* keep track if packet is CDP */
886 iscdp = is_cdp_packet(et->et_dest);
889 myvlanid = ntohs(NetOurVLAN);
890 if (myvlanid == (ushort)-1)
891 myvlanid = VLAN_NONE;
892 mynvlanid = ntohs(NetOurNativeVLAN);
893 if (mynvlanid == (ushort)-1)
894 mynvlanid = VLAN_NONE;
896 x = ntohs(et->et_protlen);
898 debug("packet received\n");
902 * Got a 802 packet. Check the other protocol field.
904 x = ntohs(et->et_prot);
906 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
907 len -= E802_HDR_SIZE;
909 } else if (x != PROT_VLAN) { /* normal packet */
910 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
911 len -= ETHER_HDR_SIZE;
913 } else { /* VLAN packet */
914 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
916 debug("VLAN packet received\n");
918 /* too small packet? */
919 if (len < VLAN_ETHER_HDR_SIZE)
922 /* if no VLAN active */
923 if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
924 #if defined(CONFIG_CMD_CDP)
930 cti = ntohs(vet->vet_tag);
931 vlanid = cti & VLAN_IDMASK;
932 x = ntohs(vet->vet_type);
934 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
935 len -= VLAN_ETHER_HDR_SIZE;
938 debug("Receive from protocol 0x%x\n", x);
940 #if defined(CONFIG_CMD_CDP)
942 CDPHandler((uchar *)ip, len);
947 if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
948 if (vlanid == VLAN_NONE)
949 vlanid = (mynvlanid & VLAN_IDMASK);
951 if (vlanid != (myvlanid & VLAN_IDMASK))
958 ArpReceive(et, ip, len);
961 #ifdef CONFIG_CMD_RARP
965 if (len < ARP_HDR_SIZE) {
966 printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
970 if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
971 (ntohs(arp->ar_hrd) != ARP_ETHER) ||
972 (ntohs(arp->ar_pro) != PROT_IP) ||
973 (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
975 puts("invalid RARP header\n");
977 NetCopyIP(&NetOurIP, &arp->ar_data[16]);
978 if (NetServerIP == 0)
979 NetCopyIP(&NetServerIP, &arp->ar_data[6]);
980 memcpy(NetServerEther, &arp->ar_data[0], 6);
982 (*packetHandler)(0, 0, 0, 0, 0);
988 /* Before we start poking the header, make sure it is there */
989 if (len < IP_HDR_SIZE) {
990 debug("len bad %d < %lu\n", len, (ulong)IP_HDR_SIZE);
993 /* Check the packet length */
994 if (len < ntohs(ip->ip_len)) {
995 printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
998 len = ntohs(ip->ip_len);
999 debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
1001 /* Can't deal with anything except IPv4 */
1002 if ((ip->ip_hl_v & 0xf0) != 0x40)
1004 /* Can't deal with IP options (headers != 20 bytes) */
1005 if ((ip->ip_hl_v & 0x0f) > 0x05)
1007 /* Check the Checksum of the header */
1008 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
1009 puts("checksum bad\n");
1012 /* If it is not for us, ignore it */
1013 tmp = NetReadIP(&ip->ip_dst);
1014 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
1015 #ifdef CONFIG_MCAST_TFTP
1016 if (Mcast_addr != tmp)
1020 /* Read source IP address for later use */
1021 src_ip = NetReadIP(&ip->ip_src);
1023 * The function returns the unchanged packet if it's not
1024 * a fragment, and either the complete packet or NULL if
1025 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
1027 ip = NetDefragment(ip, &len);
1031 * watch for ICMP host redirects
1033 * There is no real handler code (yet). We just watch
1034 * for ICMP host redirect messages. In case anybody
1035 * sees these messages: please contact me
1036 * (wd@denx.de), or - even better - send me the
1037 * necessary fixes :-)
1039 * Note: in all cases where I have seen this so far
1040 * it was a problem with the router configuration,
1041 * for instance when a router was configured in the
1042 * BOOTP reply, but the TFTP server was on the same
1043 * subnet. So this is probably a warning that your
1044 * configuration might be wrong. But I'm not really
1045 * sure if there aren't any other situations.
1047 * Simon Glass <sjg@chromium.org>: We get an ICMP when
1048 * we send a tftp packet to a dead connection, or when
1049 * there is no server at the other end.
1051 if (ip->ip_p == IPPROTO_ICMP) {
1052 receive_icmp(ip, len, src_ip, et);
1054 } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
1058 #ifdef CONFIG_UDP_CHECKSUM
1059 if (ip->udp_xsum != 0) {
1065 xsum += (ntohs(ip->udp_len));
1066 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1067 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
1068 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1069 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
1071 sumlen = ntohs(ip->udp_len);
1072 sumptr = (ushort *) &(ip->udp_src);
1074 while (sumlen > 1) {
1077 sumdata = *sumptr++;
1078 xsum += ntohs(sumdata);
1084 sumdata = *(unsigned char *) sumptr;
1085 sumdata = (sumdata << 8) & 0xff00;
1088 while ((xsum >> 16) != 0) {
1089 xsum = (xsum & 0x0000ffff) +
1090 ((xsum >> 16) & 0x0000ffff);
1092 if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1093 printf(" UDP wrong checksum %08lx %08x\n",
1094 xsum, ntohs(ip->udp_xsum));
1101 #ifdef CONFIG_NETCONSOLE
1102 nc_input_packet((uchar *)ip + IP_HDR_SIZE,
1105 ntohs(ip->udp_len) - 8);
1108 * IP header OK. Pass the packet to the current handler.
1110 (*packetHandler)((uchar *)ip + IP_HDR_SIZE,
1114 ntohs(ip->udp_len) - 8);
1120 /**********************************************************************/
1122 static int net_check_prereq(enum proto_t protocol)
1126 #if defined(CONFIG_CMD_PING)
1128 if (NetPingIP == 0) {
1129 puts("*** ERROR: ping address not given\n");
1134 #if defined(CONFIG_CMD_SNTP)
1136 if (NetNtpServerIP == 0) {
1137 puts("*** ERROR: NTP server address not given\n");
1142 #if defined(CONFIG_CMD_DNS)
1144 if (NetOurDNSIP == 0) {
1145 puts("*** ERROR: DNS server address not given\n");
1150 #if defined(CONFIG_CMD_NFS)
1155 if (NetServerIP == 0) {
1156 puts("*** ERROR: `serverip' not set\n");
1159 #if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
1160 defined(CONFIG_CMD_DNS)
1167 if (NetOurIP == 0) {
1168 puts("*** ERROR: `ipaddr' not set\n");
1173 #ifdef CONFIG_CMD_RARP
1179 if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
1180 int num = eth_get_dev_index();
1184 puts("*** ERROR: No ethernet found.\n");
1187 puts("*** ERROR: `ethaddr' not set\n");
1190 printf("*** ERROR: `eth%daddr' not set\n",
1204 /**********************************************************************/
1207 NetCksumOk(uchar *ptr, int len)
1209 return !((NetCksum(ptr, len) + 1) & 0xfffe);
1214 NetCksum(uchar *ptr, int len)
1217 ushort *p = (ushort *)ptr;
1222 xsum = (xsum & 0xffff) + (xsum >> 16);
1223 xsum = (xsum & 0xffff) + (xsum >> 16);
1224 return xsum & 0xffff;
1232 myvlanid = ntohs(NetOurVLAN);
1233 if (myvlanid == (ushort)-1)
1234 myvlanid = VLAN_NONE;
1236 return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
1237 VLAN_ETHER_HDR_SIZE;
1241 NetSetEther(uchar *xet, uchar * addr, uint prot)
1243 Ethernet_t *et = (Ethernet_t *)xet;
1246 myvlanid = ntohs(NetOurVLAN);
1247 if (myvlanid == (ushort)-1)
1248 myvlanid = VLAN_NONE;
1250 memcpy(et->et_dest, addr, 6);
1251 memcpy(et->et_src, NetOurEther, 6);
1252 if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1253 et->et_protlen = htons(prot);
1254 return ETHER_HDR_SIZE;
1256 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1258 vet->vet_vlan_type = htons(PROT_VLAN);
1259 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1260 vet->vet_type = htons(prot);
1261 return VLAN_ETHER_HDR_SIZE;
1266 NetSetIP(uchar *xip, IPaddr_t dest, int dport, int sport, int len)
1268 IP_t *ip = (IP_t *)xip;
1271 * If the data is an odd number of bytes, zero the
1272 * byte after the last byte so that the checksum
1276 xip[IP_HDR_SIZE + len] = 0;
1279 * Construct an IP and UDP header.
1280 * (need to set no fragment bit - XXX)
1282 /* IP_HDR_SIZE / 4 (not including UDP) */
1285 ip->ip_len = htons(IP_HDR_SIZE + len);
1286 ip->ip_id = htons(NetIPID++);
1287 ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */
1289 ip->ip_p = 17; /* UDP */
1291 /* already in network byte order */
1292 NetCopyIP((void *)&ip->ip_src, &NetOurIP);
1294 NetCopyIP((void *)&ip->ip_dst, &dest);
1295 ip->udp_src = htons(sport);
1296 ip->udp_dst = htons(dport);
1297 ip->udp_len = htons(8 + len);
1299 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1302 void copy_filename(char *dst, const char *src, int size)
1304 if (*src && (*src == '"')) {
1309 while ((--size > 0) && *src && (*src != '"'))
1314 #if defined(CONFIG_CMD_NFS) || \
1315 defined(CONFIG_CMD_SNTP) || \
1316 defined(CONFIG_CMD_DNS)
1318 * make port a little random (1024-17407)
1319 * This keeps the math somewhat trivial to compute, and seems to work with
1320 * all supported protocols/clients/servers
1322 unsigned int random_port(void)
1324 return 1024 + (get_timer(0) % 0x4000);
1328 void ip_to_string(IPaddr_t x, char *s)
1331 sprintf(s, "%d.%d.%d.%d",
1332 (int) ((x >> 24) & 0xff),
1333 (int) ((x >> 16) & 0xff),
1334 (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
1338 void VLAN_to_string(ushort x, char *s)
1342 if (x == (ushort)-1)
1348 sprintf(s, "%d", x & VLAN_IDMASK);
1351 ushort string_to_VLAN(const char *s)
1356 return htons(VLAN_NONE);
1358 if (*s < '0' || *s > '9')
1361 id = (ushort)simple_strtoul(s, NULL, 10);
1366 ushort getenv_VLAN(char *var)
1368 return string_to_VLAN(getenv(var));