]> git.sur5r.net Git - u-boot/blob - net/net.c
Merge with /home/m8/git/u-boot
[u-boot] / 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  * SNTP:
69  *
70  *      Prerequisites:  - own ethernet address
71  *                      - own IP address
72  *      We want:        - network time
73  *      Next step:      none
74  */
75
76
77 #include <common.h>
78 #include <watchdog.h>
79 #include <command.h>
80 #include <net.h>
81 #include "bootp.h"
82 #include "tftp.h"
83 #include "rarp.h"
84 #include "nfs.h"
85 #ifdef CONFIG_STATUS_LED
86 #include <status_led.h>
87 #include <miiphy.h>
88 #endif
89 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
90 #include "sntp.h"
91 #endif
92
93 #if (CONFIG_COMMANDS & CFG_CMD_NET)
94
95 #define ARP_TIMEOUT             5               /* Seconds before trying ARP again */
96 #ifndef CONFIG_NET_RETRY_COUNT
97 # define ARP_TIMEOUT_COUNT      5               /* # of timeouts before giving up  */
98 #else
99 # define ARP_TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
100 #endif
101
102 #if 0
103 #define ET_DEBUG
104 #endif
105
106 /** BOOTP EXTENTIONS **/
107
108 IPaddr_t        NetOurSubnetMask=0;             /* Our subnet mask (0=unknown)  */
109 IPaddr_t        NetOurGatewayIP=0;              /* Our gateways IP address      */
110 IPaddr_t        NetOurDNSIP=0;                  /* Our DNS IP address           */
111 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
112 IPaddr_t        NetOurDNS2IP=0;                 /* Our 2nd DNS IP address       */
113 #endif
114 char            NetOurNISDomain[32]={0,};       /* Our NIS domain               */
115 char            NetOurHostName[32]={0,};        /* Our hostname                 */
116 char            NetOurRootPath[64]={0,};        /* Our bootpath                 */
117 ushort          NetBootFileSize=0;              /* Our bootfile size in blocks  */
118
119 /** END OF BOOTP EXTENTIONS **/
120
121 ulong           NetBootFileXferSize;    /* The actual transferred size of the bootfile (in bytes) */
122 uchar           NetOurEther[6];         /* Our ethernet address                 */
123 uchar           NetServerEther[6] =     /* Boot server enet address             */
124                         { 0, 0, 0, 0, 0, 0 };
125 IPaddr_t        NetOurIP;               /* Our IP addr (0 = unknown)            */
126 IPaddr_t        NetServerIP;            /* Our IP addr (0 = unknown)            */
127 volatile uchar *NetRxPkt;               /* Current receive packet               */
128 int             NetRxPktLen;            /* Current rx packet length             */
129 unsigned        NetIPID;                /* IP packet ID                         */
130 uchar           NetBcastAddr[6] =       /* Ethernet bcast address               */
131                         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
132 uchar           NetEtherNullAddr[6] =
133                         { 0, 0, 0, 0, 0, 0 };
134 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
135 uchar           NetCDPAddr[6] =         /* Ethernet bcast address               */
136                         { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };
137 #endif
138 int             NetState;               /* Network loop state                   */
139 #ifdef CONFIG_NET_MULTI
140 int             NetRestartWrap = 0;     /* Tried all network devices            */
141 static int      NetRestarted = 0;       /* Network loop restarted               */
142 static int      NetDevExists = 0;       /* At least one device configured       */
143 #endif
144
145 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
146 ushort          NetOurVLAN = 0xFFFF;            /* default is without VLAN      */
147 ushort          NetOurNativeVLAN = 0xFFFF;      /* ditto                        */
148
149 char            BootFile[128];          /* Boot File name                       */
150
151 #if (CONFIG_COMMANDS & CFG_CMD_PING)
152 IPaddr_t        NetPingIP;              /* the ip address to ping               */
153
154 static void PingStart(void);
155 #endif
156
157 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
158 static void CDPStart(void);
159 #endif
160
161 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
162 IPaddr_t        NetNtpServerIP;         /* NTP server IP address                */
163 int             NetTimeOffset=0;        /* offset time from UTC                 */
164 #endif
165
166 #ifdef CONFIG_NETCONSOLE
167 void NcStart(void);
168 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
169 #endif
170
171 volatile uchar  PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
172
173 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets                     */
174
175 static rxhand_f *packetHandler;         /* Current RX packet handler            */
176 static thand_f *timeHandler;            /* Current timeout handler              */
177 static ulong    timeStart;              /* Time base value                      */
178 static ulong    timeDelta;              /* Current timeout value                */
179 volatile uchar *NetTxPacket = 0;        /* THE transmit packet                  */
180
181 static int net_check_prereq (proto_t protocol);
182
183 /**********************************************************************/
184
185 IPaddr_t        NetArpWaitPacketIP;
186 IPaddr_t        NetArpWaitReplyIP;
187 uchar          *NetArpWaitPacketMAC;    /* MAC address of waiting packet's destination  */
188 uchar          *NetArpWaitTxPacket;     /* THE transmit packet                  */
189 int             NetArpWaitTxPacketSize;
190 uchar           NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
191 ulong           NetArpWaitTimerStart;
192 int             NetArpWaitTry;
193
194 void ArpRequest (void)
195 {
196         int i;
197         volatile uchar *pkt;
198         ARP_t *arp;
199
200 #ifdef ET_DEBUG
201         printf ("ARP broadcast %d\n", NetArpWaitTry);
202 #endif
203         pkt = NetTxPacket;
204
205         pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP);
206
207         arp = (ARP_t *) pkt;
208
209         arp->ar_hrd = htons (ARP_ETHER);
210         arp->ar_pro = htons (PROT_IP);
211         arp->ar_hln = 6;
212         arp->ar_pln = 4;
213         arp->ar_op = htons (ARPOP_REQUEST);
214
215         memcpy (&arp->ar_data[0], NetOurEther, 6);              /* source ET addr       */
216         NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP);     /* source IP addr       */
217         for (i = 10; i < 16; ++i) {
218                 arp->ar_data[i] = 0;                            /* dest ET addr = 0     */
219         }
220
221         if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
222             (NetOurIP & NetOurSubnetMask)) {
223                 if (NetOurGatewayIP == 0) {
224                         puts ("## Warning: gatewayip needed but not set\n");
225                 }
226                 NetArpWaitReplyIP = NetOurGatewayIP;
227         } else {
228                 NetArpWaitReplyIP = NetArpWaitPacketIP;
229         }
230
231         NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP);
232         (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
233 }
234
235 void ArpTimeoutCheck(void)
236 {
237         ulong t;
238
239         if (!NetArpWaitPacketIP)
240                 return;
241
242         t = get_timer(0);
243
244         /* check for arp timeout */
245         if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) {
246                 NetArpWaitTry++;
247
248                 if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
249                         puts ("\nARP Retry count exceeded; starting again\n");
250                         NetArpWaitTry = 0;
251                         NetStartAgain();
252                 } else {
253                         NetArpWaitTimerStart = t;
254                         ArpRequest();
255                 }
256         }
257 }
258
259 /**********************************************************************/
260 /*
261  *      Main network processing loop.
262  */
263
264 int
265 NetLoop(proto_t protocol)
266 {
267         DECLARE_GLOBAL_DATA_PTR;
268
269         bd_t *bd = gd->bd;
270
271 #ifdef CONFIG_NET_MULTI
272         NetRestarted = 0;
273         NetDevExists = 0;
274 #endif
275
276         /* XXX problem with bss workaround */
277         NetArpWaitPacketMAC = NULL;
278         NetArpWaitTxPacket = NULL;
279         NetArpWaitPacketIP = 0;
280         NetArpWaitReplyIP = 0;
281         NetArpWaitTxPacket = NULL;
282         NetTxPacket = NULL;
283
284         if (!NetTxPacket) {
285                 int     i;
286                 /*
287                  *      Setup packet buffers, aligned correctly.
288                  */
289                 NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
290                 NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
291                 for (i = 0; i < PKTBUFSRX; i++) {
292                         NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
293                 }
294         }
295
296         if (!NetArpWaitTxPacket) {
297                 NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
298                 NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
299                 NetArpWaitTxPacketSize = 0;
300         }
301
302         eth_halt();
303 #ifdef CONFIG_NET_MULTI
304         eth_set_current();
305 #endif
306         if (eth_init(bd) < 0) {
307                 eth_halt();
308                 return(-1);
309         }
310
311 restart:
312 #ifdef CONFIG_NET_MULTI
313         memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
314 #else
315         memcpy (NetOurEther, bd->bi_enetaddr, 6);
316 #endif
317
318         NetState = NETLOOP_CONTINUE;
319
320         /*
321          *      Start the ball rolling with the given start function.  From
322          *      here on, this code is a state machine driven by received
323          *      packets and timer events.
324          */
325
326         switch (protocol) {
327 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
328         case NFS:
329 #endif
330 #if (CONFIG_COMMANDS & CFG_CMD_PING)
331         case PING:
332 #endif
333 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
334         case SNTP:
335 #endif
336         case NETCONS:
337         case TFTP:
338                 NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
339                 NetOurGatewayIP = getenv_IPaddr ("gatewayip");
340                 NetOurSubnetMask= getenv_IPaddr ("netmask");
341                 NetOurVLAN = getenv_VLAN("vlan");
342                 NetOurNativeVLAN = getenv_VLAN("nvlan");
343
344                 switch (protocol) {
345 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
346                 case NFS:
347 #endif
348                 case NETCONS:
349                 case TFTP:
350                         NetServerIP = getenv_IPaddr ("serverip");
351                         break;
352 #if (CONFIG_COMMANDS & CFG_CMD_PING)
353                 case PING:
354                         /* nothing */
355                         break;
356 #endif
357 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
358                 case SNTP:
359                         /* nothing */
360                         break;
361 #endif
362                 default:
363                         break;
364                 }
365
366                 break;
367         case BOOTP:
368         case RARP:
369                 /*
370                  * initialize our IP addr to 0 in order to accept ANY
371                  * IP addr assigned to us by the BOOTP / RARP server
372                  */
373                 NetOurIP = 0;
374                 NetServerIP = getenv_IPaddr ("serverip");
375                 NetOurVLAN = getenv_VLAN("vlan");       /* VLANs must be read */
376                 NetOurNativeVLAN = getenv_VLAN("nvlan");
377         case CDP:
378                 NetOurVLAN = getenv_VLAN("vlan");       /* VLANs must be read */
379                 NetOurNativeVLAN = getenv_VLAN("nvlan");
380                 break;
381         default:
382                 break;
383         }
384
385         switch (net_check_prereq (protocol)) {
386         case 1:
387                 /* network not configured */
388                 eth_halt();
389                 return (-1);
390
391 #ifdef CONFIG_NET_MULTI
392         case 2:
393                 /* network device not configured */
394                 break;
395 #endif /* CONFIG_NET_MULTI */
396
397         case 0:
398 #ifdef CONFIG_NET_MULTI
399                 NetDevExists = 1;
400 #endif
401                 switch (protocol) {
402                 case TFTP:
403                         /* always use ARP to get server ethernet address */
404                         TftpStart();
405                         break;
406
407 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
408                 case DHCP:
409                         /* Start with a clean slate... */
410                         BootpTry = 0;
411                         NetOurIP = 0;
412                         NetServerIP = getenv_IPaddr ("serverip");
413                         DhcpRequest();          /* Basically same as BOOTP */
414                         break;
415 #endif /* CFG_CMD_DHCP */
416
417                 case BOOTP:
418                         BootpTry = 0;
419                         BootpRequest ();
420                         break;
421
422                 case RARP:
423                         RarpTry = 0;
424                         RarpRequest ();
425                         break;
426 #if (CONFIG_COMMANDS & CFG_CMD_PING)
427                 case PING:
428                         PingStart();
429                         break;
430 #endif
431 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
432                 case NFS:
433                         NfsStart();
434                         break;
435 #endif
436 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
437                 case CDP:
438                         CDPStart();
439                         break;
440 #endif
441 #ifdef CONFIG_NETCONSOLE
442                 case NETCONS:
443                         NcStart();
444                         break;
445 #endif
446 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
447                 case SNTP:
448                         SntpStart();
449                         break;
450 #endif
451                 default:
452                         break;
453                 }
454
455                 NetBootFileXferSize = 0;
456                 break;
457         }
458
459 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
460 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
461         /*
462          * Echo the inverted link state to the fault LED.
463          */
464         if(miiphy_link(CFG_FAULT_MII_ADDR)) {
465                 status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
466         } else {
467                 status_led_set (STATUS_LED_RED, STATUS_LED_ON);
468         }
469 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
470 #endif /* CONFIG_MII, ... */
471
472         /*
473          *      Main packet reception loop.  Loop receiving packets until
474          *      someone sets `NetState' to a state that terminates.
475          */
476         for (;;) {
477                 WATCHDOG_RESET();
478 #ifdef CONFIG_SHOW_ACTIVITY
479                 {
480                         extern void show_activity(int arg);
481                         show_activity(1);
482                 }
483 #endif
484                 /*
485                  *      Check the ethernet for a new packet.  The ethernet
486                  *      receive routine will process it.
487                  */
488                         eth_rx();
489
490                 /*
491                  *      Abort if ctrl-c was pressed.
492                  */
493                 if (ctrlc()) {
494                         eth_halt();
495                         puts ("\nAbort\n");
496                         return (-1);
497                 }
498
499                 ArpTimeoutCheck();
500
501                 /*
502                  *      Check for a timeout, and run the timeout handler
503                  *      if we have one.
504                  */
505                 if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
506                         thand_f *x;
507
508 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
509 #  if defined(CFG_FAULT_ECHO_LINK_DOWN) && \
510       defined(CONFIG_STATUS_LED) &&        \
511       defined(STATUS_LED_RED)
512                         /*
513                          * Echo the inverted link state to the fault LED.
514                          */
515                         if(miiphy_link(CFG_FAULT_MII_ADDR)) {
516                                 status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
517                         } else {
518                                 status_led_set (STATUS_LED_RED, STATUS_LED_ON);
519                         }
520 #  endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
521 #endif /* CONFIG_MII, ... */
522                         x = timeHandler;
523                         timeHandler = (thand_f *)0;
524                         (*x)();
525                 }
526
527
528                 switch (NetState) {
529
530                 case NETLOOP_RESTART:
531 #ifdef CONFIG_NET_MULTI
532                         NetRestarted = 1;
533 #endif
534                         goto restart;
535
536                 case NETLOOP_SUCCESS:
537                         if (NetBootFileXferSize > 0) {
538                                 char buf[10];
539                                 printf("Bytes transferred = %ld (%lx hex)\n",
540                                         NetBootFileXferSize,
541                                         NetBootFileXferSize);
542                                 sprintf(buf, "%lx", NetBootFileXferSize);
543                                 setenv("filesize", buf);
544
545                                 sprintf(buf, "%lX", (unsigned long)load_addr);
546                                 setenv("fileaddr", buf);
547                         }
548                         eth_halt();
549                         return NetBootFileXferSize;
550
551                 case NETLOOP_FAIL:
552                         return (-1);
553                 }
554         }
555 }
556
557 /**********************************************************************/
558
559 static void
560 startAgainTimeout(void)
561 {
562         NetState = NETLOOP_RESTART;
563 }
564
565 static void
566 startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
567 {
568         /* Totally ignore the packet */
569 }
570
571 void NetStartAgain (void)
572 {
573 #ifdef  CONFIG_NET_MULTI
574         DECLARE_GLOBAL_DATA_PTR;
575 #endif
576         char *nretry;
577         int noretry = 0, once = 0;
578
579         if ((nretry = getenv ("netretry")) != NULL) {
580                 noretry = (strcmp (nretry, "no") == 0);
581                 once = (strcmp (nretry, "once") == 0);
582         }
583         if (noretry) {
584                 eth_halt ();
585                 NetState = NETLOOP_FAIL;
586                 return;
587         }
588 #ifndef CONFIG_NET_MULTI
589         NetSetTimeout (10 * CFG_HZ, startAgainTimeout);
590         NetSetHandler (startAgainHandler);
591 #else   /* !CONFIG_NET_MULTI*/
592         eth_halt ();
593         eth_try_another (!NetRestarted);
594         eth_init (gd->bd);
595         if (NetRestartWrap) {
596                 NetRestartWrap = 0;
597                 if (NetDevExists && !once) {
598                         NetSetTimeout (10 * CFG_HZ, startAgainTimeout);
599                         NetSetHandler (startAgainHandler);
600                 } else {
601                         NetState = NETLOOP_FAIL;
602                 }
603         } else {
604                 NetState = NETLOOP_RESTART;
605         }
606 #endif  /* CONFIG_NET_MULTI */
607 }
608
609 /**********************************************************************/
610 /*
611  *      Miscelaneous bits.
612  */
613
614 void
615 NetSetHandler(rxhand_f * f)
616 {
617         packetHandler = f;
618 }
619
620
621 void
622 NetSetTimeout(ulong iv, thand_f * f)
623 {
624         if (iv == 0) {
625                 timeHandler = (thand_f *)0;
626         } else {
627                 timeHandler = f;
628                 timeStart = get_timer(0);
629                 timeDelta = iv;
630         }
631 }
632
633
634 void
635 NetSendPacket(volatile uchar * pkt, int len)
636 {
637         (void) eth_send(pkt, len);
638 }
639
640 int
641 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
642 {
643         uchar *pkt;
644
645         /* convert to new style broadcast */
646         if (dest == 0)
647                 dest = 0xFFFFFFFF;
648
649         /* if broadcast, make the ether address a broadcast and don't do ARP */
650         if (dest == 0xFFFFFFFF)
651                 ether = NetBcastAddr;
652
653         /* if MAC address was not discovered yet, save the packet and do an ARP request */
654         if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
655
656 #ifdef ET_DEBUG
657                 printf("sending ARP for %08lx\n", dest);
658 #endif
659                 NetArpWaitPacketIP = dest;
660                 NetArpWaitPacketMAC = ether;
661
662                 pkt = NetArpWaitTxPacket;
663                 pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);
664
665                 NetSetIP (pkt, dest, dport, sport, len);
666                 memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
667
668                 /* size of the waiting packet */
669                 NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
670
671                 /* and do the ARP request */
672                 NetArpWaitTry = 1;
673                 NetArpWaitTimerStart = get_timer(0);
674                 ArpRequest();
675                 return 1;       /* waiting */
676         }
677
678 #ifdef ET_DEBUG
679         printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
680                 dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
681 #endif
682
683         pkt = (uchar *)NetTxPacket;
684         pkt += NetSetEther (pkt, ether, PROT_IP);
685         NetSetIP (pkt, dest, dport, sport, len);
686         (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
687
688         return 0;       /* transmitted */
689 }
690
691 #if (CONFIG_COMMANDS & CFG_CMD_PING)
692 static ushort PingSeqNo;
693
694 int PingSend(void)
695 {
696         static uchar mac[6];
697         volatile IP_t *ip;
698         volatile ushort *s;
699         uchar *pkt;
700
701         /* XXX always send arp request */
702
703         memcpy(mac, NetEtherNullAddr, 6);
704
705 #ifdef ET_DEBUG
706         printf("sending ARP for %08lx\n", NetPingIP);
707 #endif
708
709         NetArpWaitPacketIP = NetPingIP;
710         NetArpWaitPacketMAC = mac;
711
712         pkt = NetArpWaitTxPacket;
713         pkt += NetSetEther(pkt, mac, PROT_IP);
714
715         ip = (volatile IP_t *)pkt;
716
717         /*
718          *      Construct an IP and ICMP header.  (need to set no fragment bit - XXX)
719          */
720         ip->ip_hl_v  = 0x45;            /* IP_HDR_SIZE / 4 (not including UDP) */
721         ip->ip_tos   = 0;
722         ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8);
723         ip->ip_id    = htons(NetIPID++);
724         ip->ip_off   = htons(0x4000);   /* No fragmentation */
725         ip->ip_ttl   = 255;
726         ip->ip_p     = 0x01;            /* ICMP */
727         ip->ip_sum   = 0;
728         NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
729         NetCopyIP((void*)&ip->ip_dst, &NetPingIP);         /* - "" - */
730         ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
731
732         s = &ip->udp_src;               /* XXX ICMP starts here */
733         s[0] = htons(0x0800);           /* echo-request, code */
734         s[1] = 0;                       /* checksum */
735         s[2] = 0;                       /* identifier */
736         s[3] = htons(PingSeqNo++);      /* sequence number */
737         s[1] = ~NetCksum((uchar *)s, 8/2);
738
739         /* size of the waiting packet */
740         NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
741
742         /* and do the ARP request */
743         NetArpWaitTry = 1;
744         NetArpWaitTimerStart = get_timer(0);
745         ArpRequest();
746         return 1;       /* waiting */
747 }
748
749 static void
750 PingTimeout (void)
751 {
752         eth_halt();
753         NetState = NETLOOP_FAIL;        /* we did not get the reply */
754 }
755
756 static void
757 PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
758 {
759         IPaddr_t tmp;
760         volatile IP_t *ip = (volatile IP_t *)pkt;
761
762         tmp = NetReadIP((void *)&ip->ip_src);
763         if (tmp != NetPingIP)
764                 return;
765
766         NetState = NETLOOP_SUCCESS;
767 }
768
769 static void PingStart(void)
770 {
771 #if defined(CONFIG_NET_MULTI)
772         printf ("Using %s device\n", eth_get_name());
773 #endif  /* CONFIG_NET_MULTI */
774         NetSetTimeout (10 * CFG_HZ, PingTimeout);
775         NetSetHandler (PingHandler);
776
777         PingSend();
778 }
779 #endif  /* CFG_CMD_PING */
780
781 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
782
783 #define CDP_DEVICE_ID_TLV               0x0001
784 #define CDP_ADDRESS_TLV                 0x0002
785 #define CDP_PORT_ID_TLV                 0x0003
786 #define CDP_CAPABILITIES_TLV            0x0004
787 #define CDP_VERSION_TLV                 0x0005
788 #define CDP_PLATFORM_TLV                0x0006
789 #define CDP_NATIVE_VLAN_TLV             0x000a
790 #define CDP_APPLIANCE_VLAN_TLV          0x000e
791 #define CDP_TRIGGER_TLV                 0x000f
792 #define CDP_POWER_CONSUMPTION_TLV       0x0010
793 #define CDP_SYSNAME_TLV                 0x0014
794 #define CDP_SYSOBJECT_TLV               0x0015
795 #define CDP_MANAGEMENT_ADDRESS_TLV      0x0016
796
797 #define CDP_TIMEOUT                     (CFG_HZ/4)      /* one packet every 250ms */
798
799 static int CDPSeq;
800 static int CDPOK;
801
802 ushort CDPNativeVLAN;
803 ushort CDPApplianceVLAN;
804
805 static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 };
806
807 static ushort CDP_compute_csum(const uchar *buff, ushort len)
808 {
809         ushort csum;
810         int     odd;
811         ulong   result = 0;
812         ushort  leftover;
813         ushort *p;
814
815         if (len > 0) {
816                 odd = 1 & (ulong)buff;
817                 if (odd) {
818                         result = *buff << 8;
819                         len--;
820                         buff++;
821                 }
822                 while (len > 1) {
823                         p = (ushort *)buff;
824                         result += *p++;
825                         buff = (uchar *)p;
826                         if (result & 0x80000000)
827                                 result = (result & 0xFFFF) + (result >> 16);
828                         len -= 2;
829                 }
830                 if (len) {
831                         leftover = (signed short)(*(const signed char *)buff);
832                         /* * XXX CISCO SUCKS big time! (and blows too) */
833                         result = (result & 0xffff0000) | ((result + leftover) & 0x0000ffff);
834                 }
835                 while (result >> 16)
836                         result = (result & 0xFFFF) + (result >> 16);
837
838                 if (odd)
839                         result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
840         }
841
842         /* add up 16-bit and 17-bit words for 17+c bits */
843         result = (result & 0xffff) + (result >> 16);
844         /* add up 16-bit and 2-bit for 16+c bit */
845         result = (result & 0xffff) + (result >> 16);
846         /* add up carry.. */
847         result = (result & 0xffff) + (result >> 16);
848
849         /* negate */
850         csum = ~(ushort)result;
851
852         /* run time endian detection */
853         if (csum != htons(csum))        /* little endian */
854                 csum = htons(csum);
855
856         return csum;
857 }
858
859 int CDPSendTrigger(void)
860 {
861         volatile uchar *pkt;
862         volatile ushort *s;
863         volatile ushort *cp;
864         Ethernet_t *et;
865         int len;
866         ushort chksum;
867 #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID)   || \
868     defined(CONFIG_CDP_VERSION)   || defined(CONFIG_CDP_PLATFORM)
869         char buf[32];
870 #endif
871
872         pkt = NetTxPacket;
873         et = (Ethernet_t *)pkt;
874
875         /* NOTE: trigger sent not on any VLAN */
876
877         /* form ethernet header */
878         memcpy(et->et_dest, NetCDPAddr, 6);
879         memcpy(et->et_src, NetOurEther, 6);
880
881         pkt += ETHER_HDR_SIZE;
882
883         /* SNAP header */
884         memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr));
885         pkt += sizeof(CDP_SNAP_hdr);
886
887         /* CDP header */
888         *pkt++ = 0x02;                          /* CDP version 2 */
889         *pkt++ = 180;                           /* TTL */
890         s = (volatile ushort *)pkt;
891         cp = s;
892         *s++ = htons(0);                        /* checksum (0 for later calculation) */
893
894         /* CDP fields */
895 #ifdef CONFIG_CDP_DEVICE_ID
896         *s++ = htons(CDP_DEVICE_ID_TLV);
897         *s++ = htons(CONFIG_CDP_DEVICE_ID);
898         memset(buf, 0, sizeof(buf));
899         sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%02X%02X%02X%02X%02X%02X",
900                 NetOurEther[0] & 0xff, NetOurEther[1] & 0xff,
901                 NetOurEther[2] & 0xff, NetOurEther[3] & 0xff,
902                 NetOurEther[4] & 0xff, NetOurEther[5] & 0xff);
903         memcpy((uchar *)s, buf, 16);
904         s += 16 / 2;
905 #endif
906
907 #ifdef CONFIG_CDP_PORT_ID
908         *s++ = htons(CDP_PORT_ID_TLV);
909         memset(buf, 0, sizeof(buf));
910         sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index());
911         len = strlen(buf);
912         if (len & 1)    /* make it even */
913                 len++;
914         *s++ = htons(len + 4);
915         memcpy((uchar *)s, buf, len);
916         s += len / 2;
917 #endif
918
919 #ifdef CONFIG_CDP_CAPABILITIES
920         *s++ = htons(CDP_CAPABILITIES_TLV);
921         *s++ = htons(8);
922         *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES);
923         s += 2;
924 #endif
925
926 #ifdef CONFIG_CDP_VERSION
927         *s++ = htons(CDP_VERSION_TLV);
928         memset(buf, 0, sizeof(buf));
929         strcpy(buf, CONFIG_CDP_VERSION);
930         len = strlen(buf);
931         if (len & 1)    /* make it even */
932                 len++;
933         *s++ = htons(len + 4);
934         memcpy((uchar *)s, buf, len);
935         s += len / 2;
936 #endif
937
938 #ifdef CONFIG_CDP_PLATFORM
939         *s++ = htons(CDP_PLATFORM_TLV);
940         memset(buf, 0, sizeof(buf));
941         strcpy(buf, CONFIG_CDP_PLATFORM);
942         len = strlen(buf);
943         if (len & 1)    /* make it even */
944                 len++;
945         *s++ = htons(len + 4);
946         memcpy((uchar *)s, buf, len);
947         s += len / 2;
948 #endif
949
950 #ifdef CONFIG_CDP_TRIGGER
951         *s++ = htons(CDP_TRIGGER_TLV);
952         *s++ = htons(8);
953         *(ulong *)s = htonl(CONFIG_CDP_TRIGGER);
954         s += 2;
955 #endif
956
957 #ifdef CONFIG_CDP_POWER_CONSUMPTION
958         *s++ = htons(CDP_POWER_CONSUMPTION_TLV);
959         *s++ = htons(6);
960         *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION);
961 #endif
962
963         /* length of ethernet packet */
964         len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE);
965         et->et_protlen = htons(len);
966
967         len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr);
968         chksum = CDP_compute_csum((uchar *)NetTxPacket + len, (uchar *)s - (NetTxPacket + len));
969         if (chksum == 0)
970                 chksum = 0xFFFF;
971         *cp = htons(chksum);
972
973         (void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket);
974         return 0;
975 }
976
977 static void
978 CDPTimeout (void)
979 {
980         CDPSeq++;
981
982         if (CDPSeq < 3) {
983                 NetSetTimeout (CDP_TIMEOUT, CDPTimeout);
984                 CDPSendTrigger();
985                 return;
986         }
987
988         /* if not OK try again */
989         if (!CDPOK)
990                 NetStartAgain();
991         else
992                 NetState = NETLOOP_SUCCESS;
993 }
994
995 static void
996 CDPDummyHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
997 {
998         /* nothing */
999 }
1000
1001 static void
1002 CDPHandler(const uchar * pkt, unsigned len)
1003 {
1004         const uchar *t;
1005         const ushort *ss;
1006         ushort type, tlen;
1007         uchar applid;
1008         ushort vlan, nvlan;
1009
1010         /* minimum size? */
1011         if (len < sizeof(CDP_SNAP_hdr) + 4)
1012                 goto pkt_short;
1013
1014         /* check for valid CDP SNAP header */
1015         if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0)
1016                 return;
1017
1018         pkt += sizeof(CDP_SNAP_hdr);
1019         len -= sizeof(CDP_SNAP_hdr);
1020
1021         /* Version of CDP protocol must be >= 2 and TTL != 0 */
1022         if (pkt[0] < 0x02 || pkt[1] == 0)
1023                 return;
1024
1025         /* if version is greater than 0x02 maybe we'll have a problem; output a warning */
1026         if (pkt[0] != 0x02)
1027                 printf("** WARNING: CDP packet received with a protocol version %d > 2\n",
1028                                 pkt[0] & 0xff);
1029
1030         if (CDP_compute_csum(pkt, len) != 0)
1031                 return;
1032
1033         pkt += 4;
1034         len -= 4;
1035
1036         vlan = htons(-1);
1037         nvlan = htons(-1);
1038         while (len > 0) {
1039                 if (len < 4)
1040                         goto pkt_short;
1041
1042                 ss = (const ushort *)pkt;
1043                 type = ntohs(ss[0]);
1044                 tlen = ntohs(ss[1]);
1045                 if (tlen > len) {
1046                         goto pkt_short;
1047                 }
1048
1049                 pkt += tlen;
1050                 len -= tlen;
1051
1052                 ss += 2;        /* point ss to the data of the TLV */
1053                 tlen -= 4;
1054
1055                 switch (type) {
1056                         case CDP_DEVICE_ID_TLV:
1057                                 break;
1058                         case CDP_ADDRESS_TLV:
1059                                 break;
1060                         case CDP_PORT_ID_TLV:
1061                                 break;
1062                         case CDP_CAPABILITIES_TLV:
1063                                 break;
1064                         case CDP_VERSION_TLV:
1065                                 break;
1066                         case CDP_PLATFORM_TLV:
1067                                 break;
1068                         case CDP_NATIVE_VLAN_TLV:
1069                                 nvlan = *ss;
1070                                 break;
1071                         case CDP_APPLIANCE_VLAN_TLV:
1072                                 t = (const uchar *)ss;
1073                                 while (tlen > 0) {
1074                                         if (tlen < 3)
1075                                                 goto pkt_short;
1076
1077                                         applid = t[0];
1078                                         ss = (const ushort *)(t + 1);
1079
1080 #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
1081                                         if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
1082                                                 vlan = *ss;
1083 #else
1084                                         vlan = ntohs(*ss);      /* XXX will this work; dunno */
1085 #endif
1086                                         t += 3; tlen -= 3;
1087                                 }
1088                                 break;
1089                         case CDP_TRIGGER_TLV:
1090                                 break;
1091                         case CDP_POWER_CONSUMPTION_TLV:
1092                                 break;
1093                         case CDP_SYSNAME_TLV:
1094                                 break;
1095                         case CDP_SYSOBJECT_TLV:
1096                                 break;
1097                         case CDP_MANAGEMENT_ADDRESS_TLV:
1098                                 break;
1099                 }
1100         }
1101
1102         CDPApplianceVLAN = vlan;
1103         CDPNativeVLAN = nvlan;
1104
1105         CDPOK = 1;
1106         return;
1107
1108  pkt_short:
1109         printf("** CDP packet is too short\n");
1110         return;
1111 }
1112
1113 static void CDPStart(void)
1114 {
1115 #if defined(CONFIG_NET_MULTI)
1116         printf ("Using %s device\n", eth_get_name());
1117 #endif
1118         CDPSeq = 0;
1119         CDPOK = 0;
1120
1121         CDPNativeVLAN = htons(-1);
1122         CDPApplianceVLAN = htons(-1);
1123
1124         NetSetTimeout (CDP_TIMEOUT, CDPTimeout);
1125         NetSetHandler (CDPDummyHandler);
1126
1127         CDPSendTrigger();
1128 }
1129 #endif  /* CFG_CMD_CDP */
1130
1131
1132 void
1133 NetReceive(volatile uchar * inpkt, int len)
1134 {
1135         Ethernet_t *et;
1136         IP_t    *ip;
1137         ARP_t   *arp;
1138         IPaddr_t tmp;
1139         int     x;
1140         uchar *pkt;
1141 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1142         int iscdp;
1143 #endif
1144         ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
1145
1146 #ifdef ET_DEBUG
1147         printf("packet received\n");
1148 #endif
1149
1150         NetRxPkt = inpkt;
1151         NetRxPktLen = len;
1152         et = (Ethernet_t *)inpkt;
1153
1154         /* too small packet? */
1155         if (len < ETHER_HDR_SIZE)
1156                 return;
1157
1158 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1159         /* keep track if packet is CDP */
1160         iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0;
1161 #endif
1162
1163         myvlanid = ntohs(NetOurVLAN);
1164         if (myvlanid == (ushort)-1)
1165                 myvlanid = VLAN_NONE;
1166         mynvlanid = ntohs(NetOurNativeVLAN);
1167         if (mynvlanid == (ushort)-1)
1168                 mynvlanid = VLAN_NONE;
1169
1170         x = ntohs(et->et_protlen);
1171
1172 #ifdef ET_DEBUG
1173         printf("packet received\n");
1174 #endif
1175
1176         if (x < 1514) {
1177                 /*
1178                  *      Got a 802 packet.  Check the other protocol field.
1179                  */
1180                 x = ntohs(et->et_prot);
1181
1182                 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
1183                 len -= E802_HDR_SIZE;
1184
1185         } else if (x != PROT_VLAN) {    /* normal packet */
1186                 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
1187                 len -= ETHER_HDR_SIZE;
1188
1189         } else {                        /* VLAN packet */
1190                 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
1191
1192 #ifdef ET_DEBUG
1193                 printf("VLAN packet received\n");
1194 #endif
1195                 /* too small packet? */
1196                 if (len < VLAN_ETHER_HDR_SIZE)
1197                         return;
1198
1199                 /* if no VLAN active */
1200                 if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
1201 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1202                                 && iscdp == 0
1203 #endif
1204                                 )
1205                         return;
1206
1207                 cti = ntohs(vet->vet_tag);
1208                 vlanid = cti & VLAN_IDMASK;
1209                 x = ntohs(vet->vet_type);
1210
1211                 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
1212                 len -= VLAN_ETHER_HDR_SIZE;
1213         }
1214
1215 #ifdef ET_DEBUG
1216         printf("Receive from protocol 0x%x\n", x);
1217 #endif
1218
1219 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1220         if (iscdp) {
1221                 CDPHandler((uchar *)ip, len);
1222                 return;
1223         }
1224 #endif
1225
1226         if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1227                 if (vlanid == VLAN_NONE)
1228                         vlanid = (mynvlanid & VLAN_IDMASK);
1229                 /* not matched? */
1230                 if (vlanid != (myvlanid & VLAN_IDMASK))
1231                         return;
1232         }
1233
1234         switch (x) {
1235
1236         case PROT_ARP:
1237                 /*
1238                  * We have to deal with two types of ARP packets:
1239                  * - REQUEST packets will be answered by sending  our
1240                  *   IP address - if we know it.
1241                  * - REPLY packates are expected only after we asked
1242                  *   for the TFTP server's or the gateway's ethernet
1243                  *   address; so if we receive such a packet, we set
1244                  *   the server ethernet address
1245                  */
1246 #ifdef ET_DEBUG
1247                 puts ("Got ARP\n");
1248 #endif
1249                 arp = (ARP_t *)ip;
1250                 if (len < ARP_HDR_SIZE) {
1251                         printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1252                         return;
1253                 }
1254                 if (ntohs(arp->ar_hrd) != ARP_ETHER) {
1255                         return;
1256                 }
1257                 if (ntohs(arp->ar_pro) != PROT_IP) {
1258                         return;
1259                 }
1260                 if (arp->ar_hln != 6) {
1261                         return;
1262                 }
1263                 if (arp->ar_pln != 4) {
1264                         return;
1265                 }
1266
1267                 if (NetOurIP == 0) {
1268                         return;
1269                 }
1270
1271                 if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
1272                         return;
1273                 }
1274
1275                 switch (ntohs(arp->ar_op)) {
1276                 case ARPOP_REQUEST:             /* reply with our IP address    */
1277 #ifdef ET_DEBUG
1278                         puts ("Got ARP REQUEST, return our IP\n");
1279 #endif
1280                         pkt = (uchar *)et;
1281                         pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
1282                         arp->ar_op = htons(ARPOP_REPLY);
1283                         memcpy   (&arp->ar_data[10], &arp->ar_data[0], 6);
1284                         NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
1285                         memcpy   (&arp->ar_data[ 0], NetOurEther, 6);
1286                         NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
1287                         (void) eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
1288                         return;
1289
1290                 case ARPOP_REPLY:               /* arp reply */
1291                         /* are we waiting for a reply */
1292                         if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
1293                                 break;
1294 #ifdef ET_DEBUG
1295                         printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
1296                                 arp->ar_data[0], arp->ar_data[1],
1297                                 arp->ar_data[2], arp->ar_data[3],
1298                                 arp->ar_data[4], arp->ar_data[5]);
1299 #endif
1300
1301                         tmp = NetReadIP(&arp->ar_data[6]);
1302
1303                         /* matched waiting packet's address */
1304                         if (tmp == NetArpWaitReplyIP) {
1305 #ifdef ET_DEBUG
1306                                 puts ("Got it\n");
1307 #endif
1308                                 /* save address for later use */
1309                                 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
1310
1311 #ifdef CONFIG_NETCONSOLE
1312                                 (*packetHandler)(0,0,0,0);
1313 #endif
1314                                 /* modify header, and transmit it */
1315                                 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
1316                                 (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
1317
1318                                 /* no arp request pending now */
1319                                 NetArpWaitPacketIP = 0;
1320                                 NetArpWaitTxPacketSize = 0;
1321                                 NetArpWaitPacketMAC = NULL;
1322
1323                         }
1324                         return;
1325                 default:
1326 #ifdef ET_DEBUG
1327                         printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
1328 #endif
1329                         return;
1330                 }
1331                 break;
1332
1333         case PROT_RARP:
1334 #ifdef ET_DEBUG
1335                 puts ("Got RARP\n");
1336 #endif
1337                 arp = (ARP_t *)ip;
1338                 if (len < ARP_HDR_SIZE) {
1339                         printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1340                         return;
1341                 }
1342
1343                 if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
1344                         (ntohs(arp->ar_hrd) != ARP_ETHER)   ||
1345                         (ntohs(arp->ar_pro) != PROT_IP)     ||
1346                         (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
1347
1348                         puts ("invalid RARP header\n");
1349                 } else {
1350                         NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
1351                         if (NetServerIP == 0)
1352                                 NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
1353                         memcpy (NetServerEther, &arp->ar_data[ 0], 6);
1354
1355                         (*packetHandler)(0,0,0,0);
1356                 }
1357                 break;
1358
1359         case PROT_IP:
1360 #ifdef ET_DEBUG
1361                 puts ("Got IP\n");
1362 #endif
1363                 if (len < IP_HDR_SIZE) {
1364                         debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
1365                         return;
1366                 }
1367                 if (len < ntohs(ip->ip_len)) {
1368                         printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
1369                         return;
1370                 }
1371                 len = ntohs(ip->ip_len);
1372 #ifdef ET_DEBUG
1373                 printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
1374 #endif
1375                 if ((ip->ip_hl_v & 0xf0) != 0x40) {
1376                         return;
1377                 }
1378                 if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
1379                         return;
1380                 }
1381                 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
1382                         puts ("checksum bad\n");
1383                         return;
1384                 }
1385                 tmp = NetReadIP(&ip->ip_dst);
1386                 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
1387                         return;
1388                 }
1389                 /*
1390                  * watch for ICMP host redirects
1391                  *
1392                  * There is no real handler code (yet). We just watch
1393                  * for ICMP host redirect messages. In case anybody
1394                  * sees these messages: please contact me
1395                  * (wd@denx.de), or - even better - send me the
1396                  * necessary fixes :-)
1397                  *
1398                  * Note: in all cases where I have seen this so far
1399                  * it was a problem with the router configuration,
1400                  * for instance when a router was configured in the
1401                  * BOOTP reply, but the TFTP server was on the same
1402                  * subnet. So this is probably a warning that your
1403                  * configuration might be wrong. But I'm not really
1404                  * sure if there aren't any other situations.
1405                  */
1406                 if (ip->ip_p == IPPROTO_ICMP) {
1407                         ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
1408
1409                         switch (icmph->type) {
1410                         case ICMP_REDIRECT:
1411                                 if (icmph->code != ICMP_REDIR_HOST)
1412                                         return;
1413                                 puts (" ICMP Host Redirect to ");
1414                                 print_IPaddr(icmph->un.gateway);
1415                                 putc(' ');
1416                                 return;
1417 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1418                         case ICMP_ECHO_REPLY:
1419                                 /*
1420                                  *      IP header OK.  Pass the packet to the current handler.
1421                                  */
1422                                 /* XXX point to ip packet */
1423                                 (*packetHandler)((uchar *)ip, 0, 0, 0);
1424                                 return;
1425 #endif
1426                         default:
1427                                 return;
1428                         }
1429                 } else if (ip->ip_p != IPPROTO_UDP) {   /* Only UDP packets */
1430                         return;
1431                 }
1432
1433 #ifdef CONFIG_UDP_CHECKSUM
1434                 if (ip->udp_xsum != 0) {
1435                         ulong   xsum;
1436                         ushort *sumptr;
1437                         ushort  sumlen;
1438
1439                         xsum  = ip->ip_p;
1440                         xsum += (ntohs(ip->udp_len));
1441                         xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1442                         xsum += (ntohl(ip->ip_src) >>  0) & 0x0000ffff;
1443                         xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1444                         xsum += (ntohl(ip->ip_dst) >>  0) & 0x0000ffff;
1445
1446                         sumlen = ntohs(ip->udp_len);
1447                         sumptr = (ushort *) &(ip->udp_src);
1448
1449                         while (sumlen > 1) {
1450                                 ushort sumdata;
1451
1452                                 sumdata = *sumptr++;
1453                                 xsum += ntohs(sumdata);
1454                                 sumlen -= 2;
1455                         }
1456                         if (sumlen > 0) {
1457                                 ushort sumdata;
1458
1459                                 sumdata = *(unsigned char *) sumptr;
1460                                 sumdata = (sumdata << 8) & 0xff00;
1461                                 xsum += sumdata;
1462                         }
1463                         while ((xsum >> 16) != 0) {
1464                                 xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
1465                         }
1466                         if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1467                                 printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
1468                                 return;
1469                         }
1470                 }
1471 #endif
1472
1473 #ifdef CONFIG_NETCONSOLE
1474                 nc_input_packet((uchar *)ip +IP_HDR_SIZE,
1475                                                 ntohs(ip->udp_dst),
1476                                                 ntohs(ip->udp_src),
1477                                                 ntohs(ip->udp_len) - 8);
1478 #endif
1479                 /*
1480                  *      IP header OK.  Pass the packet to the current handler.
1481                  */
1482                 (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
1483                                                 ntohs(ip->udp_dst),
1484                                                 ntohs(ip->udp_src),
1485                                                 ntohs(ip->udp_len) - 8);
1486                 break;
1487         }
1488 }
1489
1490
1491 /**********************************************************************/
1492
1493 static int net_check_prereq (proto_t protocol)
1494 {
1495         switch (protocol) {
1496                 /* Fall through */
1497 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1498         case PING:
1499                 if (NetPingIP == 0) {
1500                         puts ("*** ERROR: ping address not given\n");
1501                         return (1);
1502                 }
1503                 goto common;
1504 #endif
1505 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
1506         case SNTP:
1507                 if (NetNtpServerIP == 0) {
1508                         puts ("*** ERROR: NTP server address not given\n");
1509                         return (1);
1510                 }
1511                 goto common;
1512 #endif
1513 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
1514         case NFS:
1515 #endif
1516         case NETCONS:
1517         case TFTP:
1518                 if (NetServerIP == 0) {
1519                         puts ("*** ERROR: `serverip' not set\n");
1520                         return (1);
1521                 }
1522 #if (CONFIG_COMMANDS & (CFG_CMD_PING | CFG_CMD_SNTP))
1523     common:
1524 #endif
1525
1526                 if (NetOurIP == 0) {
1527                         puts ("*** ERROR: `ipaddr' not set\n");
1528                         return (1);
1529                 }
1530                 /* Fall through */
1531
1532         case DHCP:
1533         case RARP:
1534         case BOOTP:
1535         case CDP:
1536                 if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
1537 #ifdef CONFIG_NET_MULTI
1538                         extern int eth_get_dev_index (void);
1539                         int num = eth_get_dev_index ();
1540
1541                         switch (num) {
1542                         case -1:
1543                                 puts ("*** ERROR: No ethernet found.\n");
1544                                 return (1);
1545                         case 0:
1546                                 puts ("*** ERROR: `ethaddr' not set\n");
1547                                 break;
1548                         default:
1549                                 printf ("*** ERROR: `eth%daddr' not set\n",
1550                                         num);
1551                                 break;
1552                         }
1553
1554                         NetStartAgain ();
1555                         return (2);
1556 #else
1557                         puts ("*** ERROR: `ethaddr' not set\n");
1558                         return (1);
1559 #endif
1560                 }
1561                 /* Fall through */
1562         default:
1563                 return (0);
1564         }
1565         return (0);             /* OK */
1566 }
1567 /**********************************************************************/
1568
1569 int
1570 NetCksumOk(uchar * ptr, int len)
1571 {
1572         return !((NetCksum(ptr, len) + 1) & 0xfffe);
1573 }
1574
1575
1576 unsigned
1577 NetCksum(uchar * ptr, int len)
1578 {
1579         ulong   xsum;
1580         ushort *p = (ushort *)ptr;
1581
1582         xsum = 0;
1583         while (len-- > 0)
1584                 xsum += *p++;
1585         xsum = (xsum & 0xffff) + (xsum >> 16);
1586         xsum = (xsum & 0xffff) + (xsum >> 16);
1587         return (xsum & 0xffff);
1588 }
1589
1590 int
1591 NetEthHdrSize(void)
1592 {
1593         ushort myvlanid;
1594
1595         myvlanid = ntohs(NetOurVLAN);
1596         if (myvlanid == (ushort)-1)
1597                 myvlanid = VLAN_NONE;
1598
1599         return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
1600 }
1601
1602 int
1603 NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
1604 {
1605         Ethernet_t *et = (Ethernet_t *)xet;
1606         ushort myvlanid;
1607
1608         myvlanid = ntohs(NetOurVLAN);
1609         if (myvlanid == (ushort)-1)
1610                 myvlanid = VLAN_NONE;
1611
1612         memcpy (et->et_dest, addr, 6);
1613         memcpy (et->et_src, NetOurEther, 6);
1614         if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1615         et->et_protlen = htons(prot);
1616                 return ETHER_HDR_SIZE;
1617         } else {
1618                 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1619
1620                 vet->vet_vlan_type = htons(PROT_VLAN);
1621                 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1622                 vet->vet_type = htons(prot);
1623                 return VLAN_ETHER_HDR_SIZE;
1624         }
1625 }
1626
1627 void
1628 NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
1629 {
1630         volatile IP_t *ip = (IP_t *)xip;
1631
1632         /*
1633          *      If the data is an odd number of bytes, zero the
1634          *      byte after the last byte so that the checksum
1635          *      will work.
1636          */
1637         if (len & 1)
1638                 xip[IP_HDR_SIZE + len] = 0;
1639
1640         /*
1641          *      Construct an IP and UDP header.
1642          *      (need to set no fragment bit - XXX)
1643          */
1644         ip->ip_hl_v  = 0x45;            /* IP_HDR_SIZE / 4 (not including UDP) */
1645         ip->ip_tos   = 0;
1646         ip->ip_len   = htons(IP_HDR_SIZE + len);
1647         ip->ip_id    = htons(NetIPID++);
1648         ip->ip_off   = htons(0x4000);   /* No fragmentation */
1649         ip->ip_ttl   = 255;
1650         ip->ip_p     = 17;              /* UDP */
1651         ip->ip_sum   = 0;
1652         NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1653         NetCopyIP((void*)&ip->ip_dst, &dest);      /* - "" - */
1654         ip->udp_src  = htons(sport);
1655         ip->udp_dst  = htons(dport);
1656         ip->udp_len  = htons(8 + len);
1657         ip->udp_xsum = 0;
1658         ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1659 }
1660
1661 void copy_filename (char *dst, char *src, int size)
1662 {
1663         if (*src && (*src == '"')) {
1664                 ++src;
1665                 --size;
1666         }
1667
1668         while ((--size > 0) && *src && (*src != '"')) {
1669                 *dst++ = *src++;
1670         }
1671         *dst = '\0';
1672 }
1673
1674 #endif /* CFG_CMD_NET */
1675
1676 void ip_to_string (IPaddr_t x, char *s)
1677 {
1678         x = ntohl (x);
1679         sprintf (s, "%d.%d.%d.%d",
1680                  (int) ((x >> 24) & 0xff),
1681                  (int) ((x >> 16) & 0xff),
1682                  (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
1683         );
1684 }
1685
1686 IPaddr_t string_to_ip(char *s)
1687 {
1688         IPaddr_t addr;
1689         char *e;
1690         int i;
1691
1692         if (s == NULL)
1693                 return(0);
1694
1695         for (addr=0, i=0; i<4; ++i) {
1696                 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1697                 addr <<= 8;
1698                 addr |= (val & 0xFF);
1699                 if (s) {
1700                         s = (*e) ? e+1 : e;
1701                 }
1702         }
1703
1704         return (htonl(addr));
1705 }
1706
1707 void VLAN_to_string(ushort x, char *s)
1708 {
1709         x = ntohs(x);
1710
1711         if (x == (ushort)-1)
1712                 x = VLAN_NONE;
1713
1714         if (x == VLAN_NONE)
1715                 strcpy(s, "none");
1716         else
1717                 sprintf(s, "%d", x & VLAN_IDMASK);
1718 }
1719
1720 ushort string_to_VLAN(char *s)
1721 {
1722         ushort id;
1723
1724         if (s == NULL)
1725                 return htons(VLAN_NONE);
1726
1727         if (*s < '0' || *s > '9')
1728                 id = VLAN_NONE;
1729         else
1730                 id = (ushort)simple_strtoul(s, NULL, 10);
1731
1732         return htons(id);
1733 }
1734
1735 void print_IPaddr (IPaddr_t x)
1736 {
1737         char tmp[16];
1738
1739         ip_to_string (x, tmp);
1740
1741         puts (tmp);
1742 }
1743
1744 IPaddr_t getenv_IPaddr (char *var)
1745 {
1746         return (string_to_ip(getenv(var)));
1747 }
1748
1749 ushort getenv_VLAN(char *var)
1750 {
1751         return (string_to_VLAN(getenv(var)));
1752 }