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