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 #ifdef CONFIG_CMD_RARP
87 #ifdef CONFIG_STATUS_LED
88 #include <status_led.h>
91 #if defined(CONFIG_CMD_SNTP)
94 #if defined(CONFIG_CDP_VERSION)
95 #include <timestamp.h>
97 #if defined(CONFIG_CMD_DNS)
101 DECLARE_GLOBAL_DATA_PTR;
103 #ifndef CONFIG_ARP_TIMEOUT
104 /* Milliseconds before trying ARP again */
105 # define ARP_TIMEOUT 5000UL
107 # define ARP_TIMEOUT CONFIG_ARP_TIMEOUT
111 #ifndef CONFIG_NET_RETRY_COUNT
112 # define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
114 # define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT
117 /** BOOTP EXTENTIONS **/
119 /* Our subnet mask (0=unknown) */
120 IPaddr_t NetOurSubnetMask;
121 /* Our gateways IP address */
122 IPaddr_t NetOurGatewayIP;
123 /* Our DNS IP address */
124 IPaddr_t NetOurDNSIP;
125 #if defined(CONFIG_BOOTP_DNS2)
126 /* Our 2nd DNS IP address */
127 IPaddr_t NetOurDNS2IP;
130 char NetOurNISDomain[32] = {0,};
132 char NetOurHostName[32] = {0,};
134 char NetOurRootPath[64] = {0,};
135 /* Our bootfile size in blocks */
136 ushort NetBootFileSize;
138 #ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */
142 /** END OF BOOTP EXTENTIONS **/
144 /* The actual transferred size of the bootfile (in bytes) */
145 ulong NetBootFileXferSize;
146 /* Our ethernet address */
147 uchar NetOurEther[6];
148 /* Boot server enet address */
149 uchar NetServerEther[6];
150 /* Our IP addr (0 = unknown) */
152 /* Server IP addr (0 = unknown) */
153 IPaddr_t NetServerIP;
154 /* Current receive packet */
155 volatile uchar *NetRxPacket;
156 /* Current rx packet length */
160 /* Ethernet bcast address */
161 uchar NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
162 uchar NetEtherNullAddr[6];
164 void (*push_packet)(volatile void *, int len) = 0;
166 #if defined(CONFIG_CMD_CDP)
167 /* Ethernet bcast address */
168 uchar NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };
170 /* Network loop state */
172 /* Tried all network devices */
174 /* Network loop restarted */
175 static int NetRestarted;
176 /* At least one device configured */
177 static int NetDevExists;
179 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
180 /* default is without VLAN */
181 ushort NetOurVLAN = 0xFFFF;
183 ushort NetOurNativeVLAN = 0xFFFF;
188 #if defined(CONFIG_CMD_PING)
189 /* the ip address to ping */
192 static void PingStart(void);
195 #if defined(CONFIG_CMD_CDP)
196 static void CDPStart(void);
199 #if defined(CONFIG_CMD_SNTP)
200 /* NTP server IP address */
201 IPaddr_t NetNtpServerIP;
202 /* offset time from UTC */
206 #ifdef CONFIG_NETCONSOLE
208 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
211 volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
214 volatile uchar *NetRxPackets[PKTBUFSRX];
216 /* Current RX packet handler */
217 static rxhand_f *packetHandler;
218 #ifdef CONFIG_CMD_TFTPPUT
219 static rxhand_icmp_f *packet_icmp_handler; /* Current ICMP rx handler */
221 /* Current timeout handler */
222 static thand_f *timeHandler;
223 /* Time base value */
224 static ulong timeStart;
225 /* Current timeout value */
226 static ulong timeDelta;
227 /* THE transmit packet */
228 volatile uchar *NetTxPacket;
230 static int net_check_prereq(enum proto_t protocol);
232 static int NetTryCount;
234 /**********************************************************************/
236 IPaddr_t NetArpWaitPacketIP;
237 IPaddr_t NetArpWaitReplyIP;
238 /* MAC address of waiting packet's destination */
239 uchar *NetArpWaitPacketMAC;
240 /* THE transmit packet */
241 uchar *NetArpWaitTxPacket;
242 int NetArpWaitTxPacketSize;
243 uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
244 ulong NetArpWaitTimerStart;
247 void ArpRequest(void)
252 debug("ARP broadcast %d\n", NetArpWaitTry);
256 pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
260 arp->ar_hrd = htons(ARP_ETHER);
261 arp->ar_pro = htons(PROT_IP);
264 arp->ar_op = htons(ARPOP_REQUEST);
267 memcpy(&arp->ar_data[0], NetOurEther, 6);
269 NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
270 /* dest ET addr = 0 */
271 memset(&arp->ar_data[10], '\0', 6);
272 if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
273 (NetOurIP & NetOurSubnetMask)) {
274 if (NetOurGatewayIP == 0) {
275 puts("## Warning: gatewayip needed but not set\n");
276 NetArpWaitReplyIP = NetArpWaitPacketIP;
278 NetArpWaitReplyIP = NetOurGatewayIP;
281 NetArpWaitReplyIP = NetArpWaitPacketIP;
284 NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
285 (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
288 void ArpTimeoutCheck(void)
292 if (!NetArpWaitPacketIP)
297 /* check for arp timeout */
298 if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
301 if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
302 puts("\nARP Retry count exceeded; starting again\n");
306 NetArpWaitTimerStart = t;
313 * Check if autoload is enabled. If so, use either NFS or TFTP to download
316 void net_auto_load(void)
318 const char *s = getenv("autoload");
323 * Just use BOOTP/RARP to configure system;
324 * Do not use TFTP to load the bootfile.
326 NetState = NETLOOP_SUCCESS;
329 #if defined(CONFIG_CMD_NFS)
330 if (strcmp(s, "NFS") == 0) {
332 * Use NFS to load the bootfile.
342 static void NetInitLoop(enum proto_t protocol)
344 static int env_changed_id;
346 int env_id = get_env_id();
348 /* update only when the environment has changed */
349 if (env_changed_id != env_id) {
350 NetOurIP = getenv_IPaddr("ipaddr");
351 NetCopyIP(&bd->bi_ip_addr, &NetOurIP);
352 NetOurGatewayIP = getenv_IPaddr("gatewayip");
353 NetOurSubnetMask = getenv_IPaddr("netmask");
354 NetServerIP = getenv_IPaddr("serverip");
355 NetOurNativeVLAN = getenv_VLAN("nvlan");
356 NetOurVLAN = getenv_VLAN("vlan");
357 #if defined(CONFIG_CMD_DNS)
358 NetOurDNSIP = getenv_IPaddr("dnsip");
360 env_changed_id = env_id;
366 /**********************************************************************/
368 * Main network processing loop.
371 int NetLoop(enum proto_t protocol)
379 /* XXX problem with bss workaround */
380 NetArpWaitPacketMAC = NULL;
381 NetArpWaitTxPacket = NULL;
382 NetArpWaitPacketIP = 0;
383 NetArpWaitReplyIP = 0;
384 NetArpWaitTxPacket = NULL;
391 * Setup packet buffers, aligned correctly.
393 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
394 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
395 for (i = 0; i < PKTBUFSRX; i++)
396 NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
399 if (!NetArpWaitTxPacket) {
400 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
401 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
402 NetArpWaitTxPacketSize = 0;
405 bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
408 if (eth_init(bd) < 0) {
414 memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
416 NetState = NETLOOP_CONTINUE;
419 * Start the ball rolling with the given start function. From
420 * here on, this code is a state machine driven by received
421 * packets and timer events.
423 NetInitLoop(protocol);
425 switch (net_check_prereq(protocol)) {
427 /* network not configured */
432 /* network device not configured */
437 NetBootFileXferSize = 0;
440 #ifdef CONFIG_CMD_TFTPPUT
443 /* always use ARP to get server ethernet address */
446 #ifdef CONFIG_CMD_TFTPSRV
451 #if defined(CONFIG_CMD_DHCP)
455 DhcpRequest(); /* Basically same as BOOTP */
465 #if defined(CONFIG_CMD_RARP)
472 #if defined(CONFIG_CMD_PING)
477 #if defined(CONFIG_CMD_NFS)
482 #if defined(CONFIG_CMD_CDP)
487 #ifdef CONFIG_NETCONSOLE
492 #if defined(CONFIG_CMD_SNTP)
497 #if defined(CONFIG_CMD_DNS)
509 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
510 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
511 defined(CONFIG_STATUS_LED) && \
512 defined(STATUS_LED_RED)
514 * Echo the inverted link state to the fault LED.
516 if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
517 status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
519 status_led_set(STATUS_LED_RED, STATUS_LED_ON);
520 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
521 #endif /* CONFIG_MII, ... */
524 * Main packet reception loop. Loop receiving packets until
525 * someone sets `NetState' to a state that terminates.
529 #ifdef CONFIG_SHOW_ACTIVITY
531 extern void show_activity(int arg);
536 * Check the ethernet for a new packet. The ethernet
537 * receive routine will process it.
542 * Abort if ctrl-c was pressed.
553 * Check for a timeout, and run the timeout handler
556 if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
559 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
560 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
561 defined(CONFIG_STATUS_LED) && \
562 defined(STATUS_LED_RED)
564 * Echo the inverted link state to the fault LED.
566 if (miiphy_link(eth_get_dev()->name,
567 CONFIG_SYS_FAULT_MII_ADDR)) {
568 status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
570 status_led_set(STATUS_LED_RED, STATUS_LED_ON);
572 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
573 #endif /* CONFIG_MII, ... */
575 timeHandler = (thand_f *)0;
582 case NETLOOP_RESTART:
586 case NETLOOP_SUCCESS:
587 if (NetBootFileXferSize > 0) {
589 printf("Bytes transferred = %ld (%lx hex)\n",
591 NetBootFileXferSize);
592 sprintf(buf, "%lX", NetBootFileXferSize);
593 setenv("filesize", buf);
595 sprintf(buf, "%lX", (unsigned long)load_addr);
596 setenv("fileaddr", buf);
599 ret = NetBootFileXferSize;
608 #ifdef CONFIG_CMD_TFTPPUT
609 /* Clear out the handlers */
611 net_set_icmp_handler(NULL);
616 /**********************************************************************/
619 startAgainTimeout(void)
621 NetState = NETLOOP_RESTART;
625 startAgainHandler(uchar *pkt, unsigned dest, IPaddr_t sip,
626 unsigned src, unsigned len)
628 /* Totally ignore the packet */
631 void NetStartAgain(void)
634 int retry_forever = 0;
635 unsigned long retrycnt = 0;
637 nretry = getenv("netretry");
639 if (!strcmp(nretry, "yes"))
641 else if (!strcmp(nretry, "no"))
643 else if (!strcmp(nretry, "once"))
646 retrycnt = simple_strtoul(nretry, NULL, 0);
650 if ((!retry_forever) && (NetTryCount >= retrycnt)) {
652 NetState = NETLOOP_FAIL;
659 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
660 eth_try_another(!NetRestarted);
663 if (NetRestartWrap) {
666 NetSetTimeout(10000UL, startAgainTimeout);
667 NetSetHandler(startAgainHandler);
669 NetState = NETLOOP_FAIL;
672 NetState = NETLOOP_RESTART;
676 /**********************************************************************/
682 NetSetHandler(rxhand_f *f)
687 #ifdef CONFIG_CMD_TFTPPUT
688 void net_set_icmp_handler(rxhand_icmp_f *f)
690 packet_icmp_handler = f;
695 NetSetTimeout(ulong iv, thand_f *f)
698 timeHandler = (thand_f *)0;
701 timeStart = get_timer(0);
708 NetSendPacket(volatile uchar *pkt, int len)
710 (void) eth_send(pkt, len);
714 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
718 /* convert to new style broadcast */
722 /* if broadcast, make the ether address a broadcast and don't do ARP */
723 if (dest == 0xFFFFFFFF)
724 ether = NetBcastAddr;
727 * if MAC address was not discovered yet, save the packet and do
730 if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
732 debug("sending ARP for %08x\n", dest);
734 NetArpWaitPacketIP = dest;
735 NetArpWaitPacketMAC = ether;
737 pkt = NetArpWaitTxPacket;
738 pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
740 NetSetIP(pkt, dest, dport, sport, len);
741 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket +
742 (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
744 /* size of the waiting packet */
745 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) +
748 /* and do the ARP request */
750 NetArpWaitTimerStart = get_timer(0);
752 return 1; /* waiting */
755 debug("sending UDP to %08x/%pM\n", dest, ether);
757 pkt = (uchar *)NetTxPacket;
758 pkt += NetSetEther(pkt, ether, PROT_IP);
759 NetSetIP(pkt, dest, dport, sport, len);
760 (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
762 return 0; /* transmitted */
765 #if defined(CONFIG_CMD_PING)
766 static ushort PingSeqNo;
775 /* XXX always send arp request */
777 memcpy(mac, NetEtherNullAddr, 6);
779 debug("sending ARP for %08x\n", NetPingIP);
781 NetArpWaitPacketIP = NetPingIP;
782 NetArpWaitPacketMAC = mac;
784 pkt = NetArpWaitTxPacket;
785 pkt += NetSetEther(pkt, mac, PROT_IP);
787 ip = (volatile IP_t *)pkt;
790 * Construct an IP and ICMP header.
791 * (need to set no fragment bit - XXX)
793 /* IP_HDR_SIZE / 4 (not including UDP) */
796 ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8);
797 ip->ip_id = htons(NetIPID++);
798 ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */
800 ip->ip_p = 0x01; /* ICMP */
802 /* already in network byte order */
803 NetCopyIP((void *)&ip->ip_src, &NetOurIP);
805 NetCopyIP((void *)&ip->ip_dst, &NetPingIP);
806 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
808 s = &ip->udp_src; /* XXX ICMP starts here */
809 s[0] = htons(0x0800); /* echo-request, code */
810 s[1] = 0; /* checksum */
811 s[2] = 0; /* identifier */
812 s[3] = htons(PingSeqNo++); /* sequence number */
813 s[1] = ~NetCksum((uchar *)s, 8/2);
815 /* size of the waiting packet */
816 NetArpWaitTxPacketSize =
817 (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
819 /* and do the ARP request */
821 NetArpWaitTimerStart = get_timer(0);
823 return 1; /* waiting */
830 NetState = NETLOOP_FAIL; /* we did not get the reply */
834 PingHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
837 if (sip != NetPingIP)
840 NetState = NETLOOP_SUCCESS;
843 static void PingStart(void)
845 printf("Using %s device\n", eth_get_name());
846 NetSetTimeout(10000UL, PingTimeout);
847 NetSetHandler(PingHandler);
853 #if defined(CONFIG_CMD_CDP)
855 #define CDP_DEVICE_ID_TLV 0x0001
856 #define CDP_ADDRESS_TLV 0x0002
857 #define CDP_PORT_ID_TLV 0x0003
858 #define CDP_CAPABILITIES_TLV 0x0004
859 #define CDP_VERSION_TLV 0x0005
860 #define CDP_PLATFORM_TLV 0x0006
861 #define CDP_NATIVE_VLAN_TLV 0x000a
862 #define CDP_APPLIANCE_VLAN_TLV 0x000e
863 #define CDP_TRIGGER_TLV 0x000f
864 #define CDP_POWER_CONSUMPTION_TLV 0x0010
865 #define CDP_SYSNAME_TLV 0x0014
866 #define CDP_SYSOBJECT_TLV 0x0015
867 #define CDP_MANAGEMENT_ADDRESS_TLV 0x0016
869 #define CDP_TIMEOUT 250UL /* one packet every 250ms */
874 ushort CDPNativeVLAN;
875 ushort CDPApplianceVLAN;
877 static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20,
880 static ushort CDP_compute_csum(const uchar *buff, ushort len)
889 odd = 1 & (ulong)buff;
899 if (result & 0x80000000)
900 result = (result & 0xFFFF) + (result >> 16);
904 leftover = (signed short)(*(const signed char *)buff);
905 /* CISCO SUCKS big time! (and blows too):
906 * CDP uses the IP checksum algorithm with a twist;
907 * for the last byte it *sign* extends and sums.
909 result = (result & 0xffff0000) |
910 ((result + leftover) & 0x0000ffff);
913 result = (result & 0xFFFF) + (result >> 16);
916 result = ((result >> 8) & 0xff) |
917 ((result & 0xff) << 8);
920 /* add up 16-bit and 17-bit words for 17+c bits */
921 result = (result & 0xffff) + (result >> 16);
922 /* add up 16-bit and 2-bit for 16+c bit */
923 result = (result & 0xffff) + (result >> 16);
925 result = (result & 0xffff) + (result >> 16);
928 csum = ~(ushort)result;
930 /* run time endian detection */
931 if (csum != htons(csum)) /* little endian */
937 int CDPSendTrigger(void)
945 #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID) || \
946 defined(CONFIG_CDP_VERSION) || defined(CONFIG_CDP_PLATFORM)
951 et = (Ethernet_t *)pkt;
953 /* NOTE: trigger sent not on any VLAN */
955 /* form ethernet header */
956 memcpy(et->et_dest, NetCDPAddr, 6);
957 memcpy(et->et_src, NetOurEther, 6);
959 pkt += ETHER_HDR_SIZE;
962 memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr));
963 pkt += sizeof(CDP_SNAP_hdr);
966 *pkt++ = 0x02; /* CDP version 2 */
967 *pkt++ = 180; /* TTL */
968 s = (volatile ushort *)pkt;
970 /* checksum (0 for later calculation) */
974 #ifdef CONFIG_CDP_DEVICE_ID
975 *s++ = htons(CDP_DEVICE_ID_TLV);
976 *s++ = htons(CONFIG_CDP_DEVICE_ID);
977 sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%pm", NetOurEther);
978 memcpy((uchar *)s, buf, 16);
982 #ifdef CONFIG_CDP_PORT_ID
983 *s++ = htons(CDP_PORT_ID_TLV);
984 memset(buf, 0, sizeof(buf));
985 sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index());
987 if (len & 1) /* make it even */
989 *s++ = htons(len + 4);
990 memcpy((uchar *)s, buf, len);
994 #ifdef CONFIG_CDP_CAPABILITIES
995 *s++ = htons(CDP_CAPABILITIES_TLV);
997 *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES);
1001 #ifdef CONFIG_CDP_VERSION
1002 *s++ = htons(CDP_VERSION_TLV);
1003 memset(buf, 0, sizeof(buf));
1004 strcpy(buf, CONFIG_CDP_VERSION);
1006 if (len & 1) /* make it even */
1008 *s++ = htons(len + 4);
1009 memcpy((uchar *)s, buf, len);
1013 #ifdef CONFIG_CDP_PLATFORM
1014 *s++ = htons(CDP_PLATFORM_TLV);
1015 memset(buf, 0, sizeof(buf));
1016 strcpy(buf, CONFIG_CDP_PLATFORM);
1018 if (len & 1) /* make it even */
1020 *s++ = htons(len + 4);
1021 memcpy((uchar *)s, buf, len);
1025 #ifdef CONFIG_CDP_TRIGGER
1026 *s++ = htons(CDP_TRIGGER_TLV);
1028 *(ulong *)s = htonl(CONFIG_CDP_TRIGGER);
1032 #ifdef CONFIG_CDP_POWER_CONSUMPTION
1033 *s++ = htons(CDP_POWER_CONSUMPTION_TLV);
1035 *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION);
1038 /* length of ethernet packet */
1039 len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE);
1040 et->et_protlen = htons(len);
1042 len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr);
1043 chksum = CDP_compute_csum((uchar *)NetTxPacket + len,
1044 (uchar *)s - (NetTxPacket + len));
1047 *cp = htons(chksum);
1049 (void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket);
1059 NetSetTimeout(CDP_TIMEOUT, CDPTimeout);
1064 /* if not OK try again */
1068 NetState = NETLOOP_SUCCESS;
1072 CDPDummyHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
1079 CDPHandler(const uchar *pkt, unsigned len)
1087 if (len < sizeof(CDP_SNAP_hdr) + 4)
1090 /* check for valid CDP SNAP header */
1091 if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0)
1094 pkt += sizeof(CDP_SNAP_hdr);
1095 len -= sizeof(CDP_SNAP_hdr);
1097 /* Version of CDP protocol must be >= 2 and TTL != 0 */
1098 if (pkt[0] < 0x02 || pkt[1] == 0)
1102 * if version is greater than 0x02 maybe we'll have a problem;
1106 printf("** WARNING: CDP packet received with a protocol version %d > 2\n",
1109 if (CDP_compute_csum(pkt, len) != 0)
1121 ss = (const ushort *)pkt;
1122 type = ntohs(ss[0]);
1123 tlen = ntohs(ss[1]);
1130 ss += 2; /* point ss to the data of the TLV */
1134 case CDP_DEVICE_ID_TLV:
1136 case CDP_ADDRESS_TLV:
1138 case CDP_PORT_ID_TLV:
1140 case CDP_CAPABILITIES_TLV:
1142 case CDP_VERSION_TLV:
1144 case CDP_PLATFORM_TLV:
1146 case CDP_NATIVE_VLAN_TLV:
1149 case CDP_APPLIANCE_VLAN_TLV:
1150 t = (const uchar *)ss;
1155 ss = (const ushort *)(t + 1);
1157 #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
1158 if (t[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
1161 /* XXX will this work; dunno */
1167 case CDP_TRIGGER_TLV:
1169 case CDP_POWER_CONSUMPTION_TLV:
1171 case CDP_SYSNAME_TLV:
1173 case CDP_SYSOBJECT_TLV:
1175 case CDP_MANAGEMENT_ADDRESS_TLV:
1180 CDPApplianceVLAN = vlan;
1181 CDPNativeVLAN = nvlan;
1187 printf("** CDP packet is too short\n");
1191 static void CDPStart(void)
1193 printf("Using %s device\n", eth_get_name());
1197 CDPNativeVLAN = htons(-1);
1198 CDPApplianceVLAN = htons(-1);
1200 NetSetTimeout(CDP_TIMEOUT, CDPTimeout);
1201 NetSetHandler(CDPDummyHandler);
1207 #ifdef CONFIG_IP_DEFRAG
1209 * This function collects fragments in a single packet, according
1210 * to the algorithm in RFC815. It returns NULL or the pointer to
1211 * a complete packet, in static storage
1213 #ifndef CONFIG_NET_MAXDEFRAG
1214 #define CONFIG_NET_MAXDEFRAG 16384
1217 * MAXDEFRAG, above, is chosen in the config file and is real data
1218 * so we need to add the NFS overhead, which is more than TFTP.
1219 * To use sizeof in the internal unnamed structures, we need a real
1220 * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately).
1221 * The compiler doesn't complain nor allocates the actual structure
1223 static struct rpc_t rpc_specimen;
1224 #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply))
1226 #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE_NO_UDP)
1229 * this is the packet being assembled, either data or frag control.
1230 * Fragments go by 8 bytes, so this union must be 8 bytes long
1233 /* first_byte is address of this structure */
1234 u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */
1235 u16 next_hole; /* index of next (in 8-b blocks), 0 == none */
1236 u16 prev_hole; /* index of prev, 0 == none */
1240 static IP_t *__NetDefragment(IP_t *ip, int *lenp)
1242 static uchar pkt_buff[IP_PKTSIZE] __attribute__((aligned(PKTALIGN)));
1243 static u16 first_hole, total_len;
1244 struct hole *payload, *thisfrag, *h, *newh;
1245 IP_t *localip = (IP_t *)pkt_buff;
1246 uchar *indata = (uchar *)ip;
1247 int offset8, start, len, done = 0;
1248 u16 ip_off = ntohs(ip->ip_off);
1250 /* payload starts after IP header, this fragment is in there */
1251 payload = (struct hole *)(pkt_buff + IP_HDR_SIZE_NO_UDP);
1252 offset8 = (ip_off & IP_OFFS);
1253 thisfrag = payload + offset8;
1254 start = offset8 * 8;
1255 len = ntohs(ip->ip_len) - IP_HDR_SIZE_NO_UDP;
1257 if (start + len > IP_MAXUDP) /* fragment extends too far */
1260 if (!total_len || localip->ip_id != ip->ip_id) {
1261 /* new (or different) packet, reset structs */
1263 payload[0].last_byte = ~0;
1264 payload[0].next_hole = 0;
1265 payload[0].prev_hole = 0;
1267 /* any IP header will work, copy the first we received */
1268 memcpy(localip, ip, IP_HDR_SIZE_NO_UDP);
1272 * What follows is the reassembly algorithm. We use the payload
1273 * array as a linked list of hole descriptors, as each hole starts
1274 * at a multiple of 8 bytes. However, last byte can be whatever value,
1275 * so it is represented as byte count, not as 8-byte blocks.
1278 h = payload + first_hole;
1279 while (h->last_byte < start) {
1280 if (!h->next_hole) {
1281 /* no hole that far away */
1284 h = payload + h->next_hole;
1287 /* last fragment may be 1..7 bytes, the "+7" forces acceptance */
1288 if (offset8 + ((len + 7) / 8) <= h - payload) {
1289 /* no overlap with holes (dup fragment?) */
1293 if (!(ip_off & IP_FLAGS_MFRAG)) {
1294 /* no more fragmentss: truncate this (last) hole */
1295 total_len = start + len;
1296 h->last_byte = start + len;
1300 * There is some overlap: fix the hole list. This code doesn't
1301 * deal with a fragment that overlaps with two different holes
1302 * (thus being a superset of a previously-received fragment).
1305 if ((h >= thisfrag) && (h->last_byte <= start + len)) {
1306 /* complete overlap with hole: remove hole */
1307 if (!h->prev_hole && !h->next_hole) {
1308 /* last remaining hole */
1310 } else if (!h->prev_hole) {
1312 first_hole = h->next_hole;
1313 payload[h->next_hole].prev_hole = 0;
1314 } else if (!h->next_hole) {
1316 payload[h->prev_hole].next_hole = 0;
1318 /* in the middle of the list */
1319 payload[h->next_hole].prev_hole = h->prev_hole;
1320 payload[h->prev_hole].next_hole = h->next_hole;
1323 } else if (h->last_byte <= start + len) {
1324 /* overlaps with final part of the hole: shorten this hole */
1325 h->last_byte = start;
1327 } else if (h >= thisfrag) {
1328 /* overlaps with initial part of the hole: move this hole */
1329 newh = thisfrag + (len / 8);
1333 payload[h->next_hole].prev_hole = (h - payload);
1335 payload[h->prev_hole].next_hole = (h - payload);
1337 first_hole = (h - payload);
1340 /* fragment sits in the middle: split the hole */
1341 newh = thisfrag + (len / 8);
1343 h->last_byte = start;
1344 h->next_hole = (newh - payload);
1345 newh->prev_hole = (h - payload);
1346 if (newh->next_hole)
1347 payload[newh->next_hole].prev_hole = (newh - payload);
1350 /* finally copy this fragment and possibly return whole packet */
1351 memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE_NO_UDP, len);
1355 localip->ip_len = htons(total_len);
1356 *lenp = total_len + IP_HDR_SIZE_NO_UDP;
1360 static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
1362 u16 ip_off = ntohs(ip->ip_off);
1363 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1364 return ip; /* not a fragment */
1365 return __NetDefragment(ip, lenp);
1368 #else /* !CONFIG_IP_DEFRAG */
1370 static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
1372 u16 ip_off = ntohs(ip->ip_off);
1373 if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1374 return ip; /* not a fragment */
1380 * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
1383 * @parma ip IP packet containing the ICMP
1385 static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et)
1387 ICMP_t *icmph = (ICMP_t *)&ip->udp_src;
1389 switch (icmph->type) {
1391 if (icmph->code != ICMP_REDIR_HOST)
1393 printf(" ICMP Host Redirect to %pI4 ",
1394 &icmph->un.gateway);
1396 #if defined(CONFIG_CMD_PING)
1397 case ICMP_ECHO_REPLY:
1399 * IP header OK. Pass the packet to the
1403 * XXX point to ip packet - should this use
1404 * packet_icmp_handler?
1406 (*packetHandler)((uchar *)ip, 0, src_ip, 0, 0);
1408 case ICMP_ECHO_REQUEST:
1409 debug("Got ICMP ECHO REQUEST, return %d bytes\n",
1410 ETHER_HDR_SIZE + len);
1412 memcpy(&et->et_dest[0], &et->et_src[0], 6);
1413 memcpy(&et->et_src[0], NetOurEther, 6);
1417 NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
1418 NetCopyIP((void *)&ip->ip_src, &NetOurIP);
1419 ip->ip_sum = ~NetCksum((uchar *)ip,
1420 IP_HDR_SIZE_NO_UDP >> 1);
1422 icmph->type = ICMP_ECHO_REPLY;
1423 icmph->checksum = 0;
1424 icmph->checksum = ~NetCksum((uchar *)icmph,
1425 (len - IP_HDR_SIZE_NO_UDP) >> 1);
1426 (void) eth_send((uchar *)et,
1427 ETHER_HDR_SIZE + len);
1431 #ifdef CONFIG_CMD_TFTPPUT
1432 if (packet_icmp_handler)
1433 packet_icmp_handler(icmph->type, icmph->code,
1434 ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
1435 icmph->un.data, ntohs(ip->udp_len));
1442 NetReceive(volatile uchar *inpkt, int len)
1451 #if defined(CONFIG_CMD_CDP)
1454 ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
1456 debug("packet received\n");
1458 NetRxPacket = inpkt;
1459 NetRxPacketLen = len;
1460 et = (Ethernet_t *)inpkt;
1462 /* too small packet? */
1463 if (len < ETHER_HDR_SIZE)
1468 (*push_packet)(inpkt, len);
1473 #if defined(CONFIG_CMD_CDP)
1474 /* keep track if packet is CDP */
1475 iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0;
1478 myvlanid = ntohs(NetOurVLAN);
1479 if (myvlanid == (ushort)-1)
1480 myvlanid = VLAN_NONE;
1481 mynvlanid = ntohs(NetOurNativeVLAN);
1482 if (mynvlanid == (ushort)-1)
1483 mynvlanid = VLAN_NONE;
1485 x = ntohs(et->et_protlen);
1487 debug("packet received\n");
1491 * Got a 802 packet. Check the other protocol field.
1493 x = ntohs(et->et_prot);
1495 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
1496 len -= E802_HDR_SIZE;
1498 } else if (x != PROT_VLAN) { /* normal packet */
1499 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
1500 len -= ETHER_HDR_SIZE;
1502 } else { /* VLAN packet */
1503 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
1505 debug("VLAN packet received\n");
1507 /* too small packet? */
1508 if (len < VLAN_ETHER_HDR_SIZE)
1511 /* if no VLAN active */
1512 if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
1513 #if defined(CONFIG_CMD_CDP)
1519 cti = ntohs(vet->vet_tag);
1520 vlanid = cti & VLAN_IDMASK;
1521 x = ntohs(vet->vet_type);
1523 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
1524 len -= VLAN_ETHER_HDR_SIZE;
1527 debug("Receive from protocol 0x%x\n", x);
1529 #if defined(CONFIG_CMD_CDP)
1531 CDPHandler((uchar *)ip, len);
1536 if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1537 if (vlanid == VLAN_NONE)
1538 vlanid = (mynvlanid & VLAN_IDMASK);
1540 if (vlanid != (myvlanid & VLAN_IDMASK))
1548 * We have to deal with two types of ARP packets:
1549 * - REQUEST packets will be answered by sending our
1550 * IP address - if we know it.
1551 * - REPLY packates are expected only after we asked
1552 * for the TFTP server's or the gateway's ethernet
1553 * address; so if we receive such a packet, we set
1554 * the server ethernet address
1559 if (len < ARP_HDR_SIZE) {
1560 printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1563 if (ntohs(arp->ar_hrd) != ARP_ETHER)
1565 if (ntohs(arp->ar_pro) != PROT_IP)
1567 if (arp->ar_hln != 6)
1569 if (arp->ar_pln != 4)
1575 if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
1578 switch (ntohs(arp->ar_op)) {
1580 /* reply with our IP address */
1581 debug("Got ARP REQUEST, return our IP\n");
1583 pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
1584 arp->ar_op = htons(ARPOP_REPLY);
1585 memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
1586 NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
1587 memcpy(&arp->ar_data[0], NetOurEther, 6);
1588 NetCopyIP(&arp->ar_data[6], &NetOurIP);
1589 (void) eth_send((uchar *)et,
1590 (pkt - (uchar *)et) + ARP_HDR_SIZE);
1593 case ARPOP_REPLY: /* arp reply */
1594 /* are we waiting for a reply */
1595 if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
1598 #ifdef CONFIG_KEEP_SERVERADDR
1599 if (NetServerIP == NetArpWaitPacketIP) {
1601 sprintf(buf, "%pM", arp->ar_data);
1602 setenv("serveraddr", buf);
1606 debug("Got ARP REPLY, set server/gtwy eth addr (%pM)\n",
1609 tmp = NetReadIP(&arp->ar_data[6]);
1611 /* matched waiting packet's address */
1612 if (tmp == NetArpWaitReplyIP) {
1614 /* save address for later use */
1615 memcpy(NetArpWaitPacketMAC,
1616 &arp->ar_data[0], 6);
1618 #ifdef CONFIG_NETCONSOLE
1619 (*packetHandler)(0, 0, 0, 0, 0);
1621 /* modify header, and transmit it */
1622 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
1623 (void) eth_send(NetArpWaitTxPacket,
1624 NetArpWaitTxPacketSize);
1626 /* no arp request pending now */
1627 NetArpWaitPacketIP = 0;
1628 NetArpWaitTxPacketSize = 0;
1629 NetArpWaitPacketMAC = NULL;
1634 debug("Unexpected ARP opcode 0x%x\n",
1640 #ifdef CONFIG_CMD_RARP
1642 debug("Got RARP\n");
1644 if (len < ARP_HDR_SIZE) {
1645 printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1649 if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
1650 (ntohs(arp->ar_hrd) != ARP_ETHER) ||
1651 (ntohs(arp->ar_pro) != PROT_IP) ||
1652 (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
1654 puts("invalid RARP header\n");
1656 NetCopyIP(&NetOurIP, &arp->ar_data[16]);
1657 if (NetServerIP == 0)
1658 NetCopyIP(&NetServerIP, &arp->ar_data[6]);
1659 memcpy(NetServerEther, &arp->ar_data[0], 6);
1661 (*packetHandler)(0, 0, 0, 0, 0);
1667 /* Before we start poking the header, make sure it is there */
1668 if (len < IP_HDR_SIZE) {
1669 debug("len bad %d < %lu\n", len, (ulong)IP_HDR_SIZE);
1672 /* Check the packet length */
1673 if (len < ntohs(ip->ip_len)) {
1674 printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
1677 len = ntohs(ip->ip_len);
1678 debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
1680 /* Can't deal with anything except IPv4 */
1681 if ((ip->ip_hl_v & 0xf0) != 0x40)
1683 /* Can't deal with IP options (headers != 20 bytes) */
1684 if ((ip->ip_hl_v & 0x0f) > 0x05)
1686 /* Check the Checksum of the header */
1687 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
1688 puts("checksum bad\n");
1691 /* If it is not for us, ignore it */
1692 tmp = NetReadIP(&ip->ip_dst);
1693 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
1694 #ifdef CONFIG_MCAST_TFTP
1695 if (Mcast_addr != tmp)
1699 /* Read source IP address for later use */
1700 src_ip = NetReadIP(&ip->ip_src);
1702 * The function returns the unchanged packet if it's not
1703 * a fragment, and either the complete packet or NULL if
1704 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
1706 ip = NetDefragment(ip, &len);
1710 * watch for ICMP host redirects
1712 * There is no real handler code (yet). We just watch
1713 * for ICMP host redirect messages. In case anybody
1714 * sees these messages: please contact me
1715 * (wd@denx.de), or - even better - send me the
1716 * necessary fixes :-)
1718 * Note: in all cases where I have seen this so far
1719 * it was a problem with the router configuration,
1720 * for instance when a router was configured in the
1721 * BOOTP reply, but the TFTP server was on the same
1722 * subnet. So this is probably a warning that your
1723 * configuration might be wrong. But I'm not really
1724 * sure if there aren't any other situations.
1726 * Simon Glass <sjg@chromium.org>: We get an ICMP when
1727 * we send a tftp packet to a dead connection, or when
1728 * there is no server at the other end.
1730 if (ip->ip_p == IPPROTO_ICMP) {
1731 receive_icmp(ip, len, src_ip, et);
1733 } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
1737 #ifdef CONFIG_UDP_CHECKSUM
1738 if (ip->udp_xsum != 0) {
1744 xsum += (ntohs(ip->udp_len));
1745 xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1746 xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
1747 xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1748 xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
1750 sumlen = ntohs(ip->udp_len);
1751 sumptr = (ushort *) &(ip->udp_src);
1753 while (sumlen > 1) {
1756 sumdata = *sumptr++;
1757 xsum += ntohs(sumdata);
1763 sumdata = *(unsigned char *) sumptr;
1764 sumdata = (sumdata << 8) & 0xff00;
1767 while ((xsum >> 16) != 0) {
1768 xsum = (xsum & 0x0000ffff) +
1769 ((xsum >> 16) & 0x0000ffff);
1771 if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1772 printf(" UDP wrong checksum %08lx %08x\n",
1773 xsum, ntohs(ip->udp_xsum));
1780 #ifdef CONFIG_NETCONSOLE
1781 nc_input_packet((uchar *)ip + IP_HDR_SIZE,
1784 ntohs(ip->udp_len) - 8);
1787 * IP header OK. Pass the packet to the current handler.
1789 (*packetHandler)((uchar *)ip + IP_HDR_SIZE,
1793 ntohs(ip->udp_len) - 8);
1799 /**********************************************************************/
1801 static int net_check_prereq(enum proto_t protocol)
1805 #if defined(CONFIG_CMD_PING)
1807 if (NetPingIP == 0) {
1808 puts("*** ERROR: ping address not given\n");
1813 #if defined(CONFIG_CMD_SNTP)
1815 if (NetNtpServerIP == 0) {
1816 puts("*** ERROR: NTP server address not given\n");
1821 #if defined(CONFIG_CMD_DNS)
1823 if (NetOurDNSIP == 0) {
1824 puts("*** ERROR: DNS server address not given\n");
1829 #if defined(CONFIG_CMD_NFS)
1834 if (NetServerIP == 0) {
1835 puts("*** ERROR: `serverip' not set\n");
1838 #if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
1839 defined(CONFIG_CMD_DNS)
1846 if (NetOurIP == 0) {
1847 puts("*** ERROR: `ipaddr' not set\n");
1852 #ifdef CONFIG_CMD_RARP
1858 if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
1859 extern int eth_get_dev_index(void);
1860 int num = eth_get_dev_index();
1864 puts("*** ERROR: No ethernet found.\n");
1867 puts("*** ERROR: `ethaddr' not set\n");
1870 printf("*** ERROR: `eth%daddr' not set\n",
1884 /**********************************************************************/
1887 NetCksumOk(uchar *ptr, int len)
1889 return !((NetCksum(ptr, len) + 1) & 0xfffe);
1894 NetCksum(uchar *ptr, int len)
1897 ushort *p = (ushort *)ptr;
1902 xsum = (xsum & 0xffff) + (xsum >> 16);
1903 xsum = (xsum & 0xffff) + (xsum >> 16);
1904 return xsum & 0xffff;
1912 myvlanid = ntohs(NetOurVLAN);
1913 if (myvlanid == (ushort)-1)
1914 myvlanid = VLAN_NONE;
1916 return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
1917 VLAN_ETHER_HDR_SIZE;
1921 NetSetEther(volatile uchar *xet, uchar * addr, uint prot)
1923 Ethernet_t *et = (Ethernet_t *)xet;
1926 myvlanid = ntohs(NetOurVLAN);
1927 if (myvlanid == (ushort)-1)
1928 myvlanid = VLAN_NONE;
1930 memcpy(et->et_dest, addr, 6);
1931 memcpy(et->et_src, NetOurEther, 6);
1932 if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1933 et->et_protlen = htons(prot);
1934 return ETHER_HDR_SIZE;
1936 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1938 vet->vet_vlan_type = htons(PROT_VLAN);
1939 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1940 vet->vet_type = htons(prot);
1941 return VLAN_ETHER_HDR_SIZE;
1946 NetSetIP(volatile uchar *xip, IPaddr_t dest, int dport, int sport, int len)
1948 IP_t *ip = (IP_t *)xip;
1951 * If the data is an odd number of bytes, zero the
1952 * byte after the last byte so that the checksum
1956 xip[IP_HDR_SIZE + len] = 0;
1959 * Construct an IP and UDP header.
1960 * (need to set no fragment bit - XXX)
1962 /* IP_HDR_SIZE / 4 (not including UDP) */
1965 ip->ip_len = htons(IP_HDR_SIZE + len);
1966 ip->ip_id = htons(NetIPID++);
1967 ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */
1969 ip->ip_p = 17; /* UDP */
1971 /* already in network byte order */
1972 NetCopyIP((void *)&ip->ip_src, &NetOurIP);
1974 NetCopyIP((void *)&ip->ip_dst, &dest);
1975 ip->udp_src = htons(sport);
1976 ip->udp_dst = htons(dport);
1977 ip->udp_len = htons(8 + len);
1979 ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1982 void copy_filename(char *dst, const char *src, int size)
1984 if (*src && (*src == '"')) {
1989 while ((--size > 0) && *src && (*src != '"'))
1994 #if defined(CONFIG_CMD_NFS) || \
1995 defined(CONFIG_CMD_SNTP) || \
1996 defined(CONFIG_CMD_DNS)
1998 * make port a little random (1024-17407)
1999 * This keeps the math somewhat trivial to compute, and seems to work with
2000 * all supported protocols/clients/servers
2002 unsigned int random_port(void)
2004 return 1024 + (get_timer(0) % 0x4000);
2008 void ip_to_string(IPaddr_t x, char *s)
2011 sprintf(s, "%d.%d.%d.%d",
2012 (int) ((x >> 24) & 0xff),
2013 (int) ((x >> 16) & 0xff),
2014 (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
2018 void VLAN_to_string(ushort x, char *s)
2022 if (x == (ushort)-1)
2028 sprintf(s, "%d", x & VLAN_IDMASK);
2031 ushort string_to_VLAN(const char *s)
2036 return htons(VLAN_NONE);
2038 if (*s < '0' || *s > '9')
2041 id = (ushort)simple_strtoul(s, NULL, 10);
2046 ushort getenv_VLAN(char *var)
2048 return string_to_VLAN(getenv(var));