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