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