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