uboot/net/net.c
<<
>>
Prefs
   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#ifdef CONFIG_CMD_RARP
  84#include "rarp.h"
  85#endif
  86#include "nfs.h"
  87#ifdef CONFIG_STATUS_LED
  88#include <status_led.h>
  89#include <miiphy.h>
  90#endif
  91#if defined(CONFIG_CMD_SNTP)
  92#include "sntp.h"
  93#endif
  94#if defined(CONFIG_CDP_VERSION)
  95#include <timestamp.h>
  96#endif
  97#if defined(CONFIG_CMD_DNS)
  98#include "dns.h"
  99#endif
 100
 101DECLARE_GLOBAL_DATA_PTR;
 102
 103#ifndef CONFIG_ARP_TIMEOUT
 104# define ARP_TIMEOUT            5000UL  /* Milliseconds before trying ARP again */
 105#else
 106# define ARP_TIMEOUT            CONFIG_ARP_TIMEOUT
 107#endif
 108
 109
 110#ifndef CONFIG_NET_RETRY_COUNT
 111# define ARP_TIMEOUT_COUNT      5       /* # of timeouts before giving up  */
 112#else
 113# define ARP_TIMEOUT_COUNT      CONFIG_NET_RETRY_COUNT
 114#endif
 115
 116/** BOOTP EXTENTIONS **/
 117
 118IPaddr_t        NetOurSubnetMask=0;             /* Our subnet mask (0=unknown)  */
 119IPaddr_t        NetOurGatewayIP=0;              /* Our gateways IP address      */
 120IPaddr_t        NetOurDNSIP=0;                  /* Our DNS IP address           */
 121#if defined(CONFIG_BOOTP_DNS2)
 122IPaddr_t        NetOurDNS2IP=0;                 /* Our 2nd DNS IP address       */
 123#endif
 124char            NetOurNISDomain[32]={0,};       /* Our NIS domain               */
 125char            NetOurHostName[32]={0,};        /* Our hostname                 */
 126char            NetOurRootPath[64]={0,};        /* Our bootpath                 */
 127ushort          NetBootFileSize=0;              /* Our bootfile size in blocks  */
 128
 129#ifdef CONFIG_MCAST_TFTP        /* Multicast TFTP */
 130IPaddr_t Mcast_addr;
 131#endif
 132
 133/** END OF BOOTP EXTENTIONS **/
 134
 135ulong           NetBootFileXferSize;    /* The actual transferred size of the bootfile (in bytes) */
 136uchar           NetOurEther[6];         /* Our ethernet address                 */
 137uchar           NetServerEther[6] =     /* Boot server enet address             */
 138                        { 0, 0, 0, 0, 0, 0 };
 139IPaddr_t        NetOurIP;               /* Our IP addr (0 = unknown)            */
 140IPaddr_t        NetServerIP;            /* Server IP addr (0 = unknown)         */
 141volatile uchar *NetRxPacket;            /* Current receive packet               */
 142int             NetRxPacketLen;         /* Current rx packet length             */
 143unsigned        NetIPID;                /* IP packet ID                         */
 144uchar           NetBcastAddr[6] =       /* Ethernet bcast address               */
 145                        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 146uchar           NetEtherNullAddr[6] =
 147                        { 0, 0, 0, 0, 0, 0 };
 148#ifdef CONFIG_API
 149void            (*push_packet)(volatile void *, int len) = 0;
 150#endif
 151#if defined(CONFIG_CMD_CDP)
 152uchar           NetCDPAddr[6] =         /* Ethernet bcast address               */
 153                        { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };
 154#endif
 155int             NetState;               /* Network loop state                   */
 156#ifdef CONFIG_NET_MULTI
 157int             NetRestartWrap = 0;     /* Tried all network devices            */
 158static int      NetRestarted = 0;       /* Network loop restarted               */
 159static int      NetDevExists = 0;       /* At least one device configured       */
 160#endif
 161
 162/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
 163ushort          NetOurVLAN = 0xFFFF;            /* default is without VLAN      */
 164ushort          NetOurNativeVLAN = 0xFFFF;      /* ditto                        */
 165
 166char            BootFile[128];          /* Boot File name                       */
 167
 168#if defined(CONFIG_CMD_PING)
 169IPaddr_t        NetPingIP;              /* the ip address to ping               */
 170
 171static void PingStart(void);
 172#endif
 173
 174#if defined(CONFIG_CMD_CDP)
 175static void CDPStart(void);
 176#endif
 177
 178#if defined(CONFIG_CMD_SNTP)
 179IPaddr_t        NetNtpServerIP;         /* NTP server IP address                */
 180int             NetTimeOffset=0;        /* offset time from UTC                 */
 181#endif
 182
 183#ifdef CONFIG_NETCONSOLE
 184void NcStart(void);
 185int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
 186#endif
 187
 188volatile uchar  PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
 189
 190volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets                     */
 191
 192static rxhand_f *packetHandler;         /* Current RX packet handler            */
 193static thand_f *timeHandler;            /* Current timeout handler              */
 194static ulong    timeStart;              /* Time base value                      */
 195static ulong    timeDelta;              /* Current timeout value                */
 196volatile uchar *NetTxPacket = 0;        /* THE transmit packet                  */
 197
 198static int net_check_prereq (proto_t protocol);
 199
 200static int NetTryCount;
 201
 202/**********************************************************************/
 203
 204IPaddr_t        NetArpWaitPacketIP;
 205IPaddr_t        NetArpWaitReplyIP;
 206uchar          *NetArpWaitPacketMAC;    /* MAC address of waiting packet's destination  */
 207uchar          *NetArpWaitTxPacket;     /* THE transmit packet                  */
 208int             NetArpWaitTxPacketSize;
 209uchar           NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
 210ulong           NetArpWaitTimerStart;
 211int             NetArpWaitTry;
 212
 213void ArpRequest (void)
 214{
 215        int i;
 216        volatile uchar *pkt;
 217        ARP_t *arp;
 218
 219        debug("ARP broadcast %d\n", NetArpWaitTry);
 220
 221        pkt = NetTxPacket;
 222
 223        pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP);
 224
 225        arp = (ARP_t *) pkt;
 226
 227        arp->ar_hrd = htons (ARP_ETHER);
 228        arp->ar_pro = htons (PROT_IP);
 229        arp->ar_hln = 6;
 230        arp->ar_pln = 4;
 231        arp->ar_op = htons (ARPOP_REQUEST);
 232
 233        memcpy (&arp->ar_data[0], NetOurEther, 6);              /* source ET addr       */
 234        NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP);     /* source IP addr       */
 235        for (i = 10; i < 16; ++i) {
 236                arp->ar_data[i] = 0;                            /* dest ET addr = 0     */
 237        }
 238
 239        if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
 240            (NetOurIP & NetOurSubnetMask)) {
 241                if (NetOurGatewayIP == 0) {
 242                        puts ("## Warning: gatewayip needed but not set\n");
 243                        NetArpWaitReplyIP = NetArpWaitPacketIP;
 244                } else {
 245                        NetArpWaitReplyIP = NetOurGatewayIP;
 246                }
 247        } else {
 248                NetArpWaitReplyIP = NetArpWaitPacketIP;
 249        }
 250
 251        NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP);
 252        (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
 253}
 254
 255void ArpTimeoutCheck(void)
 256{
 257        ulong t;
 258
 259        if (!NetArpWaitPacketIP)
 260                return;
 261
 262        t = get_timer(0);
 263
 264        /* check for arp timeout */
 265        if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
 266                NetArpWaitTry++;
 267
 268                if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
 269                        puts ("\nARP Retry count exceeded; starting again\n");
 270                        NetArpWaitTry = 0;
 271                        NetStartAgain();
 272                } else {
 273                        NetArpWaitTimerStart = t;
 274                        ArpRequest();
 275                }
 276        }
 277}
 278
 279static void
 280NetInitLoop(proto_t protocol)
 281{
 282        static int env_changed_id = 0;
 283        bd_t *bd = gd->bd;
 284        int env_id = get_env_id ();
 285
 286        /* update only when the environment has changed */
 287        if (env_changed_id != env_id) {
 288                NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
 289                NetOurGatewayIP = getenv_IPaddr ("gatewayip");
 290                NetOurSubnetMask= getenv_IPaddr ("netmask");
 291                NetServerIP = getenv_IPaddr ("serverip");
 292                NetOurNativeVLAN = getenv_VLAN("nvlan");
 293                NetOurVLAN = getenv_VLAN("vlan");
 294#if defined(CONFIG_CMD_DNS)
 295                NetOurDNSIP = getenv_IPaddr("dnsip");
 296#endif
 297                env_changed_id = env_id;
 298        }
 299
 300        return;
 301}
 302
 303/**********************************************************************/
 304/*
 305 *      Main network processing loop.
 306 */
 307
 308int
 309NetLoop(proto_t protocol)
 310{
 311        bd_t *bd = gd->bd;
 312
 313#ifdef CONFIG_NET_MULTI
 314        NetRestarted = 0;
 315        NetDevExists = 0;
 316#endif
 317
 318        /* XXX problem with bss workaround */
 319        NetArpWaitPacketMAC = NULL;
 320        NetArpWaitTxPacket = NULL;
 321        NetArpWaitPacketIP = 0;
 322        NetArpWaitReplyIP = 0;
 323        NetArpWaitTxPacket = NULL;
 324        NetTxPacket = NULL;
 325        NetTryCount = 1;
 326
 327        if (!NetTxPacket) {
 328                int     i;
 329                /*
 330                 *      Setup packet buffers, aligned correctly.
 331                 */
 332                NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
 333                NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
 334                for (i = 0; i < PKTBUFSRX; i++) {
 335                        NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
 336                }
 337        }
 338
 339        if (!NetArpWaitTxPacket) {
 340                NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
 341                NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
 342                NetArpWaitTxPacketSize = 0;
 343        }
 344
 345        eth_halt();
 346#ifdef CONFIG_NET_MULTI
 347        eth_set_current();
 348#endif
 349        if (eth_init(bd) < 0) {
 350                eth_halt();
 351                return(-1);
 352        }
 353
 354restart:
 355#ifdef CONFIG_NET_MULTI
 356        memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
 357#else
 358        eth_getenv_enetaddr("ethaddr", NetOurEther);
 359#endif
 360
 361        NetState = NETLOOP_CONTINUE;
 362
 363        /*
 364         *      Start the ball rolling with the given start function.  From
 365         *      here on, this code is a state machine driven by received
 366         *      packets and timer events.
 367         */
 368        NetInitLoop(protocol);
 369
 370        switch (net_check_prereq (protocol)) {
 371        case 1:
 372                /* network not configured */
 373                eth_halt();
 374                return (-1);
 375
 376#ifdef CONFIG_NET_MULTI
 377        case 2:
 378                /* network device not configured */
 379                break;
 380#endif /* CONFIG_NET_MULTI */
 381
 382        case 0:
 383#ifdef CONFIG_NET_MULTI
 384                NetDevExists = 1;
 385#endif
 386                switch (protocol) {
 387                case TFTP:
 388                        /* always use ARP to get server ethernet address */
 389                        TftpStart();
 390                        break;
 391
 392#if defined(CONFIG_CMD_DHCP)
 393                case DHCP:
 394                        BootpTry = 0;
 395                        NetOurIP = 0;
 396                        DhcpRequest();          /* Basically same as BOOTP */
 397                        break;
 398#endif
 399
 400                case BOOTP:
 401                        BootpTry = 0;
 402                        NetOurIP = 0;
 403                        BootpRequest ();
 404                        break;
 405
 406#if defined(CONFIG_CMD_RARP)
 407                case RARP:
 408                        RarpTry = 0;
 409                        NetOurIP = 0;
 410                        RarpRequest ();
 411                        break;
 412#endif
 413#if defined(CONFIG_CMD_PING)
 414                case PING:
 415                        PingStart();
 416                        break;
 417#endif
 418#if defined(CONFIG_CMD_NFS)
 419                case NFS:
 420                        NfsStart();
 421                        break;
 422#endif
 423#if defined(CONFIG_CMD_CDP)
 424                case CDP:
 425                        CDPStart();
 426                        break;
 427#endif
 428#ifdef CONFIG_NETCONSOLE
 429                case NETCONS:
 430                        NcStart();
 431                        break;
 432#endif
 433#if defined(CONFIG_CMD_SNTP)
 434                case SNTP:
 435                        SntpStart();
 436                        break;
 437#endif
 438#if defined(CONFIG_CMD_DNS)
 439                case DNS:
 440                        DnsStart();
 441                        break;
 442#endif
 443                default:
 444                        break;
 445                }
 446
 447                NetBootFileXferSize = 0;
 448                break;
 449        }
 450
 451#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 452#if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
 453        /*
 454         * Echo the inverted link state to the fault LED.
 455         */
 456        if(miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) {
 457                status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
 458        } else {
 459                status_led_set (STATUS_LED_RED, STATUS_LED_ON);
 460        }
 461#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
 462#endif /* CONFIG_MII, ... */
 463
 464        /*
 465         *      Main packet reception loop.  Loop receiving packets until
 466         *      someone sets `NetState' to a state that terminates.
 467         */
 468        for (;;) {
 469                WATCHDOG_RESET();
 470#ifdef CONFIG_SHOW_ACTIVITY
 471                {
 472                        extern void show_activity(int arg);
 473                        show_activity(1);
 474                }
 475#endif
 476                /*
 477                 *      Check the ethernet for a new packet.  The ethernet
 478                 *      receive routine will process it.
 479                 */
 480                eth_rx();
 481
 482                /*
 483                 *      Abort if ctrl-c was pressed.
 484                 */
 485                if (ctrlc()) {
 486                        eth_halt();
 487                        puts ("\nAbort\n");
 488                        return (-1);
 489                }
 490
 491                ArpTimeoutCheck();
 492
 493                /*
 494                 *      Check for a timeout, and run the timeout handler
 495                 *      if we have one.
 496                 */
 497                if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
 498                        thand_f *x;
 499
 500#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 501#  if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \
 502      defined(CONFIG_STATUS_LED) &&        \
 503      defined(STATUS_LED_RED)
 504                        /*
 505                         * Echo the inverted link state to the fault LED.
 506                         */
 507                        if(miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) {
 508                                status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
 509                        } else {
 510                                status_led_set (STATUS_LED_RED, STATUS_LED_ON);
 511                        }
 512#  endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
 513#endif /* CONFIG_MII, ... */
 514                        x = timeHandler;
 515                        timeHandler = (thand_f *)0;
 516                        (*x)();
 517                }
 518
 519
 520                switch (NetState) {
 521
 522                case NETLOOP_RESTART:
 523#ifdef CONFIG_NET_MULTI
 524                        NetRestarted = 1;
 525#endif
 526                        goto restart;
 527
 528                case NETLOOP_SUCCESS:
 529                        if (NetBootFileXferSize > 0) {
 530                                char buf[20];
 531                                printf("Bytes transferred = %ld (%lx hex)\n",
 532                                        NetBootFileXferSize,
 533                                        NetBootFileXferSize);
 534                                sprintf(buf, "%lX", NetBootFileXferSize);
 535                                setenv("filesize", buf);
 536
 537                                sprintf(buf, "%lX", (unsigned long)load_addr);
 538                                setenv("fileaddr", buf);
 539                        }
 540                        eth_halt();
 541                        return NetBootFileXferSize;
 542
 543                case NETLOOP_FAIL:
 544                        return (-1);
 545                }
 546        }
 547}
 548
 549/**********************************************************************/
 550
 551static void
 552startAgainTimeout(void)
 553{
 554        NetState = NETLOOP_RESTART;
 555}
 556
 557static void
 558startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
 559{
 560        /* Totally ignore the packet */
 561}
 562
 563void NetStartAgain (void)
 564{
 565        char *nretry;
 566        int retry_forever = 0;
 567        unsigned long retrycnt = 0;
 568
 569        nretry = getenv("netretry");
 570        if (nretry) {
 571                if (!strcmp(nretry, "yes"))
 572                        retry_forever = 1;
 573                else if (!strcmp(nretry, "no"))
 574                        retrycnt = 0;
 575                else if (!strcmp(nretry, "once"))
 576                        retrycnt = 1;
 577                else
 578                        retrycnt = simple_strtoul(nretry, NULL, 0);
 579        } else
 580                retry_forever = 1;
 581
 582        if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 583                eth_halt();
 584                NetState = NETLOOP_FAIL;
 585                return;
 586        }
 587
 588        NetTryCount++;
 589
 590#ifndef CONFIG_NET_MULTI
 591        NetSetTimeout (10000UL, startAgainTimeout);
 592        NetSetHandler (startAgainHandler);
 593#else   /* !CONFIG_NET_MULTI*/
 594        eth_halt ();
 595#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 596        eth_try_another (!NetRestarted);
 597#endif
 598        eth_init (gd->bd);
 599        if (NetRestartWrap) {
 600                NetRestartWrap = 0;
 601                if (NetDevExists) {
 602                        NetSetTimeout (10000UL, startAgainTimeout);
 603                        NetSetHandler (startAgainHandler);
 604                } else {
 605                        NetState = NETLOOP_FAIL;
 606                }
 607        } else {
 608                NetState = NETLOOP_RESTART;
 609        }
 610#endif  /* CONFIG_NET_MULTI */
 611}
 612
 613/**********************************************************************/
 614/*
 615 *      Miscelaneous bits.
 616 */
 617
 618void
 619NetSetHandler(rxhand_f * f)
 620{
 621        packetHandler = f;
 622}
 623
 624
 625void
 626NetSetTimeout(ulong iv, thand_f * f)
 627{
 628        if (iv == 0) {
 629                timeHandler = (thand_f *)0;
 630        } else {
 631                timeHandler = f;
 632                timeStart = get_timer(0);
 633                timeDelta = iv;
 634        }
 635}
 636
 637
 638void
 639NetSendPacket(volatile uchar * pkt, int len)
 640{
 641        (void) eth_send(pkt, len);
 642}
 643
 644int
 645NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
 646{
 647        uchar *pkt;
 648
 649        /* convert to new style broadcast */
 650        if (dest == 0)
 651                dest = 0xFFFFFFFF;
 652
 653        /* if broadcast, make the ether address a broadcast and don't do ARP */
 654        if (dest == 0xFFFFFFFF)
 655                ether = NetBcastAddr;
 656
 657        /* if MAC address was not discovered yet, save the packet and do an ARP request */
 658        if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
 659
 660                debug("sending ARP for %08lx\n", dest);
 661
 662                NetArpWaitPacketIP = dest;
 663                NetArpWaitPacketMAC = ether;
 664
 665                pkt = NetArpWaitTxPacket;
 666                pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);
 667
 668                NetSetIP (pkt, dest, dport, sport, len);
 669                memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
 670
 671                /* size of the waiting packet */
 672                NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
 673
 674                /* and do the ARP request */
 675                NetArpWaitTry = 1;
 676                NetArpWaitTimerStart = get_timer(0);
 677                ArpRequest();
 678                return 1;       /* waiting */
 679        }
 680
 681        debug("sending UDP to %08lx/%pM\n", dest, ether);
 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 defined(CONFIG_CMD_PING)
 692static ushort PingSeqNo;
 693
 694int 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        debug("sending ARP for %08lx\n", NetPingIP);
 706
 707        NetArpWaitPacketIP = NetPingIP;
 708        NetArpWaitPacketMAC = mac;
 709
 710        pkt = NetArpWaitTxPacket;
 711        pkt += NetSetEther(pkt, mac, PROT_IP);
 712
 713        ip = (volatile IP_t *)pkt;
 714
 715        /*
 716         *      Construct an IP and ICMP header.  (need to set no fragment bit - XXX)
 717         */
 718        ip->ip_hl_v  = 0x45;            /* IP_HDR_SIZE / 4 (not including UDP) */
 719        ip->ip_tos   = 0;
 720        ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8);
 721        ip->ip_id    = htons(NetIPID++);
 722        ip->ip_off   = htons(IP_FLAGS_DFRAG);   /* Don't fragment */
 723        ip->ip_ttl   = 255;
 724        ip->ip_p     = 0x01;            /* ICMP */
 725        ip->ip_sum   = 0;
 726        NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
 727        NetCopyIP((void*)&ip->ip_dst, &NetPingIP);         /* - "" - */
 728        ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
 729
 730        s = &ip->udp_src;               /* XXX ICMP starts here */
 731        s[0] = htons(0x0800);           /* echo-request, code */
 732        s[1] = 0;                       /* checksum */
 733        s[2] = 0;                       /* identifier */
 734        s[3] = htons(PingSeqNo++);      /* sequence number */
 735        s[1] = ~NetCksum((uchar *)s, 8/2);
 736
 737        /* size of the waiting packet */
 738        NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
 739
 740        /* and do the ARP request */
 741        NetArpWaitTry = 1;
 742        NetArpWaitTimerStart = get_timer(0);
 743        ArpRequest();
 744        return 1;       /* waiting */
 745}
 746
 747static void
 748PingTimeout (void)
 749{
 750        eth_halt();
 751        NetState = NETLOOP_FAIL;        /* we did not get the reply */
 752}
 753
 754static void
 755PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
 756{
 757        IPaddr_t tmp;
 758        volatile IP_t *ip = (volatile IP_t *)pkt;
 759
 760        tmp = NetReadIP((void *)&ip->ip_src);
 761        if (tmp != NetPingIP)
 762                return;
 763
 764        NetState = NETLOOP_SUCCESS;
 765}
 766
 767static void PingStart(void)
 768{
 769#if defined(CONFIG_NET_MULTI)
 770        printf ("Using %s device\n", eth_get_name());
 771#endif  /* CONFIG_NET_MULTI */
 772        NetSetTimeout (10000UL, PingTimeout);
 773        NetSetHandler (PingHandler);
 774
 775        PingSend();
 776}
 777#endif
 778
 779#if defined(CONFIG_CMD_CDP)
 780
 781#define CDP_DEVICE_ID_TLV               0x0001
 782#define CDP_ADDRESS_TLV                 0x0002
 783#define CDP_PORT_ID_TLV                 0x0003
 784#define CDP_CAPABILITIES_TLV            0x0004
 785#define CDP_VERSION_TLV                 0x0005
 786#define CDP_PLATFORM_TLV                0x0006
 787#define CDP_NATIVE_VLAN_TLV             0x000a
 788#define CDP_APPLIANCE_VLAN_TLV          0x000e
 789#define CDP_TRIGGER_TLV                 0x000f
 790#define CDP_POWER_CONSUMPTION_TLV       0x0010
 791#define CDP_SYSNAME_TLV                 0x0014
 792#define CDP_SYSOBJECT_TLV               0x0015
 793#define CDP_MANAGEMENT_ADDRESS_TLV      0x0016
 794
 795#define CDP_TIMEOUT                     250UL   /* one packet every 250ms */
 796
 797static int CDPSeq;
 798static int CDPOK;
 799
 800ushort CDPNativeVLAN;
 801ushort CDPApplianceVLAN;
 802
 803static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 };
 804
 805static ushort CDP_compute_csum(const uchar *buff, ushort len)
 806{
 807        ushort csum;
 808        int     odd;
 809        ulong   result = 0;
 810        ushort  leftover;
 811        ushort *p;
 812
 813        if (len > 0) {
 814                odd = 1 & (ulong)buff;
 815                if (odd) {
 816                        result = *buff << 8;
 817                        len--;
 818                        buff++;
 819                }
 820                while (len > 1) {
 821                        p = (ushort *)buff;
 822                        result += *p++;
 823                        buff = (uchar *)p;
 824                        if (result & 0x80000000)
 825                                result = (result & 0xFFFF) + (result >> 16);
 826                        len -= 2;
 827                }
 828                if (len) {
 829                        leftover = (signed short)(*(const signed char *)buff);
 830                        /* CISCO SUCKS big time! (and blows too):
 831                         * CDP uses the IP checksum algorithm with a twist;
 832                         * for the last byte it *sign* extends and sums.
 833                         */
 834                        result = (result & 0xffff0000) | ((result + leftover) & 0x0000ffff);
 835                }
 836                while (result >> 16)
 837                        result = (result & 0xFFFF) + (result >> 16);
 838
 839                if (odd)
 840                        result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
 841        }
 842
 843        /* add up 16-bit and 17-bit words for 17+c bits */
 844        result = (result & 0xffff) + (result >> 16);
 845        /* add up 16-bit and 2-bit for 16+c bit */
 846        result = (result & 0xffff) + (result >> 16);
 847        /* add up carry.. */
 848        result = (result & 0xffff) + (result >> 16);
 849
 850        /* negate */
 851        csum = ~(ushort)result;
 852
 853        /* run time endian detection */
 854        if (csum != htons(csum))        /* little endian */
 855                csum = htons(csum);
 856
 857        return csum;
 858}
 859
 860int CDPSendTrigger(void)
 861{
 862        volatile uchar *pkt;
 863        volatile ushort *s;
 864        volatile ushort *cp;
 865        Ethernet_t *et;
 866        int len;
 867        ushort chksum;
 868#if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID)   || \
 869    defined(CONFIG_CDP_VERSION)   || defined(CONFIG_CDP_PLATFORM)
 870        char buf[32];
 871#endif
 872
 873        pkt = NetTxPacket;
 874        et = (Ethernet_t *)pkt;
 875
 876        /* NOTE: trigger sent not on any VLAN */
 877
 878        /* form ethernet header */
 879        memcpy(et->et_dest, NetCDPAddr, 6);
 880        memcpy(et->et_src, NetOurEther, 6);
 881
 882        pkt += ETHER_HDR_SIZE;
 883
 884        /* SNAP header */
 885        memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr));
 886        pkt += sizeof(CDP_SNAP_hdr);
 887
 888        /* CDP header */
 889        *pkt++ = 0x02;                          /* CDP version 2 */
 890        *pkt++ = 180;                           /* TTL */
 891        s = (volatile ushort *)pkt;
 892        cp = s;
 893        *s++ = htons(0);                        /* checksum (0 for later calculation) */
 894
 895        /* CDP fields */
 896#ifdef CONFIG_CDP_DEVICE_ID
 897        *s++ = htons(CDP_DEVICE_ID_TLV);
 898        *s++ = htons(CONFIG_CDP_DEVICE_ID);
 899        sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%pm", NetOurEther);
 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
 974static void
 975CDPTimeout (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
 992static void
 993CDPDummyHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
 994{
 995        /* nothing */
 996}
 997
 998static void
 999CDPHandler(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
1110static 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
1127
1128#ifdef CONFIG_IP_DEFRAG
1129/*
1130 * This function collects fragments in a single packet, according
1131 * to the algorithm in RFC815. It returns NULL or the pointer to
1132 * a complete packet, in static storage
1133 */
1134#ifndef CONFIG_NET_MAXDEFRAG
1135#define CONFIG_NET_MAXDEFRAG 16384
1136#endif
1137/*
1138 * MAXDEFRAG, above, is chosen in the config file and  is real data
1139 * so we need to add the NFS overhead, which is more than TFTP.
1140 * To use sizeof in the internal unnamed structures, we need a real
1141 * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately).
1142 * The compiler doesn't complain nor allocates the actual structure
1143 */
1144static struct rpc_t rpc_specimen;
1145#define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply))
1146
1147#define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE_NO_UDP)
1148
1149/*
1150 * this is the packet being assembled, either data or frag control.
1151 * Fragments go by 8 bytes, so this union must be 8 bytes long
1152 */
1153struct hole {
1154        /* first_byte is address of this structure */
1155        u16 last_byte;  /* last byte in this hole + 1 (begin of next hole) */
1156        u16 next_hole;  /* index of next (in 8-b blocks), 0 == none */
1157        u16 prev_hole;  /* index of prev, 0 == none */
1158        u16 unused;
1159};
1160
1161static IP_t *__NetDefragment(IP_t *ip, int *lenp)
1162{
1163        static uchar pkt_buff[IP_PKTSIZE] __attribute__((aligned(PKTALIGN)));
1164        static u16 first_hole, total_len;
1165        struct hole *payload, *thisfrag, *h, *newh;
1166        IP_t *localip = (IP_t *)pkt_buff;
1167        uchar *indata = (uchar *)ip;
1168        int offset8, start, len, done = 0;
1169        u16 ip_off = ntohs(ip->ip_off);
1170
1171        /* payload starts after IP header, this fragment is in there */
1172        payload = (struct hole *)(pkt_buff + IP_HDR_SIZE_NO_UDP);
1173        offset8 =  (ip_off & IP_OFFS);
1174        thisfrag = payload + offset8;
1175        start = offset8 * 8;
1176        len = ntohs(ip->ip_len) - IP_HDR_SIZE_NO_UDP;
1177
1178        if (start + len > IP_MAXUDP) /* fragment extends too far */
1179                return NULL;
1180
1181        if (!total_len || localip->ip_id != ip->ip_id) {
1182                /* new (or different) packet, reset structs */
1183                total_len = 0xffff;
1184                payload[0].last_byte = ~0;
1185                payload[0].next_hole = 0;
1186                payload[0].prev_hole = 0;
1187                first_hole = 0;
1188                /* any IP header will work, copy the first we received */
1189                memcpy(localip, ip, IP_HDR_SIZE_NO_UDP);
1190        }
1191
1192        /*
1193         * What follows is the reassembly algorithm. We use the payload
1194         * array as a linked list of hole descriptors, as each hole starts
1195         * at a multiple of 8 bytes. However, last byte can be whatever value,
1196         * so it is represented as byte count, not as 8-byte blocks.
1197         */
1198
1199        h = payload + first_hole;
1200        while (h->last_byte < start) {
1201                if (!h->next_hole) {
1202                        /* no hole that far away */
1203                        return NULL;
1204                }
1205                h = payload + h->next_hole;
1206        }
1207
1208        /* last fragment may be 1..7 bytes, the "+7" forces acceptance */
1209        if (offset8 + ((len + 7) / 8) <= h - payload) {
1210                /* no overlap with holes (dup fragment?) */
1211                return NULL;
1212        }
1213
1214        if (!(ip_off & IP_FLAGS_MFRAG)) {
1215                /* no more fragmentss: truncate this (last) hole */
1216                total_len = start + len;
1217                h->last_byte = start + len;
1218        }
1219
1220        /*
1221         * There is some overlap: fix the hole list. This code doesn't
1222         * deal with a fragment that overlaps with two different holes
1223         * (thus being a superset of a previously-received fragment).
1224         */
1225
1226        if ( (h >= thisfrag) && (h->last_byte <= start + len) ) {
1227                /* complete overlap with hole: remove hole */
1228                if (!h->prev_hole && !h->next_hole) {
1229                        /* last remaining hole */
1230                        done = 1;
1231                } else if (!h->prev_hole) {
1232                        /* first hole */
1233                        first_hole = h->next_hole;
1234                        payload[h->next_hole].prev_hole = 0;
1235                } else if (!h->next_hole) {
1236                        /* last hole */
1237                        payload[h->prev_hole].next_hole = 0;
1238                } else {
1239                        /* in the middle of the list */
1240                        payload[h->next_hole].prev_hole = h->prev_hole;
1241                        payload[h->prev_hole].next_hole = h->next_hole;
1242                }
1243
1244        } else if (h->last_byte <= start + len) {
1245                /* overlaps with final part of the hole: shorten this hole */
1246                h->last_byte = start;
1247
1248        } else if (h >= thisfrag) {
1249                /* overlaps with initial part of the hole: move this hole */
1250                newh = thisfrag + (len / 8);
1251                *newh = *h;
1252                h = newh;
1253                if (h->next_hole)
1254                        payload[h->next_hole].prev_hole = (h - payload);
1255                if (h->prev_hole)
1256                        payload[h->prev_hole].next_hole = (h - payload);
1257                else
1258                        first_hole = (h - payload);
1259
1260        } else {
1261                /* fragment sits in the middle: split the hole */
1262                newh = thisfrag + (len / 8);
1263                *newh = *h;
1264                h->last_byte = start;
1265                h->next_hole = (newh - payload);
1266                newh->prev_hole = (h - payload);
1267                if (newh->next_hole)
1268                        payload[newh->next_hole].prev_hole = (newh - payload);
1269        }
1270
1271        /* finally copy this fragment and possibly return whole packet */
1272        memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE_NO_UDP, len);
1273        if (!done)
1274                return NULL;
1275
1276        localip->ip_len = htons(total_len);
1277        *lenp = total_len + IP_HDR_SIZE_NO_UDP;
1278        return localip;
1279}
1280
1281static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
1282{
1283        u16 ip_off = ntohs(ip->ip_off);
1284        if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1285                return ip; /* not a fragment */
1286        return __NetDefragment(ip, lenp);
1287}
1288
1289#else /* !CONFIG_IP_DEFRAG */
1290
1291static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
1292{
1293        u16 ip_off = ntohs(ip->ip_off);
1294        if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1295                return ip; /* not a fragment */
1296        return NULL;
1297}
1298#endif
1299
1300void
1301NetReceive(volatile uchar * inpkt, int len)
1302{
1303        Ethernet_t *et;
1304        IP_t    *ip;
1305        ARP_t   *arp;
1306        IPaddr_t tmp;
1307        int     x;
1308        uchar *pkt;
1309#if defined(CONFIG_CMD_CDP)
1310        int iscdp;
1311#endif
1312        ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
1313
1314        debug("packet received\n");
1315
1316        NetRxPacket = inpkt;
1317        NetRxPacketLen = len;
1318        et = (Ethernet_t *)inpkt;
1319
1320        /* too small packet? */
1321        if (len < ETHER_HDR_SIZE)
1322                return;
1323
1324#ifdef CONFIG_API
1325        if (push_packet) {
1326                (*push_packet)(inpkt, len);
1327                return;
1328        }
1329#endif
1330
1331#if defined(CONFIG_CMD_CDP)
1332        /* keep track if packet is CDP */
1333        iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0;
1334#endif
1335
1336        myvlanid = ntohs(NetOurVLAN);
1337        if (myvlanid == (ushort)-1)
1338                myvlanid = VLAN_NONE;
1339        mynvlanid = ntohs(NetOurNativeVLAN);
1340        if (mynvlanid == (ushort)-1)
1341                mynvlanid = VLAN_NONE;
1342
1343        x = ntohs(et->et_protlen);
1344
1345        debug("packet received\n");
1346
1347        if (x < 1514) {
1348                /*
1349                 *      Got a 802 packet.  Check the other protocol field.
1350                 */
1351                x = ntohs(et->et_prot);
1352
1353                ip = (IP_t *)(inpkt + E802_HDR_SIZE);
1354                len -= E802_HDR_SIZE;
1355
1356        } else if (x != PROT_VLAN) {    /* normal packet */
1357                ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
1358                len -= ETHER_HDR_SIZE;
1359
1360        } else {                        /* VLAN packet */
1361                VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
1362
1363                debug("VLAN packet received\n");
1364
1365                /* too small packet? */
1366                if (len < VLAN_ETHER_HDR_SIZE)
1367                        return;
1368
1369                /* if no VLAN active */
1370                if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
1371#if defined(CONFIG_CMD_CDP)
1372                                && iscdp == 0
1373#endif
1374                                )
1375                        return;
1376
1377                cti = ntohs(vet->vet_tag);
1378                vlanid = cti & VLAN_IDMASK;
1379                x = ntohs(vet->vet_type);
1380
1381                ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
1382                len -= VLAN_ETHER_HDR_SIZE;
1383        }
1384
1385        debug("Receive from protocol 0x%x\n", x);
1386
1387#if defined(CONFIG_CMD_CDP)
1388        if (iscdp) {
1389                CDPHandler((uchar *)ip, len);
1390                return;
1391        }
1392#endif
1393
1394        if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1395                if (vlanid == VLAN_NONE)
1396                        vlanid = (mynvlanid & VLAN_IDMASK);
1397                /* not matched? */
1398                if (vlanid != (myvlanid & VLAN_IDMASK))
1399                        return;
1400        }
1401
1402        switch (x) {
1403
1404        case PROT_ARP:
1405                /*
1406                 * We have to deal with two types of ARP packets:
1407                 * - REQUEST packets will be answered by sending  our
1408                 *   IP address - if we know it.
1409                 * - REPLY packates are expected only after we asked
1410                 *   for the TFTP server's or the gateway's ethernet
1411                 *   address; so if we receive such a packet, we set
1412                 *   the server ethernet address
1413                 */
1414                debug("Got ARP\n");
1415
1416                arp = (ARP_t *)ip;
1417                if (len < ARP_HDR_SIZE) {
1418                        printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1419                        return;
1420                }
1421                if (ntohs(arp->ar_hrd) != ARP_ETHER) {
1422                        return;
1423                }
1424                if (ntohs(arp->ar_pro) != PROT_IP) {
1425                        return;
1426                }
1427                if (arp->ar_hln != 6) {
1428                        return;
1429                }
1430                if (arp->ar_pln != 4) {
1431                        return;
1432                }
1433
1434                if (NetOurIP == 0) {
1435                        return;
1436                }
1437
1438                if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
1439                        return;
1440                }
1441
1442                switch (ntohs(arp->ar_op)) {
1443                case ARPOP_REQUEST:             /* reply with our IP address    */
1444                        debug("Got ARP REQUEST, return our IP\n");
1445                        pkt = (uchar *)et;
1446                        pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
1447                        arp->ar_op = htons(ARPOP_REPLY);
1448                        memcpy   (&arp->ar_data[10], &arp->ar_data[0], 6);
1449                        NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
1450                        memcpy   (&arp->ar_data[ 0], NetOurEther, 6);
1451                        NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
1452                        (void) eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
1453                        return;
1454
1455                case ARPOP_REPLY:               /* arp reply */
1456                        /* are we waiting for a reply */
1457                        if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
1458                                break;
1459
1460#ifdef CONFIG_KEEP_SERVERADDR
1461                        if (NetServerIP == NetArpWaitPacketIP) {
1462                                char buf[20];
1463                                sprintf(buf, "%pM", arp->ar_data);
1464                                setenv("serveraddr", buf);
1465                        }
1466#endif
1467
1468                        debug("Got ARP REPLY, set server/gtwy eth addr (%pM)\n",
1469                                arp->ar_data);
1470
1471                        tmp = NetReadIP(&arp->ar_data[6]);
1472
1473                        /* matched waiting packet's address */
1474                        if (tmp == NetArpWaitReplyIP) {
1475                                debug("Got it\n");
1476                                /* save address for later use */
1477                                memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
1478
1479#ifdef CONFIG_NETCONSOLE
1480                                (*packetHandler)(0,0,0,0);
1481#endif
1482                                /* modify header, and transmit it */
1483                                memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
1484                                (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
1485
1486                                /* no arp request pending now */
1487                                NetArpWaitPacketIP = 0;
1488                                NetArpWaitTxPacketSize = 0;
1489                                NetArpWaitPacketMAC = NULL;
1490
1491                        }
1492                        return;
1493                default:
1494                        debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
1495                        return;
1496                }
1497                break;
1498
1499#ifdef CONFIG_CMD_RARP
1500        case PROT_RARP:
1501                debug("Got RARP\n");
1502                arp = (ARP_t *)ip;
1503                if (len < ARP_HDR_SIZE) {
1504                        printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
1505                        return;
1506                }
1507
1508                if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
1509                        (ntohs(arp->ar_hrd) != ARP_ETHER)   ||
1510                        (ntohs(arp->ar_pro) != PROT_IP)     ||
1511                        (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
1512
1513                        puts ("invalid RARP header\n");
1514                } else {
1515                        NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
1516                        if (NetServerIP == 0)
1517                                NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
1518                        memcpy (NetServerEther, &arp->ar_data[ 0], 6);
1519
1520                        (*packetHandler)(0,0,0,0);
1521                }
1522                break;
1523#endif
1524        case PROT_IP:
1525                debug("Got IP\n");
1526                /* Before we start poking the header, make sure it is there */
1527                if (len < IP_HDR_SIZE) {
1528                        debug("len bad %d < %lu\n", len, (ulong)IP_HDR_SIZE);
1529                        return;
1530                }
1531                /* Check the packet length */
1532                if (len < ntohs(ip->ip_len)) {
1533                        printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
1534                        return;
1535                }
1536                len = ntohs(ip->ip_len);
1537                debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
1538
1539                /* Can't deal with anything except IPv4 */
1540                if ((ip->ip_hl_v & 0xf0) != 0x40) {
1541                        return;
1542                }
1543                /* Can't deal with IP options (headers != 20 bytes) */
1544                if ((ip->ip_hl_v & 0x0f) > 0x05) {
1545                        return;
1546                }
1547                /* Check the Checksum of the header */
1548                if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
1549                        puts ("checksum bad\n");
1550                        return;
1551                }
1552                /* If it is not for us, ignore it */
1553                tmp = NetReadIP(&ip->ip_dst);
1554                if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
1555#ifdef CONFIG_MCAST_TFTP
1556                        if (Mcast_addr != tmp)
1557#endif
1558                        return;
1559                }
1560                /*
1561                 * The function returns the unchanged packet if it's not
1562                 * a fragment, and either the complete packet or NULL if
1563                 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
1564                 */
1565                if (!(ip = NetDefragment(ip, &len)))
1566                        return;
1567                /*
1568                 * watch for ICMP host redirects
1569                 *
1570                 * There is no real handler code (yet). We just watch
1571                 * for ICMP host redirect messages. In case anybody
1572                 * sees these messages: please contact me
1573                 * (wd@denx.de), or - even better - send me the
1574                 * necessary fixes :-)
1575                 *
1576                 * Note: in all cases where I have seen this so far
1577                 * it was a problem with the router configuration,
1578                 * for instance when a router was configured in the
1579                 * BOOTP reply, but the TFTP server was on the same
1580                 * subnet. So this is probably a warning that your
1581                 * configuration might be wrong. But I'm not really
1582                 * sure if there aren't any other situations.
1583                 */
1584                if (ip->ip_p == IPPROTO_ICMP) {
1585                        ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
1586
1587                        switch (icmph->type) {
1588                        case ICMP_REDIRECT:
1589                                if (icmph->code != ICMP_REDIR_HOST)
1590                                        return;
1591                                printf (" ICMP Host Redirect to %pI4 ", &icmph->un.gateway);
1592                                return;
1593#if defined(CONFIG_CMD_PING)
1594                        case ICMP_ECHO_REPLY:
1595                                /*
1596                                 *      IP header OK.  Pass the packet to the current handler.
1597                                 */
1598                                /* XXX point to ip packet */
1599                                (*packetHandler)((uchar *)ip, 0, 0, 0);
1600                                return;
1601                        case ICMP_ECHO_REQUEST:
1602                                debug("Got ICMP ECHO REQUEST, return %d bytes \n",
1603                                        ETHER_HDR_SIZE + len);
1604
1605                                memcpy (&et->et_dest[0], &et->et_src[0], 6);
1606                                memcpy (&et->et_src[ 0], NetOurEther, 6);
1607
1608                                ip->ip_sum = 0;
1609                                ip->ip_off = 0;
1610                                NetCopyIP((void*)&ip->ip_dst, &ip->ip_src);
1611                                NetCopyIP((void*)&ip->ip_src, &NetOurIP);
1612                                ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP >> 1);
1613
1614                                icmph->type = ICMP_ECHO_REPLY;
1615                                icmph->checksum = 0;
1616                                icmph->checksum = ~NetCksum((uchar *)icmph,
1617                                                (len - IP_HDR_SIZE_NO_UDP) >> 1);
1618                                (void) eth_send((uchar *)et, ETHER_HDR_SIZE + len);
1619                                return;
1620#endif
1621                        default:
1622                                return;
1623                        }
1624                } else if (ip->ip_p != IPPROTO_UDP) {   /* Only UDP packets */
1625                        return;
1626                }
1627
1628#ifdef CONFIG_UDP_CHECKSUM
1629                if (ip->udp_xsum != 0) {
1630                        ulong   xsum;
1631                        ushort *sumptr;
1632                        ushort  sumlen;
1633
1634                        xsum  = ip->ip_p;
1635                        xsum += (ntohs(ip->udp_len));
1636                        xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
1637                        xsum += (ntohl(ip->ip_src) >>  0) & 0x0000ffff;
1638                        xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
1639                        xsum += (ntohl(ip->ip_dst) >>  0) & 0x0000ffff;
1640
1641                        sumlen = ntohs(ip->udp_len);
1642                        sumptr = (ushort *) &(ip->udp_src);
1643
1644                        while (sumlen > 1) {
1645                                ushort sumdata;
1646
1647                                sumdata = *sumptr++;
1648                                xsum += ntohs(sumdata);
1649                                sumlen -= 2;
1650                        }
1651                        if (sumlen > 0) {
1652                                ushort sumdata;
1653
1654                                sumdata = *(unsigned char *) sumptr;
1655                                sumdata = (sumdata << 8) & 0xff00;
1656                                xsum += sumdata;
1657                        }
1658                        while ((xsum >> 16) != 0) {
1659                                xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
1660                        }
1661                        if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1662                                printf(" UDP wrong checksum %08lx %08x\n",
1663                                        xsum, ntohs(ip->udp_xsum));
1664                                return;
1665                        }
1666                }
1667#endif
1668
1669
1670#ifdef CONFIG_NETCONSOLE
1671                nc_input_packet((uchar *)ip +IP_HDR_SIZE,
1672                                                ntohs(ip->udp_dst),
1673                                                ntohs(ip->udp_src),
1674                                                ntohs(ip->udp_len) - 8);
1675#endif
1676                /*
1677                 *      IP header OK.  Pass the packet to the current handler.
1678                 */
1679                (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
1680                                                ntohs(ip->udp_dst),
1681                                                ntohs(ip->udp_src),
1682                                                ntohs(ip->udp_len) - 8);
1683                break;
1684        }
1685}
1686
1687
1688/**********************************************************************/
1689
1690static int net_check_prereq (proto_t protocol)
1691{
1692        switch (protocol) {
1693                /* Fall through */
1694#if defined(CONFIG_CMD_PING)
1695        case PING:
1696                if (NetPingIP == 0) {
1697                        puts ("*** ERROR: ping address not given\n");
1698                        return (1);
1699                }
1700                goto common;
1701#endif
1702#if defined(CONFIG_CMD_SNTP)
1703        case SNTP:
1704                if (NetNtpServerIP == 0) {
1705                        puts ("*** ERROR: NTP server address not given\n");
1706                        return (1);
1707                }
1708                goto common;
1709#endif
1710#if defined(CONFIG_CMD_DNS)
1711        case DNS:
1712                if (NetOurDNSIP == 0) {
1713                        puts("*** ERROR: DNS server address not given\n");
1714                        return 1;
1715                }
1716                goto common;
1717#endif
1718#if defined(CONFIG_CMD_NFS)
1719        case NFS:
1720#endif
1721        case NETCONS:
1722        case TFTP:
1723                if (NetServerIP == 0) {
1724                        puts ("*** ERROR: `serverip' not set\n");
1725                        return (1);
1726                }
1727#if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP)
1728    common:
1729#endif
1730
1731                if (NetOurIP == 0) {
1732                        puts ("*** ERROR: `ipaddr' not set\n");
1733                        return (1);
1734                }
1735                /* Fall through */
1736
1737#ifdef CONFIG_CMD_RARP
1738        case RARP:
1739#endif
1740        case BOOTP:
1741        case CDP:
1742        case DHCP:
1743                if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
1744#ifdef CONFIG_NET_MULTI
1745                        extern int eth_get_dev_index (void);
1746                        int num = eth_get_dev_index ();
1747
1748                        switch (num) {
1749                        case -1:
1750                                puts ("*** ERROR: No ethernet found.\n");
1751                                return (1);
1752                        case 0:
1753                                puts ("*** ERROR: `ethaddr' not set\n");
1754                                break;
1755                        default:
1756                                printf ("*** ERROR: `eth%daddr' not set\n",
1757                                        num);
1758                                break;
1759                        }
1760
1761                        NetStartAgain ();
1762                        return (2);
1763#else
1764                        puts ("*** ERROR: `ethaddr' not set\n");
1765                        return (1);
1766#endif
1767                }
1768                /* Fall through */
1769        default:
1770                return (0);
1771        }
1772        return (0);             /* OK */
1773}
1774/**********************************************************************/
1775
1776int
1777NetCksumOk(uchar * ptr, int len)
1778{
1779        return !((NetCksum(ptr, len) + 1) & 0xfffe);
1780}
1781
1782
1783unsigned
1784NetCksum(uchar * ptr, int len)
1785{
1786        ulong   xsum;
1787        ushort *p = (ushort *)ptr;
1788
1789        xsum = 0;
1790        while (len-- > 0)
1791                xsum += *p++;
1792        xsum = (xsum & 0xffff) + (xsum >> 16);
1793        xsum = (xsum & 0xffff) + (xsum >> 16);
1794        return (xsum & 0xffff);
1795}
1796
1797int
1798NetEthHdrSize(void)
1799{
1800        ushort myvlanid;
1801
1802        myvlanid = ntohs(NetOurVLAN);
1803        if (myvlanid == (ushort)-1)
1804                myvlanid = VLAN_NONE;
1805
1806        return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
1807}
1808
1809int
1810NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
1811{
1812        Ethernet_t *et = (Ethernet_t *)xet;
1813        ushort myvlanid;
1814
1815        myvlanid = ntohs(NetOurVLAN);
1816        if (myvlanid == (ushort)-1)
1817                myvlanid = VLAN_NONE;
1818
1819        memcpy (et->et_dest, addr, 6);
1820        memcpy (et->et_src, NetOurEther, 6);
1821        if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1822        et->et_protlen = htons(prot);
1823                return ETHER_HDR_SIZE;
1824        } else {
1825                VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
1826
1827                vet->vet_vlan_type = htons(PROT_VLAN);
1828                vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1829                vet->vet_type = htons(prot);
1830                return VLAN_ETHER_HDR_SIZE;
1831        }
1832}
1833
1834void
1835NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
1836{
1837        IP_t *ip = (IP_t *)xip;
1838
1839        /*
1840         *      If the data is an odd number of bytes, zero the
1841         *      byte after the last byte so that the checksum
1842         *      will work.
1843         */
1844        if (len & 1)
1845                xip[IP_HDR_SIZE + len] = 0;
1846
1847        /*
1848         *      Construct an IP and UDP header.
1849         *      (need to set no fragment bit - XXX)
1850         */
1851        ip->ip_hl_v  = 0x45;            /* IP_HDR_SIZE / 4 (not including UDP) */
1852        ip->ip_tos   = 0;
1853        ip->ip_len   = htons(IP_HDR_SIZE + len);
1854        ip->ip_id    = htons(NetIPID++);
1855        ip->ip_off   = htons(IP_FLAGS_DFRAG);   /* Don't fragment */
1856        ip->ip_ttl   = 255;
1857        ip->ip_p     = 17;              /* UDP */
1858        ip->ip_sum   = 0;
1859        NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1860        NetCopyIP((void*)&ip->ip_dst, &dest);      /* - "" - */
1861        ip->udp_src  = htons(sport);
1862        ip->udp_dst  = htons(dport);
1863        ip->udp_len  = htons(8 + len);
1864        ip->udp_xsum = 0;
1865        ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1866}
1867
1868void copy_filename (char *dst, const char *src, int size)
1869{
1870        if (*src && (*src == '"')) {
1871                ++src;
1872                --size;
1873        }
1874
1875        while ((--size > 0) && *src && (*src != '"')) {
1876                *dst++ = *src++;
1877        }
1878        *dst = '\0';
1879}
1880
1881#if defined(CONFIG_CMD_NFS) || defined(CONFIG_CMD_SNTP) || defined(CONFIG_CMD_DNS)
1882/*
1883 * make port a little random (1024-17407)
1884 * This keeps the math somewhat trivial to compute, and seems to work with
1885 * all supported protocols/clients/servers
1886 */
1887unsigned int random_port(void)
1888{
1889        return 1024 + (get_timer(0) % 0x4000);
1890}
1891#endif
1892
1893void ip_to_string (IPaddr_t x, char *s)
1894{
1895        x = ntohl (x);
1896        sprintf (s, "%d.%d.%d.%d",
1897                 (int) ((x >> 24) & 0xff),
1898                 (int) ((x >> 16) & 0xff),
1899                 (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
1900        );
1901}
1902
1903void VLAN_to_string(ushort x, char *s)
1904{
1905        x = ntohs(x);
1906
1907        if (x == (ushort)-1)
1908                x = VLAN_NONE;
1909
1910        if (x == VLAN_NONE)
1911                strcpy(s, "none");
1912        else
1913                sprintf(s, "%d", x & VLAN_IDMASK);
1914}
1915
1916ushort string_to_VLAN(const char *s)
1917{
1918        ushort id;
1919
1920        if (s == NULL)
1921                return htons(VLAN_NONE);
1922
1923        if (*s < '0' || *s > '9')
1924                id = VLAN_NONE;
1925        else
1926                id = (ushort)simple_strtoul(s, NULL, 10);
1927
1928        return htons(id);
1929}
1930
1931ushort getenv_VLAN(char *var)
1932{
1933        return (string_to_VLAN(getenv(var)));
1934}
1935