xref: /rk3399_rockchip-uboot/net/net.c (revision e0ac62d798ce60ec5d43125d4786e58b0d881836)
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  */
10 
11 /*
12  * General Desription:
13  *
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:
17  *
18  * BOOTP:
19  *
20  *	Prerequisites:	- own ethernet address
21  *	We want:	- own IP address
22  *			- TFTP server IP address
23  *			- name of bootfile
24  *	Next step:	ARP
25  *
26  * RARP:
27  *
28  *	Prerequisites:	- own ethernet address
29  *	We want:	- own IP address
30  *			- TFTP server IP address
31  *	Next step:	ARP
32  *
33  * ARP:
34  *
35  *	Prerequisites:	- own ethernet address
36  *			- own IP address
37  *			- TFTP server IP address
38  *	We want:	- TFTP server ethernet address
39  *	Next step:	TFTP
40  *
41  * DHCP:
42  *
43  *     Prerequisites:   - own ethernet address
44  *     We want:         - IP, Netmask, ServerIP, Gateway IP
45  *                      - bootfilename, lease time
46  *     Next step:       - TFTP
47  *
48  * TFTP:
49  *
50  *	Prerequisites:	- own ethernet address
51  *			- own IP 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
57  *	Next step:	none
58  */
59 
60 
61 #include <common.h>
62 #include <watchdog.h>
63 #include <command.h>
64 #include <net.h>
65 #include "bootp.h"
66 #include "tftp.h"
67 #include "rarp.h"
68 
69 #if (CONFIG_COMMANDS & CFG_CMD_NET)
70 
71 #define ARP_TIMEOUT		5		/* Seconds before trying ARP again */
72 #ifndef	CONFIG_NET_RETRY_COUNT
73 # define ARP_TIMEOUT_COUNT	5		/* # of timeouts before giving up  */
74 #else
75 # define ARP_TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
76 #endif
77 
78 #if 0
79 #define ET_DEBUG
80 #endif
81 
82 /** BOOTP EXTENTIONS **/
83 
84 IPaddr_t	NetOurSubnetMask=0;		/* Our subnet mask (0=unknown)	*/
85 IPaddr_t	NetOurGatewayIP=0;		/* Our gateways IP address	*/
86 IPaddr_t	NetOurDNSIP=0;			/* Our DNS IP address		*/
87 char		NetOurNISDomain[32]={0,};	/* Our NIS domain		*/
88 char		NetOurHostName[32]={0,};	/* Our hostname			*/
89 char		NetOurRootPath[64]={0,};	/* Our bootpath			*/
90 ushort		NetBootFileSize=0;		/* Our bootfile size in blocks	*/
91 
92 /** END OF BOOTP EXTENTIONS **/
93 
94 ulong		NetBootFileXferSize;	/* The actual transferred size of the bootfile (in bytes) */
95 uchar		NetOurEther[6];		/* Our ethernet address			*/
96 uchar		NetServerEther[6] =	/* Boot server enet address		*/
97 			{ 0, 0, 0, 0, 0, 0 };
98 IPaddr_t	NetOurIP;		/* Our IP addr (0 = unknown)		*/
99 IPaddr_t	NetServerIP;		/* Our IP addr (0 = unknown)		*/
100 volatile uchar *NetRxPkt;		/* Current receive packet		*/
101 int		NetRxPktLen;		/* Current rx packet length		*/
102 unsigned	NetIPID;		/* IP packet ID				*/
103 uchar		NetBcastAddr[6] =	/* Ethernet bcast address		*/
104 			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
105 uchar		NetEtherNullAddr[6] =
106 			{ 0, 0, 0, 0, 0, 0 };
107 int		NetState;		/* Network loop state			*/
108 #ifdef CONFIG_NET_MULTI
109 int		NetRestartWrap = 0;	/* Tried all network devices		*/
110 static int	NetRestarted = 0;	/* Network loop restarted		*/
111 static int	NetDevExists = 0;	/* At least one device configured	*/
112 #endif
113 
114 char		BootFile[128];		/* Boot File name			*/
115 
116 #if (CONFIG_COMMANDS & CFG_CMD_PING)
117 IPaddr_t	NetPingIP;		/* the ip address to ping 		*/
118 
119 static void PingStart(void);
120 #endif
121 
122 volatile uchar	PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
123 
124 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets			*/
125 
126 static rxhand_f *packetHandler;		/* Current RX packet handler		*/
127 static thand_f *timeHandler;		/* Current timeout handler		*/
128 static ulong	timeStart;		/* Time base value			*/
129 static ulong	timeDelta;		/* Current timeout value		*/
130 volatile uchar *NetTxPacket = 0;	/* THE transmit packet			*/
131 
132 static int net_check_prereq (proto_t protocol);
133 
134 /**********************************************************************/
135 
136 IPaddr_t	NetArpWaitPacketIP;
137 IPaddr_t	NetArpWaitReplyIP;
138 uchar	       *NetArpWaitPacketMAC;	/* MAC address of waiting packet's destination	*/
139 uchar          *NetArpWaitTxPacket;	/* THE transmit packet			*/
140 int		NetArpWaitTxPacketSize;
141 uchar 		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
142 ulong		NetArpWaitTimerStart;
143 int		NetArpWaitTry;
144 
145 void ArpRequest(void)
146 {
147 	int i;
148 	volatile uchar *pkt;
149 	ARP_t *	arp;
150 
151 #ifdef ET_DEBUG
152 	printf("ARP broadcast %d\n", NetArpWaitTry);
153 #endif
154 	pkt = NetTxPacket;
155 
156 	NetSetEther(pkt, NetBcastAddr, PROT_ARP);
157 	pkt += ETHER_HDR_SIZE;
158 
159 	arp = (ARP_t *)pkt;
160 
161 	arp->ar_hrd = htons(ARP_ETHER);
162 	arp->ar_pro = htons(PROT_IP);
163 	arp->ar_hln = 6;
164 	arp->ar_pln = 4;
165 	arp->ar_op  = htons(ARPOP_REQUEST);
166 
167 	memcpy (&arp->ar_data[0], NetOurEther, 6);	/* source ET addr	*/
168 	NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP);	/* source IP addr	*/
169 	for (i=10; i<16; ++i) {
170 		arp->ar_data[i] = 0;			/* dest ET addr = 0	*/
171 	}
172 
173 	if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) {
174 	    if (NetOurGatewayIP == 0) {
175 		puts ("## Warning: gatewayip needed but not set\n");
176 	    }
177 	    NetArpWaitReplyIP = NetOurGatewayIP;
178 	} else
179 	    NetArpWaitReplyIP = NetArpWaitPacketIP;
180 
181 	NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP);
182 	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
183 }
184 
185 void ArpTimeoutCheck(void)
186 {
187 	ulong t;
188 
189 	if (!NetArpWaitPacketIP)
190 		return;
191 
192 	t = get_timer(0);
193 
194 	/* check for arp timeout */
195 	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) {
196 		NetArpWaitTry++;
197 
198 		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
199 			puts ("\nARP Retry count exceeded; starting again\n");
200 			NetArpWaitTry = 0;
201 			NetStartAgain();
202 		} else {
203 			NetArpWaitTimerStart = t;
204 			ArpRequest();
205 		}
206 	}
207 }
208 
209 /**********************************************************************/
210 /*
211  *	Main network processing loop.
212  */
213 
214 int
215 NetLoop(proto_t protocol)
216 {
217 	DECLARE_GLOBAL_DATA_PTR;
218 
219 	bd_t *bd = gd->bd;
220 
221 #ifdef CONFIG_NET_MULTI
222 	NetRestarted = 0;
223 	NetDevExists = 0;
224 #endif
225 
226 	/* XXX problem with bss workaround */
227 	NetArpWaitPacketMAC = NULL;
228 	NetArpWaitTxPacket = NULL;
229 	NetArpWaitPacketIP = 0;
230 	NetArpWaitReplyIP = 0;
231 	NetArpWaitTxPacket = NULL;
232 	NetTxPacket = NULL;
233 
234 	if (!NetTxPacket) {
235 		int	i;
236 
237 		/*
238 		 *	Setup packet buffers, aligned correctly.
239 		 */
240 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
241 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
242 		for (i = 0; i < PKTBUFSRX; i++) {
243 			NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
244 		}
245 
246 	}
247 
248 	if (!NetArpWaitTxPacket) {
249 		NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
250 		NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
251 		NetArpWaitTxPacketSize = 0;
252 	}
253 
254 	eth_halt();
255 	if(eth_init(bd) < 0)
256 	    return(-1);
257 
258 restart:
259 #ifdef CONFIG_NET_MULTI
260 	memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
261 #else
262 	memcpy (NetOurEther, bd->bi_enetaddr, 6);
263 #endif
264 
265 	NetState = NETLOOP_CONTINUE;
266 
267 	/*
268 	 *	Start the ball rolling with the given start function.  From
269 	 *	here on, this code is a state machine driven by received
270 	 *	packets and timer events.
271 	 */
272 
273 	switch (protocol) {
274 #if (CONFIG_COMMANDS & CFG_CMD_PING)
275 	case PING:
276 #endif
277 	case TFTP:
278 		NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
279 		NetOurGatewayIP = getenv_IPaddr ("gatewayip");
280 		NetOurSubnetMask= getenv_IPaddr ("netmask");
281 
282 		switch (protocol) {
283 		case TFTP:
284 			NetServerIP = getenv_IPaddr ("serverip");
285 			break;
286 #if (CONFIG_COMMANDS & CFG_CMD_PING)
287 		case PING:
288 			/* nothing */
289 			break;
290 #endif
291 		default:
292 			break;
293 		}
294 
295 		break;
296 	case BOOTP:
297 	case RARP:
298 		/*
299 		 * initialize our IP addr to 0 in order to accept ANY
300 		 * IP addr assigned to us by the BOOTP / RARP server
301 		 */
302 		NetOurIP = 0;
303 		NetServerIP = 0;
304 		break;
305 	default:
306 		break;
307 	}
308 
309 	switch (net_check_prereq (protocol)) {
310 	case 1:
311 		/* network not configured */
312 		return (-1);
313 
314 #ifdef CONFIG_NET_MULTI
315 	case 2:
316 		/* network device not configured */
317 		break;
318 #endif /* CONFIG_NET_MULTI */
319 
320 	case 0:
321 #ifdef CONFIG_NET_MULTI
322 		NetDevExists = 1;
323 #endif
324 		switch (protocol) {
325 		case TFTP:
326 			/* always use ARP to get server ethernet address */
327 			TftpStart();
328 			break;
329 
330 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
331 		case DHCP:
332 			/* Start with a clean slate... */
333 			NetOurIP = 0;
334 			NetServerIP = 0;
335 			DhcpRequest();		/* Basically same as BOOTP */
336 			break;
337 #endif /* CFG_CMD_DHCP */
338 
339 		case BOOTP:
340 			BootpTry = 0;
341 			BootpRequest ();
342 			break;
343 
344 		case RARP:
345 			RarpTry = 0;
346 			RarpRequest ();
347 			break;
348 #if (CONFIG_COMMANDS & CFG_CMD_PING)
349 		case PING:
350 			PingStart();
351 			break;
352 #endif
353 		default:
354 			break;
355 		}
356 
357 		NetBootFileXferSize = 0;
358 		break;
359 	}
360 
361 
362 	/*
363 	 *	Main packet reception loop.  Loop receiving packets until
364 	 *	someone sets `NetQuit'.
365 	 */
366 	for (;;) {
367 		WATCHDOG_RESET();
368 #ifdef CONFIG_SHOW_ACTIVITY
369 		{
370 			extern void show_activity(int arg);
371 			show_activity(1);
372 		}
373 #endif
374 		/*
375 		 *	Check the ethernet for a new packet.  The ethernet
376 		 *	receive routine will process it.
377 		 */
378 			eth_rx();
379 
380 		/*
381 		 *	Abort if ctrl-c was pressed.
382 		 */
383 		if (ctrlc()) {
384 			eth_halt();
385 			printf("\nAbort\n");
386 			return (-1);
387 		}
388 
389 		ArpTimeoutCheck();
390 
391 		/*
392 		 *	Check for a timeout, and run the timeout handler
393 		 *	if we have one.
394 		 */
395 		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
396 			thand_f *x;
397 
398 			x = timeHandler;
399 			timeHandler = (thand_f *)0;
400 			(*x)();
401 		}
402 
403 
404 		switch (NetState) {
405 
406 		case NETLOOP_RESTART:
407 #ifdef CONFIG_NET_MULTI
408 			NetRestarted = 1;
409 #endif
410 			goto restart;
411 
412 		case NETLOOP_SUCCESS:
413 			if (NetBootFileXferSize > 0) {
414 				char buf[10];
415 				printf("Bytes transferred = %ld (%lx hex)\n",
416 					NetBootFileXferSize,
417 					NetBootFileXferSize);
418 				sprintf(buf, "%lx", NetBootFileXferSize);
419 				setenv("filesize", buf);
420 			}
421 			eth_halt();
422 			return NetBootFileXferSize;
423 
424 		case NETLOOP_FAIL:
425 			return (-1);
426 		}
427 	}
428 }
429 
430 /**********************************************************************/
431 
432 static void
433 startAgainTimeout(void)
434 {
435 	NetState = NETLOOP_RESTART;
436 }
437 
438 static void
439 startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
440 {
441 	/* Totally ignore the packet */
442 }
443 
444 void
445 NetStartAgain(void)
446 {
447 #ifndef CONFIG_NET_MULTI
448 	NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
449 	NetSetHandler(startAgainHandler);
450 #else
451 	DECLARE_GLOBAL_DATA_PTR;
452 
453 	eth_halt();
454 	eth_try_another(!NetRestarted);
455 	eth_init(gd->bd);
456 	if (NetRestartWrap)
457 	{
458 		NetRestartWrap = 0;
459 		if (NetDevExists)
460 		{
461 			NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
462 			NetSetHandler(startAgainHandler);
463 		}
464 		else
465 		{
466 			NetState = NETLOOP_FAIL;
467 		}
468 	}
469 	else
470 	{
471 		NetState = NETLOOP_RESTART;
472 	}
473 #endif
474 }
475 
476 /**********************************************************************/
477 /*
478  *	Miscelaneous bits.
479  */
480 
481 void
482 NetSetHandler(rxhand_f * f)
483 {
484 	packetHandler = f;
485 }
486 
487 
488 void
489 NetSetTimeout(int iv, thand_f * f)
490 {
491 	if (iv == 0) {
492 		timeHandler = (thand_f *)0;
493 	} else {
494 		timeHandler = f;
495 		timeStart = get_timer(0);
496 		timeDelta = iv;
497 	}
498 }
499 
500 
501 void
502 NetSendPacket(volatile uchar * pkt, int len)
503 {
504 	(void) eth_send(pkt, len);
505 }
506 
507 int
508 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
509 {
510 	/* convert to new style broadcast */
511 	if (dest == 0)
512 		dest = 0xFFFFFFFF;
513 
514 	/* if broadcast, make the ether address a broadcast and don't do ARP */
515 	if (dest == 0xFFFFFFFF)
516 		ether = NetBcastAddr;
517 
518 	/* if MAC address was not discovered yet, save the packet and do an ARP request */
519 	if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
520 
521 #ifdef ET_DEBUG
522 		printf("sending ARP for %08lx\n", dest);
523 #endif
524 
525 		NetArpWaitPacketIP = dest;
526 		NetArpWaitPacketMAC = ether;
527 		NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP);
528 		NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
529 		memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE,
530 			(uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len);
531 
532 		/* size of the waiting packet */
533 		NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len;
534 
535 		/* and do the ARP request */
536 		NetArpWaitTry = 1;
537 		NetArpWaitTimerStart = get_timer(0);
538 		ArpRequest();
539 		return 1;	/* waiting */
540 	}
541 
542 #ifdef ET_DEBUG
543 	printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
544 			dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
545 #endif
546 
547 	NetSetEther (NetTxPacket, ether, PROT_IP);
548 	NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
549 	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);
550 
551 	return 0;	/* transmited */
552 }
553 
554 #if (CONFIG_COMMANDS & CFG_CMD_PING)
555 static ushort PingSeqNo;
556 
557 int PingSend(void)
558 {
559 	static uchar mac[6];
560 	volatile IP_t *ip;
561 	volatile ushort *s;
562 
563 	/* XXX always send arp request */
564 
565 	memcpy(mac, NetEtherNullAddr, 6);
566 
567 #ifdef ET_DEBUG
568 	printf("sending ARP for %08lx\n", NetPingIP);
569 #endif
570 
571 	NetArpWaitPacketIP = NetPingIP;
572 	NetArpWaitPacketMAC = mac;
573 
574 	NetSetEther(NetArpWaitTxPacket, mac, PROT_IP);
575 
576 	ip = (volatile IP_t *)(NetArpWaitTxPacket + ETHER_HDR_SIZE);
577 
578 	/*
579 	 *	Construct an IP and ICMP header.  (need to set no fragment bit - XXX)
580 	 */
581 	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
582 	ip->ip_tos   = 0;
583 	ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8);
584 	ip->ip_id    = htons(NetIPID++);
585 	ip->ip_off   = htons(0x4000);	/* No fragmentation */
586 	ip->ip_ttl   = 255;
587 	ip->ip_p     = 0x01;		/* ICMP */
588 	ip->ip_sum   = 0;
589 	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
590 	NetCopyIP((void*)&ip->ip_dst, &NetPingIP);	   /* - "" - */
591 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
592 
593 	s = &ip->udp_src;		/* XXX ICMP starts here */
594 	s[0] = htons(0x0800);		/* echo-request, code */
595 	s[1] = 0;			/* checksum */
596 	s[2] = 0; 			/* identifier */
597 	s[3] = htons(PingSeqNo++);	/* sequence number */
598 	s[1] = ~NetCksum((uchar *)s, 8/2);
599 
600 	/* size of the waiting packet */
601 	NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE_NO_UDP + 8;
602 
603 	/* and do the ARP request */
604 	NetArpWaitTry = 1;
605 	NetArpWaitTimerStart = get_timer(0);
606 	ArpRequest();
607 	return 1;	/* waiting */
608 }
609 
610 static void
611 PingTimeout (void)
612 {
613 	eth_halt();
614 	NetState = NETLOOP_FAIL;	/* we did not get the reply */
615 }
616 
617 static void
618 PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
619 {
620 	IPaddr_t tmp;
621 	volatile IP_t *ip = (volatile IP_t *)pkt;
622 
623 	tmp = NetReadIP((void *)&ip->ip_src);
624 	if (tmp != NetPingIP)
625 		return;
626 
627 	NetState = NETLOOP_SUCCESS;
628 }
629 
630 static void PingStart(void)
631 {
632 	NetSetTimeout (10 * CFG_HZ, PingTimeout);
633 	NetSetHandler (PingHandler);
634 
635 	PingSend();
636 }
637 
638 #endif
639 
640 void
641 NetReceive(volatile uchar * pkt, int len)
642 {
643 	Ethernet_t *et;
644 	IP_t	*ip;
645 	ARP_t	*arp;
646 	IPaddr_t tmp;
647 	int	x;
648 
649 	NetRxPkt = pkt;
650 	NetRxPktLen = len;
651 	et = (Ethernet_t *)pkt;
652 
653 	x = ntohs(et->et_protlen);
654 
655 	if (x < 1514) {
656 		/*
657 		 *	Got a 802 packet.  Check the other protocol field.
658 		 */
659 		x = ntohs(et->et_prot);
660 		ip = (IP_t *)(pkt + E802_HDR_SIZE);
661 		len -= E802_HDR_SIZE;
662 	} else {
663 		ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
664 		len -= ETHER_HDR_SIZE;
665 	}
666 
667 #ifdef ET_DEBUG
668 	printf("Receive from protocol 0x%x\n", x);
669 #endif
670 
671 	switch (x) {
672 
673 	case PROT_ARP:
674 		/*
675 		 * We have to deal with two types of ARP packets:
676 		 * - REQUEST packets will be answered by sending  our
677 		 *   IP address - if we know it.
678 		 * - REPLY packates are expected only after we asked
679 		 *   for the TFTP server's or the gateway's ethernet
680 		 *   address; so if we receive such a packet, we set
681 		 *   the server ethernet address
682 		 */
683 #ifdef ET_DEBUG
684 		printf("Got ARP\n");
685 #endif
686 		arp = (ARP_t *)ip;
687 		if (len < ARP_HDR_SIZE) {
688 			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
689 			return;
690 		}
691 		if (ntohs(arp->ar_hrd) != ARP_ETHER) {
692 			return;
693 		}
694 		if (ntohs(arp->ar_pro) != PROT_IP) {
695 			return;
696 		}
697 		if (arp->ar_hln != 6) {
698 			return;
699 		}
700 		if (arp->ar_pln != 4) {
701 			return;
702 		}
703 
704 		if (NetOurIP == 0) {
705 			return;
706 		}
707 
708 		if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
709 			return;
710 		}
711 
712 		switch (ntohs(arp->ar_op)) {
713 		case ARPOP_REQUEST:		/* reply with our IP address	*/
714 #ifdef ET_DEBUG
715 			printf("Got ARP REQUEST, return our IP\n");
716 #endif
717 			NetSetEther((uchar *)et, et->et_src, PROT_ARP);
718 			arp->ar_op = htons(ARPOP_REPLY);
719 			memcpy   (&arp->ar_data[10], &arp->ar_data[0], 6);
720 			NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
721 			memcpy   (&arp->ar_data[ 0], NetOurEther, 6);
722 			NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
723 			(void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE);
724 			return;
725 
726 		case ARPOP_REPLY:		/* arp reply */
727 			/* are we waiting for a reply */
728 			if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
729 				break;
730 #ifdef ET_DEBUG
731 			printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
732 				arp->ar_data[0], arp->ar_data[1],
733 				arp->ar_data[2], arp->ar_data[3],
734 				arp->ar_data[4], arp->ar_data[5]);
735 #endif
736 
737 			tmp = NetReadIP(&arp->ar_data[6]);
738 
739 			/* matched waiting packet's address */
740 			if (tmp == NetArpWaitReplyIP) {
741 #ifdef ET_DEBUG
742 				printf("Got it\n");
743 #endif
744 				/* save address for later use */
745 				memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
746 
747 				/* modify header, and transmit it */
748 				memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
749 				(void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
750 
751 				/* no arp request pending now */
752 				NetArpWaitPacketIP = 0;
753 				NetArpWaitTxPacketSize = 0;
754 				NetArpWaitPacketMAC = NULL;
755 
756 			}
757 			return;
758 		default:
759 #ifdef ET_DEBUG
760 			printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
761 #endif
762 			return;
763 		}
764 
765 	case PROT_RARP:
766 #ifdef ET_DEBUG
767 		printf("Got RARP\n");
768 #endif
769 		arp = (ARP_t *)ip;
770 		if (len < ARP_HDR_SIZE) {
771 			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
772 			return;
773 		}
774 
775 		if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
776 			(ntohs(arp->ar_hrd) != ARP_ETHER)   ||
777 			(ntohs(arp->ar_pro) != PROT_IP)     ||
778 			(arp->ar_hln != 6) || (arp->ar_pln != 4)) {
779 
780 			printf("invalid RARP header\n");
781 		} else {
782 			NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
783 			NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
784 			memcpy (NetServerEther, &arp->ar_data[ 0], 6);
785 
786 			(*packetHandler)(0,0,0,0);
787 		}
788 		break;
789 
790 	case PROT_IP:
791 #ifdef ET_DEBUG
792 		printf("Got IP\n");
793 #endif
794 		if (len < IP_HDR_SIZE) {
795 			debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
796 			return;
797 		}
798 		if (len < ntohs(ip->ip_len)) {
799 			printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
800 			return;
801 		}
802 		len = ntohs(ip->ip_len);
803 #ifdef ET_DEBUG
804 		printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
805 #endif
806 		if ((ip->ip_hl_v & 0xf0) != 0x40) {
807 			return;
808 		}
809 		if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
810 			return;
811 		}
812 		if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
813 			printf("checksum bad\n");
814 			return;
815 		}
816 		tmp = NetReadIP(&ip->ip_dst);
817 		if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
818 			return;
819 		}
820 		/*
821 		 * watch for ICMP host redirects
822 		 *
823 		 * There is no real handler code (yet). We just watch
824 		 * for ICMP host redirect messages. In case anybody
825 		 * sees these messages: please contact me
826 		 * (wd@denx.de), or - even better - send me the
827 		 * necessary fixes :-)
828 		 *
829 		 * Note: in all cases where I have seen this so far
830 		 * it was a problem with the router configuration,
831 		 * for instance when a router was configured in the
832 		 * BOOTP reply, but the TFTP server was on the same
833 		 * subnet. So this is probably a warning that your
834 		 * configuration might be wrong. But I'm not really
835 		 * sure if there aren't any other situations.
836 		 */
837 		if (ip->ip_p == IPPROTO_ICMP) {
838 			ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
839 
840 			switch (icmph->type) {
841 			case ICMP_REDIRECT:
842 			if (icmph->code != ICMP_REDIR_HOST)
843 				return;
844 			puts (" ICMP Host Redirect to ");
845 			print_IPaddr(icmph->un.gateway);
846 			putc(' ');
847 				break;
848 #if (CONFIG_COMMANDS & CFG_CMD_PING)
849 			case ICMP_ECHO_REPLY:
850 				/*
851 				 *	IP header OK.  Pass the packet to the current handler.
852 				 */
853 				/* XXX point to ip packet */
854 				(*packetHandler)((uchar *)ip, 0, 0, 0);
855 				break;
856 #endif
857 			default:
858 				return;
859 			}
860 		} else if (ip->ip_p != IPPROTO_UDP) {	/* Only UDP packets */
861 			return;
862 		}
863 
864 		/*
865 		 *	IP header OK.  Pass the packet to the current handler.
866 		 */
867 		(*packetHandler)((uchar *)ip +IP_HDR_SIZE,
868 						ntohs(ip->udp_dst),
869 						ntohs(ip->udp_src),
870 						ntohs(ip->udp_len) - 8);
871 
872 		break;
873 	}
874 }
875 
876 
877 /**********************************************************************/
878 
879 static int net_check_prereq (proto_t protocol)
880 {
881 	switch (protocol) {
882 			/* Fall through */
883 #if (CONFIG_COMMANDS & CFG_CMD_PING)
884 	case PING:
885 			if (NetPingIP == 0) {
886 				puts ("*** ERROR: ping address not given\n");
887 				return (1);
888 			}
889 			goto common;
890 #endif
891 	case TFTP:
892 			if (NetServerIP == 0) {
893 				puts ("*** ERROR: `serverip' not set\n");
894 				return (1);
895 			}
896 
897 #if (CONFIG_COMMANDS & CFG_CMD_PING)
898 		common:
899 #endif
900 
901 			if (NetOurIP == 0) {
902 				puts ("*** ERROR: `ipaddr' not set\n");
903 				return (1);
904 			}
905 			/* Fall through */
906 
907 	case DHCP:
908 	case RARP:
909 	case BOOTP:
910 			if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
911 #ifdef CONFIG_NET_MULTI
912 			    extern int eth_get_dev_index (void);
913 			    int num = eth_get_dev_index();
914 
915 			    switch (num) {
916 			    case -1:
917 				puts ("*** ERROR: No ethernet found.\n");
918 				return (1);
919 			    case 0:
920 				puts ("*** ERROR: `ethaddr' not set\n");
921 				break;
922 			    default:
923 				printf ("*** ERROR: `eth%daddr' not set\n",
924 					num);
925 				break;
926 			    }
927 
928 			    NetStartAgain ();
929 			    return (2);
930 #else
931 			    puts ("*** ERROR: `ethaddr' not set\n");
932 			    return (1);
933 #endif
934 			}
935 			/* Fall through */
936 		default:
937 			return(0);
938 	}
939 	return (0);	/* OK */
940 }
941 /**********************************************************************/
942 
943 int
944 NetCksumOk(uchar * ptr, int len)
945 {
946 	return !((NetCksum(ptr, len) + 1) & 0xfffe);
947 }
948 
949 
950 unsigned
951 NetCksum(uchar * ptr, int len)
952 {
953 	ulong	xsum;
954 
955 	xsum = 0;
956 	while (len-- > 0)
957 		xsum += *((ushort *)ptr)++;
958 	xsum = (xsum & 0xffff) + (xsum >> 16);
959 	xsum = (xsum & 0xffff) + (xsum >> 16);
960 	return (xsum & 0xffff);
961 }
962 
963 
964 void
965 NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
966 {
967 	Ethernet_t *et = (Ethernet_t *)xet;
968 
969 	memcpy (et->et_dest, addr, 6);
970 	memcpy (et->et_src, NetOurEther, 6);
971 	et->et_protlen = htons(prot);
972 }
973 
974 
975 void
976 NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
977 {
978 	volatile IP_t *ip = (IP_t *)xip;
979 
980 	/*
981 	 *	If the data is an odd number of bytes, zero the
982 	 *	byte after the last byte so that the checksum
983 	 *	will work.
984 	 */
985 	if (len & 1)
986 		xip[IP_HDR_SIZE + len] = 0;
987 
988 	/*
989 	 *	Construct an IP and UDP header.
990 			(need to set no fragment bit - XXX)
991 	 */
992 	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
993 	ip->ip_tos   = 0;
994 	ip->ip_len   = htons(IP_HDR_SIZE + len);
995 	ip->ip_id    = htons(NetIPID++);
996 	ip->ip_off   = htons(0x4000);	/* No fragmentation */
997 	ip->ip_ttl   = 255;
998 	ip->ip_p     = 17;		/* UDP */
999 	ip->ip_sum   = 0;
1000 	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1001 	NetCopyIP((void*)&ip->ip_dst, &dest);	   /* - "" - */
1002 	ip->udp_src  = htons(sport);
1003 	ip->udp_dst  = htons(dport);
1004 	ip->udp_len  = htons(8 + len);
1005 	ip->udp_xsum = 0;
1006 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1007 }
1008 
1009 void copy_filename (uchar *dst, uchar *src, int size)
1010 {
1011 	if (*src && (*src == '"')) {
1012 		++src;
1013 		--size;
1014 	}
1015 
1016 	while ((--size > 0) && *src && (*src != '"')) {
1017 		*dst++ = *src++;
1018 	}
1019 	*dst = '\0';
1020 }
1021 
1022 #endif /* CFG_CMD_NET */
1023 
1024 void ip_to_string (IPaddr_t x, char *s)
1025 {
1026     x = ntohl(x);
1027     sprintf (s,"%d.%d.%d.%d",
1028 	(int)((x >> 24) & 0xff),
1029 	(int)((x >> 16) & 0xff),
1030 	(int)((x >>  8) & 0xff),
1031 	(int)((x >>  0) & 0xff)
1032     );
1033 }
1034 
1035 IPaddr_t string_to_ip(char *s)
1036 {
1037 	IPaddr_t addr;
1038 	char *e;
1039 	int i;
1040 
1041 	if (s == NULL)
1042 		return(0);
1043 
1044 	for (addr=0, i=0; i<4; ++i) {
1045 		ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1046 		addr <<= 8;
1047 		addr |= (val & 0xFF);
1048 		if (s) {
1049 			s = (*e) ? e+1 : e;
1050 		}
1051 	}
1052 
1053 	return (htonl(addr));
1054 }
1055 
1056 void print_IPaddr (IPaddr_t x)
1057 {
1058     char tmp[16];
1059 
1060     ip_to_string(x, tmp);
1061 
1062     puts(tmp);
1063 }
1064 
1065 IPaddr_t getenv_IPaddr (char *var)
1066 {
1067 	return (string_to_ip(getenv(var)));
1068 }
1069