xref: /rk3399_rockchip-uboot/net/net.c (revision 2eede1f363b485a9b2b49ac097b9a24256716c8b)
1 /*
2  *	Copied from Linux Monitor (LiMon) - Networking.
3  *
4  *	Copyright 1994 - 2000 Neil Russell.
5  *	(See License)
6  *	Copyright 2000 Roland Borde
7  *	Copyright 2000 Paolo Scaffardi
8  *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de
9  *	SPDX-License-Identifier:	GPL-2.0
10  */
11 
12 /*
13  * General Desription:
14  *
15  * The user interface supports commands for BOOTP, RARP, and TFTP.
16  * Also, we support ARP internally. Depending on available data,
17  * these interact as follows:
18  *
19  * BOOTP:
20  *
21  *	Prerequisites:	- own ethernet address
22  *	We want:	- own IP address
23  *			- TFTP server IP address
24  *			- name of bootfile
25  *	Next step:	ARP
26  *
27  * LINK_LOCAL:
28  *
29  *	Prerequisites:	- own ethernet address
30  *	We want:	- own IP address
31  *	Next step:	ARP
32  *
33  * RARP:
34  *
35  *	Prerequisites:	- own ethernet address
36  *	We want:	- own IP address
37  *			- TFTP server IP address
38  *	Next step:	ARP
39  *
40  * ARP:
41  *
42  *	Prerequisites:	- own ethernet address
43  *			- own IP address
44  *			- TFTP server IP address
45  *	We want:	- TFTP server ethernet address
46  *	Next step:	TFTP
47  *
48  * DHCP:
49  *
50  *     Prerequisites:	- own ethernet address
51  *     We want:		- IP, Netmask, ServerIP, Gateway IP
52  *			- bootfilename, lease time
53  *     Next step:	- TFTP
54  *
55  * TFTP:
56  *
57  *	Prerequisites:	- own ethernet address
58  *			- own IP address
59  *			- TFTP server IP address
60  *			- TFTP server ethernet address
61  *			- name of bootfile (if unknown, we use a default name
62  *			  derived from our own IP address)
63  *	We want:	- load the boot file
64  *	Next step:	none
65  *
66  * NFS:
67  *
68  *	Prerequisites:	- own ethernet address
69  *			- own IP address
70  *			- name of bootfile (if unknown, we use a default name
71  *			  derived from our own IP address)
72  *	We want:	- load the boot file
73  *	Next step:	none
74  *
75  * SNTP:
76  *
77  *	Prerequisites:	- own ethernet address
78  *			- own IP address
79  *	We want:	- network time
80  *	Next step:	none
81  */
82 
83 
84 #include <common.h>
85 #include <command.h>
86 #include <environment.h>
87 #include <net.h>
88 #if defined(CONFIG_STATUS_LED)
89 #include <miiphy.h>
90 #include <status_led.h>
91 #endif
92 #include <watchdog.h>
93 #include <linux/compiler.h>
94 #include "arp.h"
95 #include "bootp.h"
96 #include "cdp.h"
97 #if defined(CONFIG_CMD_DNS)
98 #include "dns.h"
99 #endif
100 #include "link_local.h"
101 #include "nfs.h"
102 #include "ping.h"
103 #include "rarp.h"
104 #if defined(CONFIG_CMD_SNTP)
105 #include "sntp.h"
106 #endif
107 #include "tftp.h"
108 
109 DECLARE_GLOBAL_DATA_PTR;
110 
111 /** BOOTP EXTENTIONS **/
112 
113 /* Our subnet mask (0=unknown) */
114 IPaddr_t	NetOurSubnetMask;
115 /* Our gateways IP address */
116 IPaddr_t	NetOurGatewayIP;
117 /* Our DNS IP address */
118 IPaddr_t	NetOurDNSIP;
119 #if defined(CONFIG_BOOTP_DNS2)
120 /* Our 2nd DNS IP address */
121 IPaddr_t	NetOurDNS2IP;
122 #endif
123 /* Our NIS domain */
124 char		NetOurNISDomain[32] = {0,};
125 /* Our hostname */
126 char		NetOurHostName[32] = {0,};
127 /* Our bootpath */
128 char		NetOurRootPath[64] = {0,};
129 /* Our bootfile size in blocks */
130 ushort		NetBootFileSize;
131 
132 #ifdef CONFIG_MCAST_TFTP	/* Multicast TFTP */
133 IPaddr_t Mcast_addr;
134 #endif
135 
136 /** END OF BOOTP EXTENTIONS **/
137 
138 /* The actual transferred size of the bootfile (in bytes) */
139 ulong		NetBootFileXferSize;
140 /* Our ethernet address */
141 uchar		NetOurEther[6];
142 /* Boot server enet address */
143 uchar		NetServerEther[6];
144 /* Our IP addr (0 = unknown) */
145 IPaddr_t	NetOurIP;
146 /* Server IP addr (0 = unknown) */
147 IPaddr_t	NetServerIP;
148 /* Current receive packet */
149 uchar *NetRxPacket;
150 /* Current rx packet length */
151 int		NetRxPacketLen;
152 /* IP packet ID */
153 unsigned	NetIPID;
154 /* Ethernet bcast address */
155 uchar		NetBcastAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
156 uchar		NetEtherNullAddr[6];
157 #ifdef CONFIG_API
158 void		(*push_packet)(void *, int len) = 0;
159 #endif
160 /* Network loop state */
161 enum net_loop_state net_state;
162 /* Tried all network devices */
163 int		NetRestartWrap;
164 /* Network loop restarted */
165 static int	NetRestarted;
166 /* At least one device configured */
167 static int	NetDevExists;
168 
169 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
170 /* default is without VLAN */
171 ushort		NetOurVLAN = 0xFFFF;
172 /* ditto */
173 ushort		NetOurNativeVLAN = 0xFFFF;
174 
175 /* Boot File name */
176 char		BootFile[128];
177 
178 #if defined(CONFIG_CMD_SNTP)
179 /* NTP server IP address */
180 IPaddr_t	NetNtpServerIP;
181 /* offset time from UTC */
182 int		NetTimeOffset;
183 #endif
184 
185 static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
186 #ifdef CONFIG_DM_ETH
187 /* Receive packets */
188 uchar *net_rx_packets[PKTBUFSRX];
189 #else
190 /* Receive packet */
191 uchar *NetRxPackets[PKTBUFSRX];
192 #endif
193 /* Current UDP RX packet handler */
194 static rxhand_f *udp_packet_handler;
195 /* Current ARP RX packet handler */
196 static rxhand_f *arp_packet_handler;
197 #ifdef CONFIG_CMD_TFTPPUT
198 /* Current ICMP rx handler */
199 static rxhand_icmp_f *packet_icmp_handler;
200 #endif
201 /* Current timeout handler */
202 static thand_f *timeHandler;
203 /* Time base value */
204 static ulong	timeStart;
205 /* Current timeout value */
206 static ulong	timeDelta;
207 /* THE transmit packet */
208 uchar *NetTxPacket;
209 
210 static int net_check_prereq(enum proto_t protocol);
211 
212 static int NetTryCount;
213 
214 int __maybe_unused net_busy_flag;
215 
216 /**********************************************************************/
217 
218 static int on_bootfile(const char *name, const char *value, enum env_op op,
219 	int flags)
220 {
221 	switch (op) {
222 	case env_op_create:
223 	case env_op_overwrite:
224 		copy_filename(BootFile, value, sizeof(BootFile));
225 		break;
226 	default:
227 		break;
228 	}
229 
230 	return 0;
231 }
232 U_BOOT_ENV_CALLBACK(bootfile, on_bootfile);
233 
234 /*
235  * Check if autoload is enabled. If so, use either NFS or TFTP to download
236  * the boot file.
237  */
238 void net_auto_load(void)
239 {
240 #if defined(CONFIG_CMD_NFS)
241 	const char *s = getenv("autoload");
242 
243 	if (s != NULL && strcmp(s, "NFS") == 0) {
244 		/*
245 		 * Use NFS to load the bootfile.
246 		 */
247 		NfsStart();
248 		return;
249 	}
250 #endif
251 	if (getenv_yesno("autoload") == 0) {
252 		/*
253 		 * Just use BOOTP/RARP to configure system;
254 		 * Do not use TFTP to load the bootfile.
255 		 */
256 		net_set_state(NETLOOP_SUCCESS);
257 		return;
258 	}
259 	TftpStart(TFTPGET);
260 }
261 
262 static void NetInitLoop(void)
263 {
264 	static int env_changed_id;
265 	int env_id = get_env_id();
266 
267 	/* update only when the environment has changed */
268 	if (env_changed_id != env_id) {
269 		NetOurIP = getenv_IPaddr("ipaddr");
270 		NetOurGatewayIP = getenv_IPaddr("gatewayip");
271 		NetOurSubnetMask = getenv_IPaddr("netmask");
272 		NetServerIP = getenv_IPaddr("serverip");
273 		NetOurNativeVLAN = getenv_VLAN("nvlan");
274 		NetOurVLAN = getenv_VLAN("vlan");
275 #if defined(CONFIG_CMD_DNS)
276 		NetOurDNSIP = getenv_IPaddr("dnsip");
277 #endif
278 		env_changed_id = env_id;
279 	}
280 	if (eth_get_dev())
281 		memcpy(NetOurEther, eth_get_ethaddr(), 6);
282 
283 	return;
284 }
285 
286 static void net_clear_handlers(void)
287 {
288 	net_set_udp_handler(NULL);
289 	net_set_arp_handler(NULL);
290 	NetSetTimeout(0, NULL);
291 }
292 
293 static void net_cleanup_loop(void)
294 {
295 	net_clear_handlers();
296 }
297 
298 void net_init(void)
299 {
300 	static int first_call = 1;
301 
302 	if (first_call) {
303 		/*
304 		 *	Setup packet buffers, aligned correctly.
305 		 */
306 		int i;
307 
308 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
309 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
310 #ifdef CONFIG_DM_ETH
311 		for (i = 0; i < PKTBUFSRX; i++) {
312 			net_rx_packets[i] = NetTxPacket + (i + 1) *
313 				PKTSIZE_ALIGN;
314 		}
315 #else
316 		for (i = 0; i < PKTBUFSRX; i++)
317 			NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
318 #endif
319 		ArpInit();
320 		net_clear_handlers();
321 
322 		/* Only need to setup buffer pointers once. */
323 		first_call = 0;
324 	}
325 
326 	NetInitLoop();
327 }
328 
329 /**********************************************************************/
330 /*
331  *	Main network processing loop.
332  */
333 
334 int NetLoop(enum proto_t protocol)
335 {
336 	int ret = -1;
337 
338 	NetRestarted = 0;
339 	NetDevExists = 0;
340 	NetTryCount = 1;
341 	debug_cond(DEBUG_INT_STATE, "--- NetLoop Entry\n");
342 
343 	bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
344 	net_init();
345 	if (eth_is_on_demand_init() || protocol != NETCONS) {
346 		eth_halt();
347 		eth_set_current();
348 		if (eth_init() < 0) {
349 			eth_halt();
350 			return -1;
351 		}
352 	} else
353 		eth_init_state_only();
354 
355 restart:
356 #ifdef CONFIG_USB_KEYBOARD
357 	net_busy_flag = 0;
358 #endif
359 	net_set_state(NETLOOP_CONTINUE);
360 
361 	/*
362 	 *	Start the ball rolling with the given start function.  From
363 	 *	here on, this code is a state machine driven by received
364 	 *	packets and timer events.
365 	 */
366 	debug_cond(DEBUG_INT_STATE, "--- NetLoop Init\n");
367 	NetInitLoop();
368 
369 	switch (net_check_prereq(protocol)) {
370 	case 1:
371 		/* network not configured */
372 		eth_halt();
373 		return -1;
374 
375 	case 2:
376 		/* network device not configured */
377 		break;
378 
379 	case 0:
380 		NetDevExists = 1;
381 		NetBootFileXferSize = 0;
382 		switch (protocol) {
383 		case TFTPGET:
384 #ifdef CONFIG_CMD_TFTPPUT
385 		case TFTPPUT:
386 #endif
387 			/* always use ARP to get server ethernet address */
388 			TftpStart(protocol);
389 			break;
390 #ifdef CONFIG_CMD_TFTPSRV
391 		case TFTPSRV:
392 			TftpStartServer();
393 			break;
394 #endif
395 #if defined(CONFIG_CMD_DHCP)
396 		case DHCP:
397 			BootpReset();
398 			NetOurIP = 0;
399 			DhcpRequest();		/* Basically same as BOOTP */
400 			break;
401 #endif
402 
403 		case BOOTP:
404 			BootpReset();
405 			NetOurIP = 0;
406 			BootpRequest();
407 			break;
408 
409 #if defined(CONFIG_CMD_RARP)
410 		case RARP:
411 			RarpTry = 0;
412 			NetOurIP = 0;
413 			RarpRequest();
414 			break;
415 #endif
416 #if defined(CONFIG_CMD_PING)
417 		case PING:
418 			ping_start();
419 			break;
420 #endif
421 #if defined(CONFIG_CMD_NFS)
422 		case NFS:
423 			NfsStart();
424 			break;
425 #endif
426 #if defined(CONFIG_CMD_CDP)
427 		case CDP:
428 			CDPStart();
429 			break;
430 #endif
431 #if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD)
432 		case NETCONS:
433 			NcStart();
434 			break;
435 #endif
436 #if defined(CONFIG_CMD_SNTP)
437 		case SNTP:
438 			SntpStart();
439 			break;
440 #endif
441 #if defined(CONFIG_CMD_DNS)
442 		case DNS:
443 			DnsStart();
444 			break;
445 #endif
446 #if defined(CONFIG_CMD_LINK_LOCAL)
447 		case LINKLOCAL:
448 			link_local_start();
449 			break;
450 #endif
451 		default:
452 			break;
453 		}
454 
455 		break;
456 	}
457 
458 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
459 #if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
460 	defined(CONFIG_STATUS_LED)			&& \
461 	defined(STATUS_LED_RED)
462 	/*
463 	 * Echo the inverted link state to the fault LED.
464 	 */
465 	if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
466 		status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
467 	else
468 		status_led_set(STATUS_LED_RED, STATUS_LED_ON);
469 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
470 #endif /* CONFIG_MII, ... */
471 #ifdef CONFIG_USB_KEYBOARD
472 	net_busy_flag = 1;
473 #endif
474 
475 	/*
476 	 *	Main packet reception loop.  Loop receiving packets until
477 	 *	someone sets `net_state' to a state that terminates.
478 	 */
479 	for (;;) {
480 		WATCHDOG_RESET();
481 #ifdef CONFIG_SHOW_ACTIVITY
482 		show_activity(1);
483 #endif
484 		/*
485 		 *	Check the ethernet for a new packet.  The ethernet
486 		 *	receive routine will process it.
487 		 */
488 		eth_rx();
489 
490 		/*
491 		 *	Abort if ctrl-c was pressed.
492 		 */
493 		if (ctrlc()) {
494 			/* cancel any ARP that may not have completed */
495 			NetArpWaitPacketIP = 0;
496 
497 			net_cleanup_loop();
498 			eth_halt();
499 			/* Invalidate the last protocol */
500 			eth_set_last_protocol(BOOTP);
501 
502 			puts("\nAbort\n");
503 			/* include a debug print as well incase the debug
504 			   messages are directed to stderr */
505 			debug_cond(DEBUG_INT_STATE, "--- NetLoop Abort!\n");
506 			goto done;
507 		}
508 
509 		ArpTimeoutCheck();
510 
511 		/*
512 		 *	Check for a timeout, and run the timeout handler
513 		 *	if we have one.
514 		 */
515 		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
516 			thand_f *x;
517 
518 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
519 #if	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)	&& \
520 	defined(CONFIG_STATUS_LED)			&& \
521 	defined(STATUS_LED_RED)
522 			/*
523 			 * Echo the inverted link state to the fault LED.
524 			 */
525 			if (miiphy_link(eth_get_dev()->name,
526 				       CONFIG_SYS_FAULT_MII_ADDR)) {
527 				status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
528 			} else {
529 				status_led_set(STATUS_LED_RED, STATUS_LED_ON);
530 			}
531 #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
532 #endif /* CONFIG_MII, ... */
533 			debug_cond(DEBUG_INT_STATE, "--- NetLoop timeout\n");
534 			x = timeHandler;
535 			timeHandler = (thand_f *)0;
536 			(*x)();
537 		}
538 
539 		if (net_state == NETLOOP_FAIL)
540 			NetStartAgain();
541 
542 		switch (net_state) {
543 
544 		case NETLOOP_RESTART:
545 			NetRestarted = 1;
546 			goto restart;
547 
548 		case NETLOOP_SUCCESS:
549 			net_cleanup_loop();
550 			if (NetBootFileXferSize > 0) {
551 				printf("Bytes transferred = %ld (%lx hex)\n",
552 					NetBootFileXferSize,
553 					NetBootFileXferSize);
554 				setenv_hex("filesize", NetBootFileXferSize);
555 				setenv_hex("fileaddr", load_addr);
556 			}
557 			if (protocol != NETCONS)
558 				eth_halt();
559 			else
560 				eth_halt_state_only();
561 
562 			eth_set_last_protocol(protocol);
563 
564 			ret = NetBootFileXferSize;
565 			debug_cond(DEBUG_INT_STATE, "--- NetLoop Success!\n");
566 			goto done;
567 
568 		case NETLOOP_FAIL:
569 			net_cleanup_loop();
570 			/* Invalidate the last protocol */
571 			eth_set_last_protocol(BOOTP);
572 			debug_cond(DEBUG_INT_STATE, "--- NetLoop Fail!\n");
573 			goto done;
574 
575 		case NETLOOP_CONTINUE:
576 			continue;
577 		}
578 	}
579 
580 done:
581 #ifdef CONFIG_USB_KEYBOARD
582 	net_busy_flag = 0;
583 #endif
584 #ifdef CONFIG_CMD_TFTPPUT
585 	/* Clear out the handlers */
586 	net_set_udp_handler(NULL);
587 	net_set_icmp_handler(NULL);
588 #endif
589 	return ret;
590 }
591 
592 /**********************************************************************/
593 
594 static void
595 startAgainTimeout(void)
596 {
597 	net_set_state(NETLOOP_RESTART);
598 }
599 
600 void NetStartAgain(void)
601 {
602 	char *nretry;
603 	int retry_forever = 0;
604 	unsigned long retrycnt = 0;
605 
606 	nretry = getenv("netretry");
607 	if (nretry) {
608 		if (!strcmp(nretry, "yes"))
609 			retry_forever = 1;
610 		else if (!strcmp(nretry, "no"))
611 			retrycnt = 0;
612 		else if (!strcmp(nretry, "once"))
613 			retrycnt = 1;
614 		else
615 			retrycnt = simple_strtoul(nretry, NULL, 0);
616 	} else {
617 		retrycnt = 0;
618 		retry_forever = 0;
619 	}
620 
621 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
622 		eth_halt();
623 		net_set_state(NETLOOP_FAIL);
624 		return;
625 	}
626 
627 	NetTryCount++;
628 
629 	eth_halt();
630 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
631 	eth_try_another(!NetRestarted);
632 #endif
633 	eth_init();
634 	if (NetRestartWrap) {
635 		NetRestartWrap = 0;
636 		if (NetDevExists) {
637 			NetSetTimeout(10000UL, startAgainTimeout);
638 			net_set_udp_handler(NULL);
639 		} else {
640 			net_set_state(NETLOOP_FAIL);
641 		}
642 	} else {
643 		net_set_state(NETLOOP_RESTART);
644 	}
645 }
646 
647 /**********************************************************************/
648 /*
649  *	Miscelaneous bits.
650  */
651 
652 static void dummy_handler(uchar *pkt, unsigned dport,
653 			IPaddr_t sip, unsigned sport,
654 			unsigned len)
655 {
656 }
657 
658 rxhand_f *net_get_udp_handler(void)
659 {
660 	return udp_packet_handler;
661 }
662 
663 void net_set_udp_handler(rxhand_f *f)
664 {
665 	debug_cond(DEBUG_INT_STATE, "--- NetLoop UDP handler set (%p)\n", f);
666 	if (f == NULL)
667 		udp_packet_handler = dummy_handler;
668 	else
669 		udp_packet_handler = f;
670 }
671 
672 rxhand_f *net_get_arp_handler(void)
673 {
674 	return arp_packet_handler;
675 }
676 
677 void net_set_arp_handler(rxhand_f *f)
678 {
679 	debug_cond(DEBUG_INT_STATE, "--- NetLoop ARP handler set (%p)\n", f);
680 	if (f == NULL)
681 		arp_packet_handler = dummy_handler;
682 	else
683 		arp_packet_handler = f;
684 }
685 
686 #ifdef CONFIG_CMD_TFTPPUT
687 void net_set_icmp_handler(rxhand_icmp_f *f)
688 {
689 	packet_icmp_handler = f;
690 }
691 #endif
692 
693 void
694 NetSetTimeout(ulong iv, thand_f *f)
695 {
696 	if (iv == 0) {
697 		debug_cond(DEBUG_INT_STATE,
698 			"--- NetLoop timeout handler cancelled\n");
699 		timeHandler = (thand_f *)0;
700 	} else {
701 		debug_cond(DEBUG_INT_STATE,
702 			"--- NetLoop timeout handler set (%p)\n", f);
703 		timeHandler = f;
704 		timeStart = get_timer(0);
705 		timeDelta = iv * CONFIG_SYS_HZ / 1000;
706 	}
707 }
708 
709 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport,
710 		int payload_len)
711 {
712 	uchar *pkt;
713 	int eth_hdr_size;
714 	int pkt_hdr_size;
715 
716 	/* make sure the NetTxPacket is initialized (NetInit() was called) */
717 	assert(NetTxPacket != NULL);
718 	if (NetTxPacket == NULL)
719 		return -1;
720 
721 	/* convert to new style broadcast */
722 	if (dest == 0)
723 		dest = 0xFFFFFFFF;
724 
725 	/* if broadcast, make the ether address a broadcast and don't do ARP */
726 	if (dest == 0xFFFFFFFF)
727 		ether = NetBcastAddr;
728 
729 	pkt = (uchar *)NetTxPacket;
730 
731 	eth_hdr_size = NetSetEther(pkt, ether, PROT_IP);
732 	pkt += eth_hdr_size;
733 	net_set_udp_header(pkt, dest, dport, sport, payload_len);
734 	pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
735 
736 	/* if MAC address was not discovered yet, do an ARP request */
737 	if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
738 		debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &dest);
739 
740 		/* save the ip and eth addr for the packet to send after arp */
741 		NetArpWaitPacketIP = dest;
742 		NetArpWaitPacketMAC = ether;
743 
744 		/* size of the waiting packet */
745 		NetArpWaitTxPacketSize = pkt_hdr_size + payload_len;
746 
747 		/* and do the ARP request */
748 		NetArpWaitTry = 1;
749 		NetArpWaitTimerStart = get_timer(0);
750 		ArpRequest();
751 		return 1;	/* waiting */
752 	} else {
753 		debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n",
754 			&dest, ether);
755 		NetSendPacket(NetTxPacket, pkt_hdr_size + payload_len);
756 		return 0;	/* transmitted */
757 	}
758 }
759 
760 #ifdef CONFIG_IP_DEFRAG
761 /*
762  * This function collects fragments in a single packet, according
763  * to the algorithm in RFC815. It returns NULL or the pointer to
764  * a complete packet, in static storage
765  */
766 #ifndef CONFIG_NET_MAXDEFRAG
767 #define CONFIG_NET_MAXDEFRAG 16384
768 #endif
769 /*
770  * MAXDEFRAG, above, is chosen in the config file and  is real data
771  * so we need to add the NFS overhead, which is more than TFTP.
772  * To use sizeof in the internal unnamed structures, we need a real
773  * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately).
774  * The compiler doesn't complain nor allocates the actual structure
775  */
776 static struct rpc_t rpc_specimen;
777 #define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply))
778 
779 #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE)
780 
781 /*
782  * this is the packet being assembled, either data or frag control.
783  * Fragments go by 8 bytes, so this union must be 8 bytes long
784  */
785 struct hole {
786 	/* first_byte is address of this structure */
787 	u16 last_byte;	/* last byte in this hole + 1 (begin of next hole) */
788 	u16 next_hole;	/* index of next (in 8-b blocks), 0 == none */
789 	u16 prev_hole;	/* index of prev, 0 == none */
790 	u16 unused;
791 };
792 
793 static struct ip_udp_hdr *__NetDefragment(struct ip_udp_hdr *ip, int *lenp)
794 {
795 	static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
796 	static u16 first_hole, total_len;
797 	struct hole *payload, *thisfrag, *h, *newh;
798 	struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff;
799 	uchar *indata = (uchar *)ip;
800 	int offset8, start, len, done = 0;
801 	u16 ip_off = ntohs(ip->ip_off);
802 
803 	/* payload starts after IP header, this fragment is in there */
804 	payload = (struct hole *)(pkt_buff + IP_HDR_SIZE);
805 	offset8 =  (ip_off & IP_OFFS);
806 	thisfrag = payload + offset8;
807 	start = offset8 * 8;
808 	len = ntohs(ip->ip_len) - IP_HDR_SIZE;
809 
810 	if (start + len > IP_MAXUDP) /* fragment extends too far */
811 		return NULL;
812 
813 	if (!total_len || localip->ip_id != ip->ip_id) {
814 		/* new (or different) packet, reset structs */
815 		total_len = 0xffff;
816 		payload[0].last_byte = ~0;
817 		payload[0].next_hole = 0;
818 		payload[0].prev_hole = 0;
819 		first_hole = 0;
820 		/* any IP header will work, copy the first we received */
821 		memcpy(localip, ip, IP_HDR_SIZE);
822 	}
823 
824 	/*
825 	 * What follows is the reassembly algorithm. We use the payload
826 	 * array as a linked list of hole descriptors, as each hole starts
827 	 * at a multiple of 8 bytes. However, last byte can be whatever value,
828 	 * so it is represented as byte count, not as 8-byte blocks.
829 	 */
830 
831 	h = payload + first_hole;
832 	while (h->last_byte < start) {
833 		if (!h->next_hole) {
834 			/* no hole that far away */
835 			return NULL;
836 		}
837 		h = payload + h->next_hole;
838 	}
839 
840 	/* last fragment may be 1..7 bytes, the "+7" forces acceptance */
841 	if (offset8 + ((len + 7) / 8) <= h - payload) {
842 		/* no overlap with holes (dup fragment?) */
843 		return NULL;
844 	}
845 
846 	if (!(ip_off & IP_FLAGS_MFRAG)) {
847 		/* no more fragmentss: truncate this (last) hole */
848 		total_len = start + len;
849 		h->last_byte = start + len;
850 	}
851 
852 	/*
853 	 * There is some overlap: fix the hole list. This code doesn't
854 	 * deal with a fragment that overlaps with two different holes
855 	 * (thus being a superset of a previously-received fragment).
856 	 */
857 
858 	if ((h >= thisfrag) && (h->last_byte <= start + len)) {
859 		/* complete overlap with hole: remove hole */
860 		if (!h->prev_hole && !h->next_hole) {
861 			/* last remaining hole */
862 			done = 1;
863 		} else if (!h->prev_hole) {
864 			/* first hole */
865 			first_hole = h->next_hole;
866 			payload[h->next_hole].prev_hole = 0;
867 		} else if (!h->next_hole) {
868 			/* last hole */
869 			payload[h->prev_hole].next_hole = 0;
870 		} else {
871 			/* in the middle of the list */
872 			payload[h->next_hole].prev_hole = h->prev_hole;
873 			payload[h->prev_hole].next_hole = h->next_hole;
874 		}
875 
876 	} else if (h->last_byte <= start + len) {
877 		/* overlaps with final part of the hole: shorten this hole */
878 		h->last_byte = start;
879 
880 	} else if (h >= thisfrag) {
881 		/* overlaps with initial part of the hole: move this hole */
882 		newh = thisfrag + (len / 8);
883 		*newh = *h;
884 		h = newh;
885 		if (h->next_hole)
886 			payload[h->next_hole].prev_hole = (h - payload);
887 		if (h->prev_hole)
888 			payload[h->prev_hole].next_hole = (h - payload);
889 		else
890 			first_hole = (h - payload);
891 
892 	} else {
893 		/* fragment sits in the middle: split the hole */
894 		newh = thisfrag + (len / 8);
895 		*newh = *h;
896 		h->last_byte = start;
897 		h->next_hole = (newh - payload);
898 		newh->prev_hole = (h - payload);
899 		if (newh->next_hole)
900 			payload[newh->next_hole].prev_hole = (newh - payload);
901 	}
902 
903 	/* finally copy this fragment and possibly return whole packet */
904 	memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len);
905 	if (!done)
906 		return NULL;
907 
908 	localip->ip_len = htons(total_len);
909 	*lenp = total_len + IP_HDR_SIZE;
910 	return localip;
911 }
912 
913 static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp)
914 {
915 	u16 ip_off = ntohs(ip->ip_off);
916 	if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
917 		return ip; /* not a fragment */
918 	return __NetDefragment(ip, lenp);
919 }
920 
921 #else /* !CONFIG_IP_DEFRAG */
922 
923 static inline struct ip_udp_hdr *NetDefragment(struct ip_udp_hdr *ip, int *lenp)
924 {
925 	u16 ip_off = ntohs(ip->ip_off);
926 	if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
927 		return ip; /* not a fragment */
928 	return NULL;
929 }
930 #endif
931 
932 /**
933  * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
934  * drop others.
935  *
936  * @parma ip	IP packet containing the ICMP
937  */
938 static void receive_icmp(struct ip_udp_hdr *ip, int len,
939 			IPaddr_t src_ip, struct ethernet_hdr *et)
940 {
941 	struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
942 
943 	switch (icmph->type) {
944 	case ICMP_REDIRECT:
945 		if (icmph->code != ICMP_REDIR_HOST)
946 			return;
947 		printf(" ICMP Host Redirect to %pI4 ",
948 			&icmph->un.gateway);
949 		break;
950 	default:
951 #if defined(CONFIG_CMD_PING)
952 		ping_receive(et, ip, len);
953 #endif
954 #ifdef CONFIG_CMD_TFTPPUT
955 		if (packet_icmp_handler)
956 			packet_icmp_handler(icmph->type, icmph->code,
957 				ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
958 				icmph->un.data, ntohs(ip->udp_len));
959 #endif
960 		break;
961 	}
962 }
963 
964 void net_process_received_packet(uchar *in_packet, int len)
965 {
966 	struct ethernet_hdr *et;
967 	struct ip_udp_hdr *ip;
968 	IPaddr_t dst_ip;
969 	IPaddr_t src_ip;
970 	int eth_proto;
971 #if defined(CONFIG_CMD_CDP)
972 	int iscdp;
973 #endif
974 	ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
975 
976 	debug_cond(DEBUG_NET_PKT, "packet received\n");
977 
978 	NetRxPacket = in_packet;
979 	NetRxPacketLen = len;
980 	et = (struct ethernet_hdr *)in_packet;
981 
982 	/* too small packet? */
983 	if (len < ETHER_HDR_SIZE)
984 		return;
985 
986 #ifdef CONFIG_API
987 	if (push_packet) {
988 		(*push_packet)(in_packet, len);
989 		return;
990 	}
991 #endif
992 
993 #if defined(CONFIG_CMD_CDP)
994 	/* keep track if packet is CDP */
995 	iscdp = is_cdp_packet(et->et_dest);
996 #endif
997 
998 	myvlanid = ntohs(NetOurVLAN);
999 	if (myvlanid == (ushort)-1)
1000 		myvlanid = VLAN_NONE;
1001 	mynvlanid = ntohs(NetOurNativeVLAN);
1002 	if (mynvlanid == (ushort)-1)
1003 		mynvlanid = VLAN_NONE;
1004 
1005 	eth_proto = ntohs(et->et_protlen);
1006 
1007 	if (eth_proto < 1514) {
1008 		struct e802_hdr *et802 = (struct e802_hdr *)et;
1009 		/*
1010 		 *	Got a 802.2 packet.  Check the other protocol field.
1011 		 *	XXX VLAN over 802.2+SNAP not implemented!
1012 		 */
1013 		eth_proto = ntohs(et802->et_prot);
1014 
1015 		ip = (struct ip_udp_hdr *)(in_packet + E802_HDR_SIZE);
1016 		len -= E802_HDR_SIZE;
1017 
1018 	} else if (eth_proto != PROT_VLAN) {	/* normal packet */
1019 		ip = (struct ip_udp_hdr *)(in_packet + ETHER_HDR_SIZE);
1020 		len -= ETHER_HDR_SIZE;
1021 
1022 	} else {			/* VLAN packet */
1023 		struct vlan_ethernet_hdr *vet =
1024 			(struct vlan_ethernet_hdr *)et;
1025 
1026 		debug_cond(DEBUG_NET_PKT, "VLAN packet received\n");
1027 
1028 		/* too small packet? */
1029 		if (len < VLAN_ETHER_HDR_SIZE)
1030 			return;
1031 
1032 		/* if no VLAN active */
1033 		if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
1034 #if defined(CONFIG_CMD_CDP)
1035 				&& iscdp == 0
1036 #endif
1037 				)
1038 			return;
1039 
1040 		cti = ntohs(vet->vet_tag);
1041 		vlanid = cti & VLAN_IDMASK;
1042 		eth_proto = ntohs(vet->vet_type);
1043 
1044 		ip = (struct ip_udp_hdr *)(in_packet + VLAN_ETHER_HDR_SIZE);
1045 		len -= VLAN_ETHER_HDR_SIZE;
1046 	}
1047 
1048 	debug_cond(DEBUG_NET_PKT, "Receive from protocol 0x%x\n", eth_proto);
1049 
1050 #if defined(CONFIG_CMD_CDP)
1051 	if (iscdp) {
1052 		cdp_receive((uchar *)ip, len);
1053 		return;
1054 	}
1055 #endif
1056 
1057 	if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1058 		if (vlanid == VLAN_NONE)
1059 			vlanid = (mynvlanid & VLAN_IDMASK);
1060 		/* not matched? */
1061 		if (vlanid != (myvlanid & VLAN_IDMASK))
1062 			return;
1063 	}
1064 
1065 	switch (eth_proto) {
1066 
1067 	case PROT_ARP:
1068 		ArpReceive(et, ip, len);
1069 		break;
1070 
1071 #ifdef CONFIG_CMD_RARP
1072 	case PROT_RARP:
1073 		rarp_receive(ip, len);
1074 		break;
1075 #endif
1076 	case PROT_IP:
1077 		debug_cond(DEBUG_NET_PKT, "Got IP\n");
1078 		/* Before we start poking the header, make sure it is there */
1079 		if (len < IP_UDP_HDR_SIZE) {
1080 			debug("len bad %d < %lu\n", len,
1081 				(ulong)IP_UDP_HDR_SIZE);
1082 			return;
1083 		}
1084 		/* Check the packet length */
1085 		if (len < ntohs(ip->ip_len)) {
1086 			debug("len bad %d < %d\n", len, ntohs(ip->ip_len));
1087 			return;
1088 		}
1089 		len = ntohs(ip->ip_len);
1090 		debug_cond(DEBUG_NET_PKT, "len=%d, v=%02x\n",
1091 			len, ip->ip_hl_v & 0xff);
1092 
1093 		/* Can't deal with anything except IPv4 */
1094 		if ((ip->ip_hl_v & 0xf0) != 0x40)
1095 			return;
1096 		/* Can't deal with IP options (headers != 20 bytes) */
1097 		if ((ip->ip_hl_v & 0x0f) > 0x05)
1098 			return;
1099 		/* Check the Checksum of the header */
1100 		if (!ip_checksum_ok((uchar *)ip, IP_HDR_SIZE)) {
1101 			debug("checksum bad\n");
1102 			return;
1103 		}
1104 		/* If it is not for us, ignore it */
1105 		dst_ip = NetReadIP(&ip->ip_dst);
1106 		if (NetOurIP && dst_ip != NetOurIP && dst_ip != 0xFFFFFFFF) {
1107 #ifdef CONFIG_MCAST_TFTP
1108 			if (Mcast_addr != dst_ip)
1109 #endif
1110 				return;
1111 		}
1112 		/* Read source IP address for later use */
1113 		src_ip = NetReadIP(&ip->ip_src);
1114 		/*
1115 		 * The function returns the unchanged packet if it's not
1116 		 * a fragment, and either the complete packet or NULL if
1117 		 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
1118 		 */
1119 		ip = NetDefragment(ip, &len);
1120 		if (!ip)
1121 			return;
1122 		/*
1123 		 * watch for ICMP host redirects
1124 		 *
1125 		 * There is no real handler code (yet). We just watch
1126 		 * for ICMP host redirect messages. In case anybody
1127 		 * sees these messages: please contact me
1128 		 * (wd@denx.de), or - even better - send me the
1129 		 * necessary fixes :-)
1130 		 *
1131 		 * Note: in all cases where I have seen this so far
1132 		 * it was a problem with the router configuration,
1133 		 * for instance when a router was configured in the
1134 		 * BOOTP reply, but the TFTP server was on the same
1135 		 * subnet. So this is probably a warning that your
1136 		 * configuration might be wrong. But I'm not really
1137 		 * sure if there aren't any other situations.
1138 		 *
1139 		 * Simon Glass <sjg@chromium.org>: We get an ICMP when
1140 		 * we send a tftp packet to a dead connection, or when
1141 		 * there is no server at the other end.
1142 		 */
1143 		if (ip->ip_p == IPPROTO_ICMP) {
1144 			receive_icmp(ip, len, src_ip, et);
1145 			return;
1146 		} else if (ip->ip_p != IPPROTO_UDP) {	/* Only UDP packets */
1147 			return;
1148 		}
1149 
1150 		debug_cond(DEBUG_DEV_PKT,
1151 			"received UDP (to=%pI4, from=%pI4, len=%d)\n",
1152 			&dst_ip, &src_ip, len);
1153 
1154 #ifdef CONFIG_UDP_CHECKSUM
1155 		if (ip->udp_xsum != 0) {
1156 			ulong   xsum;
1157 			ushort *sumptr;
1158 			ushort  sumlen;
1159 
1160 			xsum  = ip->ip_p;
1161 			xsum += (ntohs(ip->udp_len));
1162 			xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1163 			xsum += (ntohl(ip->ip_src) >>  0) & 0x0000ffff;
1164 			xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1165 			xsum += (ntohl(ip->ip_dst) >>  0) & 0x0000ffff;
1166 
1167 			sumlen = ntohs(ip->udp_len);
1168 			sumptr = (ushort *) &(ip->udp_src);
1169 
1170 			while (sumlen > 1) {
1171 				ushort sumdata;
1172 
1173 				sumdata = *sumptr++;
1174 				xsum += ntohs(sumdata);
1175 				sumlen -= 2;
1176 			}
1177 			if (sumlen > 0) {
1178 				ushort sumdata;
1179 
1180 				sumdata = *(unsigned char *) sumptr;
1181 				sumdata = (sumdata << 8) & 0xff00;
1182 				xsum += sumdata;
1183 			}
1184 			while ((xsum >> 16) != 0) {
1185 				xsum = (xsum & 0x0000ffff) +
1186 				       ((xsum >> 16) & 0x0000ffff);
1187 			}
1188 			if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1189 				printf(" UDP wrong checksum %08lx %08x\n",
1190 					xsum, ntohs(ip->udp_xsum));
1191 				return;
1192 			}
1193 		}
1194 #endif
1195 
1196 
1197 #if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD)
1198 		nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE,
1199 					src_ip,
1200 					ntohs(ip->udp_dst),
1201 					ntohs(ip->udp_src),
1202 					ntohs(ip->udp_len) - UDP_HDR_SIZE);
1203 #endif
1204 		/*
1205 		 *	IP header OK.  Pass the packet to the current handler.
1206 		 */
1207 		(*udp_packet_handler)((uchar *)ip + IP_UDP_HDR_SIZE,
1208 				ntohs(ip->udp_dst),
1209 				src_ip,
1210 				ntohs(ip->udp_src),
1211 				ntohs(ip->udp_len) - UDP_HDR_SIZE);
1212 		break;
1213 	}
1214 }
1215 
1216 
1217 /**********************************************************************/
1218 
1219 static int net_check_prereq(enum proto_t protocol)
1220 {
1221 	switch (protocol) {
1222 		/* Fall through */
1223 #if defined(CONFIG_CMD_PING)
1224 	case PING:
1225 		if (NetPingIP == 0) {
1226 			puts("*** ERROR: ping address not given\n");
1227 			return 1;
1228 		}
1229 		goto common;
1230 #endif
1231 #if defined(CONFIG_CMD_SNTP)
1232 	case SNTP:
1233 		if (NetNtpServerIP == 0) {
1234 			puts("*** ERROR: NTP server address not given\n");
1235 			return 1;
1236 		}
1237 		goto common;
1238 #endif
1239 #if defined(CONFIG_CMD_DNS)
1240 	case DNS:
1241 		if (NetOurDNSIP == 0) {
1242 			puts("*** ERROR: DNS server address not given\n");
1243 			return 1;
1244 		}
1245 		goto common;
1246 #endif
1247 #if defined(CONFIG_CMD_NFS)
1248 	case NFS:
1249 #endif
1250 	case TFTPGET:
1251 	case TFTPPUT:
1252 		if (NetServerIP == 0) {
1253 			puts("*** ERROR: `serverip' not set\n");
1254 			return 1;
1255 		}
1256 #if	defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
1257 	defined(CONFIG_CMD_DNS)
1258 common:
1259 #endif
1260 		/* Fall through */
1261 
1262 	case NETCONS:
1263 	case TFTPSRV:
1264 		if (NetOurIP == 0) {
1265 			puts("*** ERROR: `ipaddr' not set\n");
1266 			return 1;
1267 		}
1268 		/* Fall through */
1269 
1270 #ifdef CONFIG_CMD_RARP
1271 	case RARP:
1272 #endif
1273 	case BOOTP:
1274 	case CDP:
1275 	case DHCP:
1276 	case LINKLOCAL:
1277 		if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
1278 			int num = eth_get_dev_index();
1279 
1280 			switch (num) {
1281 			case -1:
1282 				puts("*** ERROR: No ethernet found.\n");
1283 				return 1;
1284 			case 0:
1285 				puts("*** ERROR: `ethaddr' not set\n");
1286 				break;
1287 			default:
1288 				printf("*** ERROR: `eth%daddr' not set\n",
1289 					num);
1290 				break;
1291 			}
1292 
1293 			NetStartAgain();
1294 			return 2;
1295 		}
1296 		/* Fall through */
1297 	default:
1298 		return 0;
1299 	}
1300 	return 0;		/* OK */
1301 }
1302 /**********************************************************************/
1303 
1304 int
1305 NetEthHdrSize(void)
1306 {
1307 	ushort myvlanid;
1308 
1309 	myvlanid = ntohs(NetOurVLAN);
1310 	if (myvlanid == (ushort)-1)
1311 		myvlanid = VLAN_NONE;
1312 
1313 	return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
1314 		VLAN_ETHER_HDR_SIZE;
1315 }
1316 
1317 int
1318 NetSetEther(uchar *xet, uchar * addr, uint prot)
1319 {
1320 	struct ethernet_hdr *et = (struct ethernet_hdr *)xet;
1321 	ushort myvlanid;
1322 
1323 	myvlanid = ntohs(NetOurVLAN);
1324 	if (myvlanid == (ushort)-1)
1325 		myvlanid = VLAN_NONE;
1326 
1327 	memcpy(et->et_dest, addr, 6);
1328 	memcpy(et->et_src, NetOurEther, 6);
1329 	if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1330 		et->et_protlen = htons(prot);
1331 		return ETHER_HDR_SIZE;
1332 	} else {
1333 		struct vlan_ethernet_hdr *vet =
1334 			(struct vlan_ethernet_hdr *)xet;
1335 
1336 		vet->vet_vlan_type = htons(PROT_VLAN);
1337 		vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1338 		vet->vet_type = htons(prot);
1339 		return VLAN_ETHER_HDR_SIZE;
1340 	}
1341 }
1342 
1343 int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot)
1344 {
1345 	ushort protlen;
1346 
1347 	memcpy(et->et_dest, addr, 6);
1348 	memcpy(et->et_src, NetOurEther, 6);
1349 	protlen = ntohs(et->et_protlen);
1350 	if (protlen == PROT_VLAN) {
1351 		struct vlan_ethernet_hdr *vet =
1352 			(struct vlan_ethernet_hdr *)et;
1353 		vet->vet_type = htons(prot);
1354 		return VLAN_ETHER_HDR_SIZE;
1355 	} else if (protlen > 1514) {
1356 		et->et_protlen = htons(prot);
1357 		return ETHER_HDR_SIZE;
1358 	} else {
1359 		/* 802.2 + SNAP */
1360 		struct e802_hdr *et802 = (struct e802_hdr *)et;
1361 		et802->et_prot = htons(prot);
1362 		return E802_HDR_SIZE;
1363 	}
1364 }
1365 
1366 void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source)
1367 {
1368 	struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
1369 
1370 	/*
1371 	 *	Construct an IP header.
1372 	 */
1373 	/* IP_HDR_SIZE / 4 (not including UDP) */
1374 	ip->ip_hl_v  = 0x45;
1375 	ip->ip_tos   = 0;
1376 	ip->ip_len   = htons(IP_HDR_SIZE);
1377 	ip->ip_id    = htons(NetIPID++);
1378 	ip->ip_off   = htons(IP_FLAGS_DFRAG);	/* Don't fragment */
1379 	ip->ip_ttl   = 255;
1380 	ip->ip_sum   = 0;
1381 	/* already in network byte order */
1382 	NetCopyIP((void *)&ip->ip_src, &source);
1383 	/* already in network byte order */
1384 	NetCopyIP((void *)&ip->ip_dst, &dest);
1385 }
1386 
1387 void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, int sport,
1388 			int len)
1389 {
1390 	struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
1391 
1392 	/*
1393 	 *	If the data is an odd number of bytes, zero the
1394 	 *	byte after the last byte so that the checksum
1395 	 *	will work.
1396 	 */
1397 	if (len & 1)
1398 		pkt[IP_UDP_HDR_SIZE + len] = 0;
1399 
1400 	net_set_ip_header(pkt, dest, NetOurIP);
1401 	ip->ip_len   = htons(IP_UDP_HDR_SIZE + len);
1402 	ip->ip_p     = IPPROTO_UDP;
1403 	ip->ip_sum   = compute_ip_checksum(ip, IP_HDR_SIZE);
1404 
1405 	ip->udp_src  = htons(sport);
1406 	ip->udp_dst  = htons(dport);
1407 	ip->udp_len  = htons(UDP_HDR_SIZE + len);
1408 	ip->udp_xsum = 0;
1409 }
1410 
1411 void copy_filename(char *dst, const char *src, int size)
1412 {
1413 	if (*src && (*src == '"')) {
1414 		++src;
1415 		--size;
1416 	}
1417 
1418 	while ((--size > 0) && *src && (*src != '"'))
1419 		*dst++ = *src++;
1420 	*dst = '\0';
1421 }
1422 
1423 #if	defined(CONFIG_CMD_NFS)		|| \
1424 	defined(CONFIG_CMD_SNTP)	|| \
1425 	defined(CONFIG_CMD_DNS)
1426 /*
1427  * make port a little random (1024-17407)
1428  * This keeps the math somewhat trivial to compute, and seems to work with
1429  * all supported protocols/clients/servers
1430  */
1431 unsigned int random_port(void)
1432 {
1433 	return 1024 + (get_timer(0) % 0x4000);
1434 }
1435 #endif
1436 
1437 void ip_to_string(IPaddr_t x, char *s)
1438 {
1439 	x = ntohl(x);
1440 	sprintf(s, "%d.%d.%d.%d",
1441 		(int) ((x >> 24) & 0xff),
1442 		(int) ((x >> 16) & 0xff),
1443 		(int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
1444 	);
1445 }
1446 
1447 void VLAN_to_string(ushort x, char *s)
1448 {
1449 	x = ntohs(x);
1450 
1451 	if (x == (ushort)-1)
1452 		x = VLAN_NONE;
1453 
1454 	if (x == VLAN_NONE)
1455 		strcpy(s, "none");
1456 	else
1457 		sprintf(s, "%d", x & VLAN_IDMASK);
1458 }
1459 
1460 ushort string_to_VLAN(const char *s)
1461 {
1462 	ushort id;
1463 
1464 	if (s == NULL)
1465 		return htons(VLAN_NONE);
1466 
1467 	if (*s < '0' || *s > '9')
1468 		id = VLAN_NONE;
1469 	else
1470 		id = (ushort)simple_strtoul(s, NULL, 10);
1471 
1472 	return htons(id);
1473 }
1474 
1475 ushort getenv_VLAN(char *var)
1476 {
1477 	return string_to_VLAN(getenv(var));
1478 }
1479