]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - net/net.c
d13ae74cd144646abe933c653721249996a890c8
[karo-tx-uboot.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  * 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
814         if (len > 0) {
815                 odd = 1 & (ulong)buff;
816                 if (odd) {
817                         result = *buff << 8;
818                         len--;
819                         buff++;
820                 }
821                 while (len > 1) {
822                         result += *((const ushort *)buff)++;
823                         if (result & 0x80000000)
824                                 result = (result & 0xFFFF) + (result >> 16);
825                         len -= 2;
826                 }
827                 if (len) {
828                         leftover = (signed short)(*(const signed char *)buff);
829                         /* * XXX CISCO SUCKS big time! (and blows too) */
830                         result = (result & 0xffff0000) | ((result + leftover) & 0x0000ffff);
831                 }
832                 while (result >> 16)
833                         result = (result & 0xFFFF) + (result >> 16);
834
835                 if (odd)
836                         result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
837         }
838
839         /* add up 16-bit and 17-bit words for 17+c bits */
840         result = (result & 0xffff) + (result >> 16);
841         /* add up 16-bit and 2-bit for 16+c bit */
842         result = (result & 0xffff) + (result >> 16);
843         /* add up carry.. */
844         result = (result & 0xffff) + (result >> 16);
845
846         /* negate */
847         csum = ~(ushort)result;
848
849         /* run time endian detection */
850         if (csum != htons(csum))        /* little endian */
851                 csum = htons(csum);
852
853         return csum;
854 }
855
856 int CDPSendTrigger(void)
857 {
858         volatile uchar *pkt;
859         volatile ushort *s;
860         volatile ushort *cp;
861         Ethernet_t *et;
862         int len;
863         ushort chksum;
864 #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID)   || \
865     defined(CONFIG_CDP_VERSION)   || defined(CONFIG_CDP_PLATFORM)
866         char buf[32];
867 #endif
868
869         pkt = NetTxPacket;
870         et = (Ethernet_t *)pkt;
871
872         /* NOTE: trigger sent not on any VLAN */
873
874         /* form ethernet header */
875         memcpy(et->et_dest, NetCDPAddr, 6);
876         memcpy(et->et_src, NetOurEther, 6);
877
878         pkt += ETHER_HDR_SIZE;
879
880         /* SNAP header */
881         memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr));
882         pkt += sizeof(CDP_SNAP_hdr);
883
884         /* CDP header */
885         *pkt++ = 0x02;                          /* CDP version 2 */
886         *pkt++ = 180;                           /* TTL */
887         s = (volatile ushort *)pkt;
888         cp = s;
889         *s++ = htons(0);                        /* checksum (0 for later calculation) */
890
891         /* CDP fields */
892 #ifdef CONFIG_CDP_DEVICE_ID
893         *s++ = htons(CDP_DEVICE_ID_TLV);
894         *s++ = htons(CONFIG_CDP_DEVICE_ID);
895         memset(buf, 0, sizeof(buf));
896         sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%02X%02X%02X%02X%02X%02X",
897                 NetOurEther[0] & 0xff, NetOurEther[1] & 0xff,
898                 NetOurEther[2] & 0xff, NetOurEther[3] & 0xff,
899                 NetOurEther[4] & 0xff, NetOurEther[5] & 0xff);
900         memcpy((uchar *)s, buf, 16);
901         s += 16 / 2;
902 #endif
903
904 #ifdef CONFIG_CDP_PORT_ID
905         *s++ = htons(CDP_PORT_ID_TLV);
906         memset(buf, 0, sizeof(buf));
907         sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index());
908         len = strlen(buf);
909         if (len & 1)    /* make it even */
910                 len++;
911         *s++ = htons(len + 4);
912         memcpy((uchar *)s, buf, len);
913         s += len / 2;
914 #endif
915
916 #ifdef CONFIG_CDP_CAPABILITIES
917         *s++ = htons(CDP_CAPABILITIES_TLV);
918         *s++ = htons(8);
919         *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES);
920         s += 2;
921 #endif
922
923 #ifdef CONFIG_CDP_VERSION
924         *s++ = htons(CDP_VERSION_TLV);
925         memset(buf, 0, sizeof(buf));
926         strcpy(buf, CONFIG_CDP_VERSION);
927         len = strlen(buf);
928         if (len & 1)    /* make it even */
929                 len++;
930         *s++ = htons(len + 4);
931         memcpy((uchar *)s, buf, len);
932         s += len / 2;
933 #endif
934
935 #ifdef CONFIG_CDP_PLATFORM
936         *s++ = htons(CDP_PLATFORM_TLV);
937         memset(buf, 0, sizeof(buf));
938         strcpy(buf, CONFIG_CDP_PLATFORM);
939         len = strlen(buf);
940         if (len & 1)    /* make it even */
941                 len++;
942         *s++ = htons(len + 4);
943         memcpy((uchar *)s, buf, len);
944         s += len / 2;
945 #endif
946
947 #ifdef CONFIG_CDP_TRIGGER
948         *s++ = htons(CDP_TRIGGER_TLV);
949         *s++ = htons(8);
950         *(ulong *)s = htonl(CONFIG_CDP_TRIGGER);
951         s += 2;
952 #endif
953
954 #ifdef CONFIG_CDP_POWER_CONSUMPTION
955         *s++ = htons(CDP_POWER_CONSUMPTION_TLV);
956         *s++ = htons(6);
957         *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION);
958 #endif
959
960         /* length of ethernet packet */
961         len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE);
962         et->et_protlen = htons(len);
963
964         len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr);
965         chksum = CDP_compute_csum((uchar *)NetTxPacket + len, (uchar *)s - (NetTxPacket + len));
966         if (chksum == 0)
967                 chksum = 0xFFFF;
968         *cp = htons(chksum);
969
970         (void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket);
971         return 0;
972 }
973
974 static void
975 CDPTimeout (void)
976 {
977         CDPSeq++;
978
979         if (CDPSeq < 3) {
980                 NetSetTimeout (CDP_TIMEOUT, CDPTimeout);
981                 CDPSendTrigger();
982                 return;
983         }
984
985         /* if not OK try again */
986         if (!CDPOK)
987                 NetStartAgain();
988         else
989                 NetState = NETLOOP_SUCCESS;
990 }
991
992 static void
993 CDPDummyHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
994 {
995         /* nothing */
996 }
997
998 static void
999 CDPHandler(const uchar * pkt, unsigned len)
1000 {
1001         const uchar *t;
1002         const ushort *ss;
1003         ushort type, tlen;
1004         uchar applid;
1005         ushort vlan, nvlan;
1006
1007         /* minimum size? */
1008         if (len < sizeof(CDP_SNAP_hdr) + 4)
1009                 goto pkt_short;
1010
1011         /* check for valid CDP SNAP header */
1012         if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0)
1013                 return;
1014
1015         pkt += sizeof(CDP_SNAP_hdr);
1016         len -= sizeof(CDP_SNAP_hdr);
1017
1018         /* Version of CDP protocol must be >= 2 and TTL != 0 */
1019         if (pkt[0] < 0x02 || pkt[1] == 0)
1020                 return;
1021
1022         /* if version is greater than 0x02 maybe we'll have a problem; output a warning */
1023         if (pkt[0] != 0x02)
1024                 printf("** WARNING: CDP packet received with a protocol version %d > 2\n",
1025                                 pkt[0] & 0xff);
1026
1027         if (CDP_compute_csum(pkt, len) != 0)
1028                 return;
1029
1030         pkt += 4;
1031         len -= 4;
1032
1033         vlan = htons(-1);
1034         nvlan = htons(-1);
1035         while (len > 0) {
1036                 if (len < 4)
1037                         goto pkt_short;
1038
1039                 ss = (const ushort *)pkt;
1040                 type = ntohs(ss[0]);
1041                 tlen = ntohs(ss[1]);
1042                 if (tlen > len) {
1043                         goto pkt_short;
1044                 }
1045
1046                 pkt += tlen;
1047                 len -= tlen;
1048
1049                 ss += 2;        /* point ss to the data of the TLV */
1050                 tlen -= 4;
1051
1052                 switch (type) {
1053                         case CDP_DEVICE_ID_TLV:
1054                                 break;
1055                         case CDP_ADDRESS_TLV:
1056                                 break;
1057                         case CDP_PORT_ID_TLV:
1058                                 break;
1059                         case CDP_CAPABILITIES_TLV:
1060                                 break;
1061                         case CDP_VERSION_TLV:
1062                                 break;
1063                         case CDP_PLATFORM_TLV:
1064                                 break;
1065                         case CDP_NATIVE_VLAN_TLV:
1066                                 nvlan = *ss;
1067                                 break;
1068                         case CDP_APPLIANCE_VLAN_TLV:
1069                                 t = (const uchar *)ss;
1070                                 while (tlen > 0) {
1071                                         if (tlen < 3)
1072                                                 goto pkt_short;
1073
1074                                         applid = t[0];
1075                                         ss = (const ushort *)(t + 1);
1076
1077 #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
1078                                         if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
1079                                                 vlan = *ss;
1080 #else
1081                                         vlan = ntohs(*ss);      /* XXX will this work; dunno */
1082 #endif
1083                                         t += 3; tlen -= 3;
1084                                 }
1085                                 break;
1086                         case CDP_TRIGGER_TLV:
1087                                 break;
1088                         case CDP_POWER_CONSUMPTION_TLV:
1089                                 break;
1090                         case CDP_SYSNAME_TLV:
1091                                 break;
1092                         case CDP_SYSOBJECT_TLV:
1093                                 break;
1094                         case CDP_MANAGEMENT_ADDRESS_TLV:
1095                                 break;
1096                 }
1097         }
1098
1099         CDPApplianceVLAN = vlan;
1100         CDPNativeVLAN = nvlan;
1101
1102         CDPOK = 1;
1103         return;
1104
1105  pkt_short:
1106         printf("** CDP packet is too short\n");
1107         return;
1108 }
1109
1110 static void CDPStart(void)
1111 {
1112 #if defined(CONFIG_NET_MULTI)
1113         printf ("Using %s device\n", eth_get_name());
1114 #endif
1115         CDPSeq = 0;
1116         CDPOK = 0;
1117
1118         CDPNativeVLAN = htons(-1);
1119         CDPApplianceVLAN = htons(-1);
1120
1121         NetSetTimeout (CDP_TIMEOUT, CDPTimeout);
1122         NetSetHandler (CDPDummyHandler);
1123
1124         CDPSendTrigger();
1125 }
1126 #endif  /* CFG_CMD_CDP */
1127
1128
1129 void
1130 NetReceive(volatile uchar * inpkt, int len)
1131 {
1132         Ethernet_t *et;
1133         IP_t    *ip;
1134         ARP_t   *arp;
1135         IPaddr_t tmp;
1136         int     x;
1137         uchar *pkt;
1138 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1139         int iscdp;
1140 #endif
1141         ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
1142
1143 #ifdef ET_DEBUG
1144         printf("packet received\n");
1145 #endif
1146
1147         NetRxPkt = inpkt;
1148         NetRxPktLen = len;
1149         et = (Ethernet_t *)inpkt;
1150
1151         /* too small packet? */
1152         if (len < ETHER_HDR_SIZE)
1153                 return;
1154
1155 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1156         /* keep track if packet is CDP */
1157         iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0;
1158 #endif
1159
1160         myvlanid = ntohs(NetOurVLAN);
1161         if (myvlanid == (ushort)-1)
1162                 myvlanid = VLAN_NONE;
1163         mynvlanid = ntohs(NetOurNativeVLAN);
1164         if (mynvlanid == (ushort)-1)
1165                 mynvlanid = VLAN_NONE;
1166
1167         x = ntohs(et->et_protlen);
1168
1169 #ifdef ET_DEBUG
1170         printf("packet received\n");
1171 #endif
1172
1173         if (x < 1514) {
1174                 /*
1175                  *      Got a 802 packet.  Check the other protocol field.
1176                  */
1177                 x = ntohs(et->et_prot);
1178
1179                 ip = (IP_t *)(inpkt + E802_HDR_SIZE);
1180                 len -= E802_HDR_SIZE;
1181
1182         } else if (x != PROT_VLAN) {    /* normal packet */
1183                 ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
1184                 len -= ETHER_HDR_SIZE;
1185
1186         } else {                        /* VLAN packet */
1187                 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
1188
1189 #ifdef ET_DEBUG
1190                 printf("VLAN packet received\n");
1191 #endif
1192                 /* too small packet? */
1193                 if (len < VLAN_ETHER_HDR_SIZE)
1194                         return;
1195
1196                 /* if no VLAN active */
1197                 if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
1198 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1199                                 && iscdp == 0
1200 #endif
1201                                 )
1202                         return;
1203
1204                 cti = ntohs(vet->vet_tag);
1205                 vlanid = cti & VLAN_IDMASK;
1206                 x = ntohs(vet->vet_type);
1207
1208                 ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
1209                 len -= VLAN_ETHER_HDR_SIZE;
1210         }
1211
1212 #ifdef ET_DEBUG
1213         printf("Receive from protocol 0x%x\n", x);
1214 #endif
1215
1216 #if (CONFIG_COMMANDS & CFG_CMD_CDP)
1217         if (iscdp) {
1218                 CDPHandler((uchar *)ip, len);
1219                 return;
1220         }
1221 #endif
1222
1223         if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1224                 if (vlanid == VLAN_NONE)
1225                         vlanid = (mynvlanid & VLAN_IDMASK);
1226                 /* not matched? */
1227                 if (vlanid != (myvlanid & VLAN_IDMASK))
1228                         return;
1229         }
1230
1231         switch (x) {
1232
1233         case PROT_ARP:
1234                 /*
1235                  * We have to deal with two types of ARP packets:
1236                  * - REQUEST packets will be answered by sending  our
1237                  *   IP address - if we know it.
1238                  * - REPLY packates are expected only after we asked
1239                  *   for the TFTP server's or the gateway's ethernet
1240                  *   address; so if we receive such a packet, we set
1241                  *   the server ethernet address
1242                  */
1243 #ifdef ET_DEBUG
1244                 puts ("Got ARP\n");
1245 #endif
1246                 arp = (ARP_t *)ip;
1247                 if (len < ARP_HDR_SIZE) {
1248                         printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1249                         return;
1250                 }
1251                 if (ntohs(arp->ar_hrd) != ARP_ETHER) {
1252                         return;
1253                 }
1254                 if (ntohs(arp->ar_pro) != PROT_IP) {
1255                         return;
1256                 }
1257                 if (arp->ar_hln != 6) {
1258                         return;
1259                 }
1260                 if (arp->ar_pln != 4) {
1261                         return;
1262                 }
1263
1264                 if (NetOurIP == 0) {
1265                         return;
1266                 }
1267
1268                 if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
1269                         return;
1270                 }
1271
1272                 switch (ntohs(arp->ar_op)) {
1273                 case ARPOP_REQUEST:             /* reply with our IP address    */
1274 #ifdef ET_DEBUG
1275                         puts ("Got ARP REQUEST, return our IP\n");
1276 #endif
1277                         pkt = (uchar *)et;
1278                         pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
1279                         arp->ar_op = htons(ARPOP_REPLY);
1280                         memcpy   (&arp->ar_data[10], &arp->ar_data[0], 6);
1281                         NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
1282                         memcpy   (&arp->ar_data[ 0], NetOurEther, 6);
1283                         NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
1284                         (void) eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
1285                         return;
1286
1287                 case ARPOP_REPLY:               /* arp reply */
1288                         /* are we waiting for a reply */
1289                         if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
1290                                 break;
1291 #ifdef ET_DEBUG
1292                         printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
1293                                 arp->ar_data[0], arp->ar_data[1],
1294                                 arp->ar_data[2], arp->ar_data[3],
1295                                 arp->ar_data[4], arp->ar_data[5]);
1296 #endif
1297
1298                         tmp = NetReadIP(&arp->ar_data[6]);
1299
1300                         /* matched waiting packet's address */
1301                         if (tmp == NetArpWaitReplyIP) {
1302 #ifdef ET_DEBUG
1303                                 puts ("Got it\n");
1304 #endif
1305                                 /* save address for later use */
1306                                 memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
1307
1308 #ifdef CONFIG_NETCONSOLE
1309                                 (*packetHandler)(0,0,0,0);
1310 #endif
1311                                 /* modify header, and transmit it */
1312                                 memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
1313                                 (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
1314
1315                                 /* no arp request pending now */
1316                                 NetArpWaitPacketIP = 0;
1317                                 NetArpWaitTxPacketSize = 0;
1318                                 NetArpWaitPacketMAC = NULL;
1319
1320                         }
1321                         return;
1322                 default:
1323 #ifdef ET_DEBUG
1324                         printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
1325 #endif
1326                         return;
1327                 }
1328                 break;
1329
1330         case PROT_RARP:
1331 #ifdef ET_DEBUG
1332                 puts ("Got RARP\n");
1333 #endif
1334                 arp = (ARP_t *)ip;
1335                 if (len < ARP_HDR_SIZE) {
1336                         printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1337                         return;
1338                 }
1339
1340                 if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
1341                         (ntohs(arp->ar_hrd) != ARP_ETHER)   ||
1342                         (ntohs(arp->ar_pro) != PROT_IP)     ||
1343                         (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
1344
1345                         puts ("invalid RARP header\n");
1346                 } else {
1347                         NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
1348                         if (NetServerIP == 0)
1349                                 NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
1350                         memcpy (NetServerEther, &arp->ar_data[ 0], 6);
1351
1352                         (*packetHandler)(0,0,0,0);
1353                 }
1354                 break;
1355
1356         case PROT_IP:
1357 #ifdef ET_DEBUG
1358                 puts ("Got IP\n");
1359 #endif
1360                 if (len < IP_HDR_SIZE) {
1361                         debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
1362                         return;
1363                 }
1364                 if (len < ntohs(ip->ip_len)) {
1365                         printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
1366                         return;
1367                 }
1368                 len = ntohs(ip->ip_len);
1369 #ifdef ET_DEBUG
1370                 printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
1371 #endif
1372                 if ((ip->ip_hl_v & 0xf0) != 0x40) {
1373                         return;
1374                 }
1375                 if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
1376                         return;
1377                 }
1378                 if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
1379                         puts ("checksum bad\n");
1380                         return;
1381                 }
1382                 tmp = NetReadIP(&ip->ip_dst);
1383                 if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
1384                         return;
1385                 }
1386                 /*
1387                  * watch for ICMP host redirects
1388                  *
1389                  * There is no real handler code (yet). We just watch
1390                  * for ICMP host redirect messages. In case anybody
1391                  * sees these messages: please contact me
1392                  * (wd@denx.de), or - even better - send me the
1393                  * necessary fixes :-)
1394                  *
1395                  * Note: in all cases where I have seen this so far
1396                  * it was a problem with the router configuration,
1397                  * for instance when a router was configured in the
1398                  * BOOTP reply, but the TFTP server was on the same
1399                  * subnet. So this is probably a warning that your
1400                  * configuration might be wrong. But I'm not really
1401                  * sure if there aren't any other situations.
1402                  */
1403                 if (ip->ip_p == IPPROTO_ICMP) {
1404                         ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
1405
1406                         switch (icmph->type) {
1407                         case ICMP_REDIRECT:
1408                                 if (icmph->code != ICMP_REDIR_HOST)
1409                                         return;
1410                                 puts (" ICMP Host Redirect to ");
1411                                 print_IPaddr(icmph->un.gateway);
1412                                 putc(' ');
1413                                 return;
1414 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1415                         case ICMP_ECHO_REPLY:
1416                                 /*
1417                                  *      IP header OK.  Pass the packet to the current handler.
1418                                  */
1419                                 /* XXX point to ip packet */
1420                                 (*packetHandler)((uchar *)ip, 0, 0, 0);
1421                                 return;
1422 #endif
1423                         default:
1424                                 return;
1425                         }
1426                 } else if (ip->ip_p != IPPROTO_UDP) {   /* Only UDP packets */
1427                         return;
1428                 }
1429
1430 #ifdef CONFIG_UDP_CHECKSUM
1431                 if (ip->udp_xsum != 0) {
1432                         ulong   xsum;
1433                         ushort *sumptr;
1434                         ushort  sumlen;
1435
1436                         xsum  = ip->ip_p;
1437                         xsum += (ntohs(ip->udp_len));
1438                         xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1439                         xsum += (ntohl(ip->ip_src) >>  0) & 0x0000ffff;
1440                         xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1441                         xsum += (ntohl(ip->ip_dst) >>  0) & 0x0000ffff;
1442
1443                         sumlen = ntohs(ip->udp_len);
1444                         sumptr = (ushort *) &(ip->udp_src);
1445
1446                         while (sumlen > 1) {
1447                                 ushort sumdata;
1448
1449                                 sumdata = *sumptr++;
1450                                 xsum += ntohs(sumdata);
1451                                 sumlen -= 2;
1452                         }
1453                         if (sumlen > 0) {
1454                                 ushort sumdata;
1455
1456                                 sumdata = *(unsigned char *) sumptr;
1457                                 sumdata = (sumdata << 8) & 0xff00;
1458                                 xsum += sumdata;
1459                         }
1460                         while ((xsum >> 16) != 0) {
1461                                 xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
1462                         }
1463                         if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1464                                 printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
1465                                 return;
1466                         }
1467                 }
1468 #endif
1469
1470 #ifdef CONFIG_NETCONSOLE
1471                 nc_input_packet((uchar *)ip +IP_HDR_SIZE,
1472                                                 ntohs(ip->udp_dst),
1473                                                 ntohs(ip->udp_src),
1474                                                 ntohs(ip->udp_len) - 8);
1475 #endif
1476                 /*
1477                  *      IP header OK.  Pass the packet to the current handler.
1478                  */
1479                 (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
1480                                                 ntohs(ip->udp_dst),
1481                                                 ntohs(ip->udp_src),
1482                                                 ntohs(ip->udp_len) - 8);
1483                 break;
1484         }
1485 }
1486
1487
1488 /**********************************************************************/
1489
1490 static int net_check_prereq (proto_t protocol)
1491 {
1492         switch (protocol) {
1493                 /* Fall through */
1494 #if (CONFIG_COMMANDS & CFG_CMD_PING)
1495         case PING:
1496                 if (NetPingIP == 0) {
1497                         puts ("*** ERROR: ping address not given\n");
1498                         return (1);
1499                 }
1500                 goto common;
1501 #endif
1502 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
1503         case SNTP:
1504                 if (NetNtpServerIP == 0) {
1505                         puts ("*** ERROR: NTP server address not given\n");
1506                         return (1);
1507                 }
1508                 goto common;
1509 #endif
1510 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
1511         case NFS:
1512 #endif
1513         case NETCONS:
1514         case TFTP:
1515                 if (NetServerIP == 0) {
1516                         puts ("*** ERROR: `serverip' not set\n");
1517                         return (1);
1518                 }
1519 #if (CONFIG_COMMANDS & (CFG_CMD_PING | CFG_CMD_SNTP))
1520     common:
1521 #endif
1522
1523                 if (NetOurIP == 0) {
1524                         puts ("*** ERROR: `ipaddr' not set\n");
1525                         return (1);
1526                 }
1527                 /* Fall through */
1528
1529         case DHCP:
1530         case RARP:
1531         case BOOTP:
1532         case CDP:
1533                 if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
1534 #ifdef CONFIG_NET_MULTI
1535                         extern int eth_get_dev_index (void);
1536                         int num = eth_get_dev_index ();
1537
1538                         switch (num) {
1539                         case -1:
1540                                 puts ("*** ERROR: No ethernet found.\n");
1541                                 return (1);
1542                         case 0:
1543                                 puts ("*** ERROR: `ethaddr' not set\n");
1544                                 break;
1545                         default:
1546                                 printf ("*** ERROR: `eth%daddr' not set\n",
1547                                         num);
1548                                 break;
1549                         }
1550
1551                         NetStartAgain ();
1552                         return (2);
1553 #else
1554                         puts ("*** ERROR: `ethaddr' not set\n");
1555                         return (1);
1556 #endif
1557                 }
1558                 /* Fall through */
1559         default:
1560                 return (0);
1561         }
1562         return (0);             /* OK */
1563 }
1564 /**********************************************************************/
1565
1566 int
1567 NetCksumOk(uchar * ptr, int len)
1568 {
1569         return !((NetCksum(ptr, len) + 1) & 0xfffe);
1570 }
1571
1572
1573 unsigned
1574 NetCksum(uchar * ptr, int len)
1575 {
1576         ulong   xsum;
1577         ushort *p = ptr;
1578
1579         xsum = 0;
1580         while (len-- > 0)
1581                 xsum += *p++;
1582         xsum = (xsum & 0xffff) + (xsum >> 16);
1583         xsum = (xsum & 0xffff) + (xsum >> 16);
1584         return (xsum & 0xffff);
1585 }
1586
1587 int
1588 NetEthHdrSize(void)
1589 {
1590         ushort myvlanid;
1591
1592         myvlanid = ntohs(NetOurVLAN);
1593         if (myvlanid == (ushort)-1)
1594                 myvlanid = VLAN_NONE;
1595
1596         return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
1597 }
1598
1599 int
1600 NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
1601 {
1602         Ethernet_t *et = (Ethernet_t *)xet;
1603         ushort myvlanid;
1604
1605         myvlanid = ntohs(NetOurVLAN);
1606         if (myvlanid == (ushort)-1)
1607                 myvlanid = VLAN_NONE;
1608
1609         memcpy (et->et_dest, addr, 6);
1610         memcpy (et->et_src, NetOurEther, 6);
1611         if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1612         et->et_protlen = htons(prot);
1613                 return ETHER_HDR_SIZE;
1614         } else {
1615                 VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1616
1617                 vet->vet_vlan_type = htons(PROT_VLAN);
1618                 vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1619                 vet->vet_type = htons(prot);
1620                 return VLAN_ETHER_HDR_SIZE;
1621         }
1622 }
1623
1624 void
1625 NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
1626 {
1627         volatile IP_t *ip = (IP_t *)xip;
1628
1629         /*
1630          *      If the data is an odd number of bytes, zero the
1631          *      byte after the last byte so that the checksum
1632          *      will work.
1633          */
1634         if (len & 1)
1635                 xip[IP_HDR_SIZE + len] = 0;
1636
1637         /*
1638          *      Construct an IP and UDP header.
1639          *      (need to set no fragment bit - XXX)
1640          */
1641         ip->ip_hl_v  = 0x45;            /* IP_HDR_SIZE / 4 (not including UDP) */
1642         ip->ip_tos   = 0;
1643         ip->ip_len   = htons(IP_HDR_SIZE + len);
1644         ip->ip_id    = htons(NetIPID++);
1645         ip->ip_off   = htons(0x4000);   /* No fragmentation */
1646         ip->ip_ttl   = 255;
1647         ip->ip_p     = 17;              /* UDP */
1648         ip->ip_sum   = 0;
1649         NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1650         NetCopyIP((void*)&ip->ip_dst, &dest);      /* - "" - */
1651         ip->udp_src  = htons(sport);
1652         ip->udp_dst  = htons(dport);
1653         ip->udp_len  = htons(8 + len);
1654         ip->udp_xsum = 0;
1655         ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1656 }
1657
1658 void copy_filename (uchar *dst, uchar *src, int size)
1659 {
1660         if (*src && (*src == '"')) {
1661                 ++src;
1662                 --size;
1663         }
1664
1665         while ((--size > 0) && *src && (*src != '"')) {
1666                 *dst++ = *src++;
1667         }
1668         *dst = '\0';
1669 }
1670
1671 #endif /* CFG_CMD_NET */
1672
1673 void ip_to_string (IPaddr_t x, char *s)
1674 {
1675         x = ntohl (x);
1676         sprintf (s, "%d.%d.%d.%d",
1677                  (int) ((x >> 24) & 0xff),
1678                  (int) ((x >> 16) & 0xff),
1679                  (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
1680         );
1681 }
1682
1683 IPaddr_t string_to_ip(char *s)
1684 {
1685         IPaddr_t addr;
1686         char *e;
1687         int i;
1688
1689         if (s == NULL)
1690                 return(0);
1691
1692         for (addr=0, i=0; i<4; ++i) {
1693                 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1694                 addr <<= 8;
1695                 addr |= (val & 0xFF);
1696                 if (s) {
1697                         s = (*e) ? e+1 : e;
1698                 }
1699         }
1700
1701         return (htonl(addr));
1702 }
1703
1704 void VLAN_to_string(ushort x, char *s)
1705 {
1706         x = ntohs(x);
1707
1708         if (x == (ushort)-1)
1709                 x = VLAN_NONE;
1710
1711         if (x == VLAN_NONE)
1712                 strcpy(s, "none");
1713         else
1714                 sprintf(s, "%d", x & VLAN_IDMASK);
1715 }
1716
1717 ushort string_to_VLAN(char *s)
1718 {
1719         ushort id;
1720
1721         if (s == NULL)
1722                 return htons(VLAN_NONE);
1723
1724         if (*s < '0' || *s > '9')
1725                 id = VLAN_NONE;
1726         else
1727                 id = (ushort)simple_strtoul(s, NULL, 10);
1728
1729         return htons(id);
1730 }
1731
1732 void print_IPaddr (IPaddr_t x)
1733 {
1734         char tmp[16];
1735
1736         ip_to_string (x, tmp);
1737
1738         puts (tmp);
1739 }
1740
1741 IPaddr_t getenv_IPaddr (char *var)
1742 {
1743         return (string_to_ip(getenv(var)));
1744 }
1745
1746 ushort getenv_VLAN(char *var)
1747 {
1748         return (string_to_VLAN(getenv(var)));
1749 }