uboot/net/net.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *      Copied from Linux Monitor (LiMon) - Networking.
   4 *
   5 *      Copyright 1994 - 2000 Neil Russell.
   6 *      (See License)
   7 *      Copyright 2000 Roland Borde
   8 *      Copyright 2000 Paolo Scaffardi
   9 *      Copyright 2000-2002 Wolfgang Denk, wd@denx.de
  10 */
  11
  12/*
  13 * General Desription:
  14 *
  15 * The user interface supports commands for BOOTP, RARP, and TFTP.
  16 * Also, we support ARP internally. Depending on available data,
  17 * these interact as follows:
  18 *
  19 * BOOTP:
  20 *
  21 *      Prerequisites:  - own ethernet address
  22 *      We want:        - own IP address
  23 *                      - TFTP server IP address
  24 *                      - name of bootfile
  25 *      Next step:      ARP
  26 *
  27 * LINK_LOCAL:
  28 *
  29 *      Prerequisites:  - own ethernet address
  30 *      We want:        - own IP address
  31 *      Next step:      ARP
  32 *
  33 * RARP:
  34 *
  35 *      Prerequisites:  - own ethernet address
  36 *      We want:        - own IP address
  37 *                      - TFTP server IP address
  38 *      Next step:      ARP
  39 *
  40 * ARP:
  41 *
  42 *      Prerequisites:  - own ethernet address
  43 *                      - own IP address
  44 *                      - TFTP server IP address
  45 *      We want:        - TFTP server ethernet address
  46 *      Next step:      TFTP
  47 *
  48 * DHCP:
  49 *
  50 *     Prerequisites:   - own ethernet address
  51 *     We want:         - IP, Netmask, ServerIP, Gateway IP
  52 *                      - bootfilename, lease time
  53 *     Next step:       - TFTP
  54 *
  55 * TFTP:
  56 *
  57 *      Prerequisites:  - own ethernet address
  58 *                      - own IP address
  59 *                      - TFTP server IP address
  60 *                      - TFTP server ethernet address
  61 *                      - name of bootfile (if unknown, we use a default name
  62 *                        derived from our own IP address)
  63 *      We want:        - load the boot file
  64 *      Next step:      none
  65 *
  66 * NFS:
  67 *
  68 *      Prerequisites:  - own ethernet address
  69 *                      - own IP address
  70 *                      - name of bootfile (if unknown, we use a default name
  71 *                        derived from our own IP address)
  72 *      We want:        - load the boot file
  73 *      Next step:      none
  74 *
  75 * SNTP:
  76 *
  77 *      Prerequisites:  - own ethernet address
  78 *                      - own IP address
  79 *      We want:        - network time
  80 *      Next step:      none
  81 *
  82 * WOL:
  83 *
  84 *      Prerequisites:  - own ethernet address
  85 *      We want:        - magic packet or timeout
  86 *      Next step:      none
  87 */
  88
  89
  90#include <common.h>
  91#include <command.h>
  92#include <console.h>
  93#include <environment.h>
  94#include <errno.h>
  95#include <net.h>
  96#include <net/fastboot.h>
  97#include <net/tftp.h>
  98#if defined(CONFIG_LED_STATUS)
  99#include <miiphy.h>
 100#include <status_led.h>
 101#endif
 102#include <watchdog.h>
 103#include <linux/compiler.h>
 104#include "arp.h"
 105#include "bootp.h"
 106#include "cdp.h"
 107#if defined(CONFIG_CMD_DNS)
 108#include "dns.h"
 109#endif
 110#include "link_local.h"
 111#include "nfs.h"
 112#include "ping.h"
 113#include "rarp.h"
 114#if defined(CONFIG_CMD_SNTP)
 115#include "sntp.h"
 116#endif
 117#if defined(CONFIG_CMD_WOL)
 118#include "wol.h"
 119#endif
 120
 121/** BOOTP EXTENTIONS **/
 122
 123/* Our subnet mask (0=unknown) */
 124struct in_addr net_netmask;
 125/* Our gateways IP address */
 126struct in_addr net_gateway;
 127/* Our DNS IP address */
 128struct in_addr net_dns_server;
 129#if defined(CONFIG_BOOTP_DNS2)
 130/* Our 2nd DNS IP address */
 131struct in_addr net_dns_server2;
 132#endif
 133
 134/** END OF BOOTP EXTENTIONS **/
 135
 136/* Our ethernet address */
 137u8 net_ethaddr[6];
 138/* Boot server enet address */
 139u8 net_server_ethaddr[6];
 140/* Our IP addr (0 = unknown) */
 141struct in_addr  net_ip;
 142/* Server IP addr (0 = unknown) */
 143struct in_addr  net_server_ip;
 144/* Current receive packet */
 145uchar *net_rx_packet;
 146/* Current rx packet length */
 147int             net_rx_packet_len;
 148/* IP packet ID */
 149static unsigned net_ip_id;
 150/* Ethernet bcast address */
 151const u8 net_bcast_ethaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 152const u8 net_null_ethaddr[6];
 153#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
 154void (*push_packet)(void *, int len) = 0;
 155#endif
 156/* Network loop state */
 157enum net_loop_state net_state;
 158/* Tried all network devices */
 159int             net_restart_wrap;
 160/* Network loop restarted */
 161static int      net_restarted;
 162/* At least one device configured */
 163static int      net_dev_exists;
 164
 165/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
 166/* default is without VLAN */
 167ushort          net_our_vlan = 0xFFFF;
 168/* ditto */
 169ushort          net_native_vlan = 0xFFFF;
 170
 171/* Boot File name */
 172char net_boot_file_name[1024];
 173/* Indicates whether the file name was specified on the command line */
 174bool net_boot_file_name_explicit;
 175/* The actual transferred size of the bootfile (in bytes) */
 176u32 net_boot_file_size;
 177/* Boot file size in blocks as reported by the DHCP server */
 178u32 net_boot_file_expected_size_in_blocks;
 179
 180#if defined(CONFIG_CMD_SNTP)
 181/* NTP server IP address */
 182struct in_addr  net_ntp_server;
 183/* offset time from UTC */
 184int             net_ntp_time_offset;
 185#endif
 186
 187static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
 188/* Receive packets */
 189uchar *net_rx_packets[PKTBUFSRX];
 190/* Current UDP RX packet handler */
 191static rxhand_f *udp_packet_handler;
 192/* Current ARP RX packet handler */
 193static rxhand_f *arp_packet_handler;
 194#ifdef CONFIG_CMD_TFTPPUT
 195/* Current ICMP rx handler */
 196static rxhand_icmp_f *packet_icmp_handler;
 197#endif
 198/* Current timeout handler */
 199static thand_f *time_handler;
 200/* Time base value */
 201static ulong    time_start;
 202/* Current timeout value */
 203static ulong    time_delta;
 204/* THE transmit packet */
 205uchar *net_tx_packet;
 206
 207static int net_check_prereq(enum proto_t protocol);
 208
 209static int net_try_count;
 210
 211int __maybe_unused net_busy_flag;
 212
 213/**********************************************************************/
 214
 215static int on_ipaddr(const char *name, const char *value, enum env_op op,
 216        int flags)
 217{
 218        if (flags & H_PROGRAMMATIC)
 219                return 0;
 220
 221        net_ip = string_to_ip(value);
 222
 223        return 0;
 224}
 225U_BOOT_ENV_CALLBACK(ipaddr, on_ipaddr);
 226
 227static int on_gatewayip(const char *name, const char *value, enum env_op op,
 228        int flags)
 229{
 230        if (flags & H_PROGRAMMATIC)
 231                return 0;
 232
 233        net_gateway = string_to_ip(value);
 234
 235        return 0;
 236}
 237U_BOOT_ENV_CALLBACK(gatewayip, on_gatewayip);
 238
 239static int on_netmask(const char *name, const char *value, enum env_op op,
 240        int flags)
 241{
 242        if (flags & H_PROGRAMMATIC)
 243                return 0;
 244
 245        net_netmask = string_to_ip(value);
 246
 247        return 0;
 248}
 249U_BOOT_ENV_CALLBACK(netmask, on_netmask);
 250
 251static int on_serverip(const char *name, const char *value, enum env_op op,
 252        int flags)
 253{
 254        if (flags & H_PROGRAMMATIC)
 255                return 0;
 256
 257        net_server_ip = string_to_ip(value);
 258
 259        return 0;
 260}
 261U_BOOT_ENV_CALLBACK(serverip, on_serverip);
 262
 263static int on_nvlan(const char *name, const char *value, enum env_op op,
 264        int flags)
 265{
 266        if (flags & H_PROGRAMMATIC)
 267                return 0;
 268
 269        net_native_vlan = string_to_vlan(value);
 270
 271        return 0;
 272}
 273U_BOOT_ENV_CALLBACK(nvlan, on_nvlan);
 274
 275static int on_vlan(const char *name, const char *value, enum env_op op,
 276        int flags)
 277{
 278        if (flags & H_PROGRAMMATIC)
 279                return 0;
 280
 281        net_our_vlan = string_to_vlan(value);
 282
 283        return 0;
 284}
 285U_BOOT_ENV_CALLBACK(vlan, on_vlan);
 286
 287#if defined(CONFIG_CMD_DNS)
 288static int on_dnsip(const char *name, const char *value, enum env_op op,
 289        int flags)
 290{
 291        if (flags & H_PROGRAMMATIC)
 292                return 0;
 293
 294        net_dns_server = string_to_ip(value);
 295
 296        return 0;
 297}
 298U_BOOT_ENV_CALLBACK(dnsip, on_dnsip);
 299#endif
 300
 301/*
 302 * Check if autoload is enabled. If so, use either NFS or TFTP to download
 303 * the boot file.
 304 */
 305void net_auto_load(void)
 306{
 307#if defined(CONFIG_CMD_NFS)
 308        const char *s = env_get("autoload");
 309
 310        if (s != NULL && strcmp(s, "NFS") == 0) {
 311                if (net_check_prereq(NFS)) {
 312/* We aren't expecting to get a serverip, so just accept the assigned IP */
 313#ifdef CONFIG_BOOTP_SERVERIP
 314                        net_set_state(NETLOOP_SUCCESS);
 315#else
 316                        printf("Cannot autoload with NFS\n");
 317                        net_set_state(NETLOOP_FAIL);
 318#endif
 319                        return;
 320                }
 321                /*
 322                 * Use NFS to load the bootfile.
 323                 */
 324                nfs_start();
 325                return;
 326        }
 327#endif
 328        if (env_get_yesno("autoload") == 0) {
 329                /*
 330                 * Just use BOOTP/RARP to configure system;
 331                 * Do not use TFTP to load the bootfile.
 332                 */
 333                net_set_state(NETLOOP_SUCCESS);
 334                return;
 335        }
 336        if (net_check_prereq(TFTPGET)) {
 337/* We aren't expecting to get a serverip, so just accept the assigned IP */
 338#ifdef CONFIG_BOOTP_SERVERIP
 339                net_set_state(NETLOOP_SUCCESS);
 340#else
 341                printf("Cannot autoload with TFTPGET\n");
 342                net_set_state(NETLOOP_FAIL);
 343#endif
 344                return;
 345        }
 346        tftp_start(TFTPGET);
 347}
 348
 349static void net_init_loop(void)
 350{
 351        if (eth_get_dev())
 352                memcpy(net_ethaddr, eth_get_ethaddr(), 6);
 353
 354        return;
 355}
 356
 357static void net_clear_handlers(void)
 358{
 359        net_set_udp_handler(NULL);
 360        net_set_arp_handler(NULL);
 361        net_set_timeout_handler(0, NULL);
 362}
 363
 364static void net_cleanup_loop(void)
 365{
 366        net_clear_handlers();
 367}
 368
 369void net_init(void)
 370{
 371        static int first_call = 1;
 372
 373        if (first_call) {
 374                /*
 375                 *      Setup packet buffers, aligned correctly.
 376                 */
 377                int i;
 378
 379                net_tx_packet = &net_pkt_buf[0] + (PKTALIGN - 1);
 380                net_tx_packet -= (ulong)net_tx_packet % PKTALIGN;
 381                for (i = 0; i < PKTBUFSRX; i++) {
 382                        net_rx_packets[i] = net_tx_packet +
 383                                (i + 1) * PKTSIZE_ALIGN;
 384                }
 385                arp_init();
 386                net_clear_handlers();
 387
 388                /* Only need to setup buffer pointers once. */
 389                first_call = 0;
 390        }
 391
 392        net_init_loop();
 393}
 394
 395/**********************************************************************/
 396/*
 397 *      Main network processing loop.
 398 */
 399
 400int net_loop(enum proto_t protocol)
 401{
 402        int ret = -EINVAL;
 403        enum net_loop_state prev_net_state = net_state;
 404
 405        net_restarted = 0;
 406        net_dev_exists = 0;
 407        net_try_count = 1;
 408        debug_cond(DEBUG_INT_STATE, "--- net_loop Entry\n");
 409
 410        bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
 411        net_init();
 412        if (eth_is_on_demand_init() || protocol != NETCONS) {
 413                eth_halt();
 414                eth_set_current();
 415                ret = eth_init();
 416                if (ret < 0) {
 417                        eth_halt();
 418                        return ret;
 419                }
 420        } else {
 421                eth_init_state_only();
 422        }
 423restart:
 424#ifdef CONFIG_USB_KEYBOARD
 425        net_busy_flag = 0;
 426#endif
 427        net_set_state(NETLOOP_CONTINUE);
 428
 429        /*
 430         *      Start the ball rolling with the given start function.  From
 431         *      here on, this code is a state machine driven by received
 432         *      packets and timer events.
 433         */
 434        debug_cond(DEBUG_INT_STATE, "--- net_loop Init\n");
 435        net_init_loop();
 436
 437        switch (net_check_prereq(protocol)) {
 438        case 1:
 439                /* network not configured */
 440                eth_halt();
 441                net_set_state(prev_net_state);
 442                return -ENODEV;
 443
 444        case 2:
 445                /* network device not configured */
 446                break;
 447
 448        case 0:
 449                net_dev_exists = 1;
 450                net_boot_file_size = 0;
 451                switch (protocol) {
 452                case TFTPGET:
 453#ifdef CONFIG_CMD_TFTPPUT
 454                case TFTPPUT:
 455#endif
 456                        /* always use ARP to get server ethernet address */
 457                        tftp_start(protocol);
 458                        break;
 459#ifdef CONFIG_CMD_TFTPSRV
 460                case TFTPSRV:
 461                        tftp_start_server();
 462                        break;
 463#endif
 464#ifdef CONFIG_UDP_FUNCTION_FASTBOOT
 465                case FASTBOOT:
 466                        fastboot_start_server();
 467                        break;
 468#endif
 469#if defined(CONFIG_CMD_DHCP)
 470                case DHCP:
 471                        bootp_reset();
 472                        net_ip.s_addr = 0;
 473                        dhcp_request();         /* Basically same as BOOTP */
 474                        break;
 475#endif
 476
 477                case BOOTP:
 478                        bootp_reset();
 479                        net_ip.s_addr = 0;
 480                        bootp_request();
 481                        break;
 482
 483#if defined(CONFIG_CMD_RARP)
 484                case RARP:
 485                        rarp_try = 0;
 486                        net_ip.s_addr = 0;
 487                        rarp_request();
 488                        break;
 489#endif
 490#if defined(CONFIG_CMD_PING)
 491                case PING:
 492                        ping_start();
 493                        break;
 494#endif
 495#if defined(CONFIG_CMD_NFS)
 496                case NFS:
 497                        nfs_start();
 498                        break;
 499#endif
 500#if defined(CONFIG_CMD_CDP)
 501                case CDP:
 502                        cdp_start();
 503                        break;
 504#endif
 505#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
 506                case NETCONS:
 507                        nc_start();
 508                        break;
 509#endif
 510#if defined(CONFIG_CMD_SNTP)
 511                case SNTP:
 512                        sntp_start();
 513                        break;
 514#endif
 515#if defined(CONFIG_CMD_DNS)
 516                case DNS:
 517                        dns_start();
 518                        break;
 519#endif
 520#if defined(CONFIG_CMD_LINK_LOCAL)
 521                case LINKLOCAL:
 522                        link_local_start();
 523                        break;
 524#endif
 525#if defined(CONFIG_CMD_WOL)
 526                case WOL:
 527                        wol_start();
 528                        break;
 529#endif
 530                default:
 531                        break;
 532                }
 533
 534                break;
 535        }
 536
 537#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 538#if     defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)        && \
 539        defined(CONFIG_LED_STATUS)                      && \
 540        defined(CONFIG_LED_STATUS_RED)
 541        /*
 542         * Echo the inverted link state to the fault LED.
 543         */
 544        if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR))
 545                status_led_set(CONFIG_LED_STATUS_RED, CONFIG_LED_STATUS_OFF);
 546        else
 547                status_led_set(CONFIG_LED_STATUS_RED, CONFIG_LED_STATUS_ON);
 548#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
 549#endif /* CONFIG_MII, ... */
 550#ifdef CONFIG_USB_KEYBOARD
 551        net_busy_flag = 1;
 552#endif
 553
 554        /*
 555         *      Main packet reception loop.  Loop receiving packets until
 556         *      someone sets `net_state' to a state that terminates.
 557         */
 558        for (;;) {
 559                WATCHDOG_RESET();
 560#ifdef CONFIG_SHOW_ACTIVITY
 561                show_activity(1);
 562#endif
 563                if (arp_timeout_check() > 0)
 564                        time_start = get_timer(0);
 565
 566                /*
 567                 *      Check the ethernet for a new packet.  The ethernet
 568                 *      receive routine will process it.
 569                 *      Most drivers return the most recent packet size, but not
 570                 *      errors that may have happened.
 571                 */
 572                eth_rx();
 573
 574                /*
 575                 *      Abort if ctrl-c was pressed.
 576                 */
 577                if (ctrlc()) {
 578                        /* cancel any ARP that may not have completed */
 579                        net_arp_wait_packet_ip.s_addr = 0;
 580
 581                        net_cleanup_loop();
 582                        eth_halt();
 583                        /* Invalidate the last protocol */
 584                        eth_set_last_protocol(BOOTP);
 585
 586                        puts("\nAbort\n");
 587                        /* include a debug print as well incase the debug
 588                           messages are directed to stderr */
 589                        debug_cond(DEBUG_INT_STATE, "--- net_loop Abort!\n");
 590                        ret = -EINTR;
 591                        goto done;
 592                }
 593
 594                /*
 595                 *      Check for a timeout, and run the timeout handler
 596                 *      if we have one.
 597                 */
 598                if (time_handler &&
 599                    ((get_timer(0) - time_start) > time_delta)) {
 600                        thand_f *x;
 601
 602#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 603#if     defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)        && \
 604        defined(CONFIG_LED_STATUS)                      && \
 605        defined(CONFIG_LED_STATUS_RED)
 606                        /*
 607                         * Echo the inverted link state to the fault LED.
 608                         */
 609                        if (miiphy_link(eth_get_dev()->name,
 610                                        CONFIG_SYS_FAULT_MII_ADDR))
 611                                status_led_set(CONFIG_LED_STATUS_RED,
 612                                               CONFIG_LED_STATUS_OFF);
 613                        else
 614                                status_led_set(CONFIG_LED_STATUS_RED,
 615                                               CONFIG_LED_STATUS_ON);
 616#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
 617#endif /* CONFIG_MII, ... */
 618                        debug_cond(DEBUG_INT_STATE, "--- net_loop timeout\n");
 619                        x = time_handler;
 620                        time_handler = (thand_f *)0;
 621                        (*x)();
 622                }
 623
 624                if (net_state == NETLOOP_FAIL)
 625                        ret = net_start_again();
 626
 627                switch (net_state) {
 628                case NETLOOP_RESTART:
 629                        net_restarted = 1;
 630                        goto restart;
 631
 632                case NETLOOP_SUCCESS:
 633                        net_cleanup_loop();
 634                        if (net_boot_file_size > 0) {
 635                                printf("Bytes transferred = %d (%x hex)\n",
 636                                       net_boot_file_size, net_boot_file_size);
 637                                env_set_hex("filesize", net_boot_file_size);
 638                                env_set_hex("fileaddr", load_addr);
 639                        }
 640                        if (protocol != NETCONS)
 641                                eth_halt();
 642                        else
 643                                eth_halt_state_only();
 644
 645                        eth_set_last_protocol(protocol);
 646
 647                        ret = net_boot_file_size;
 648                        debug_cond(DEBUG_INT_STATE, "--- net_loop Success!\n");
 649                        goto done;
 650
 651                case NETLOOP_FAIL:
 652                        net_cleanup_loop();
 653                        /* Invalidate the last protocol */
 654                        eth_set_last_protocol(BOOTP);
 655                        debug_cond(DEBUG_INT_STATE, "--- net_loop Fail!\n");
 656                        ret = -ENONET;
 657                        goto done;
 658
 659                case NETLOOP_CONTINUE:
 660                        continue;
 661                }
 662        }
 663
 664done:
 665#ifdef CONFIG_USB_KEYBOARD
 666        net_busy_flag = 0;
 667#endif
 668#ifdef CONFIG_CMD_TFTPPUT
 669        /* Clear out the handlers */
 670        net_set_udp_handler(NULL);
 671        net_set_icmp_handler(NULL);
 672#endif
 673        net_set_state(prev_net_state);
 674        return ret;
 675}
 676
 677/**********************************************************************/
 678
 679static void start_again_timeout_handler(void)
 680{
 681        net_set_state(NETLOOP_RESTART);
 682}
 683
 684int net_start_again(void)
 685{
 686        char *nretry;
 687        int retry_forever = 0;
 688        unsigned long retrycnt = 0;
 689        int ret;
 690
 691        nretry = env_get("netretry");
 692        if (nretry) {
 693                if (!strcmp(nretry, "yes"))
 694                        retry_forever = 1;
 695                else if (!strcmp(nretry, "no"))
 696                        retrycnt = 0;
 697                else if (!strcmp(nretry, "once"))
 698                        retrycnt = 1;
 699                else
 700                        retrycnt = simple_strtoul(nretry, NULL, 0);
 701        } else {
 702                retrycnt = 0;
 703                retry_forever = 0;
 704        }
 705
 706        if ((!retry_forever) && (net_try_count > retrycnt)) {
 707                eth_halt();
 708                net_set_state(NETLOOP_FAIL);
 709                /*
 710                 * We don't provide a way for the protocol to return an error,
 711                 * but this is almost always the reason.
 712                 */
 713                return -ETIMEDOUT;
 714        }
 715
 716        net_try_count++;
 717
 718        eth_halt();
 719#if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 720        eth_try_another(!net_restarted);
 721#endif
 722        ret = eth_init();
 723        if (net_restart_wrap) {
 724                net_restart_wrap = 0;
 725                if (net_dev_exists) {
 726                        net_set_timeout_handler(10000UL,
 727                                                start_again_timeout_handler);
 728                        net_set_udp_handler(NULL);
 729                } else {
 730                        net_set_state(NETLOOP_FAIL);
 731                }
 732        } else {
 733                net_set_state(NETLOOP_RESTART);
 734        }
 735        return ret;
 736}
 737
 738/**********************************************************************/
 739/*
 740 *      Miscelaneous bits.
 741 */
 742
 743static void dummy_handler(uchar *pkt, unsigned dport,
 744                        struct in_addr sip, unsigned sport,
 745                        unsigned len)
 746{
 747}
 748
 749rxhand_f *net_get_udp_handler(void)
 750{
 751        return udp_packet_handler;
 752}
 753
 754void net_set_udp_handler(rxhand_f *f)
 755{
 756        debug_cond(DEBUG_INT_STATE, "--- net_loop UDP handler set (%p)\n", f);
 757        if (f == NULL)
 758                udp_packet_handler = dummy_handler;
 759        else
 760                udp_packet_handler = f;
 761}
 762
 763rxhand_f *net_get_arp_handler(void)
 764{
 765        return arp_packet_handler;
 766}
 767
 768void net_set_arp_handler(rxhand_f *f)
 769{
 770        debug_cond(DEBUG_INT_STATE, "--- net_loop ARP handler set (%p)\n", f);
 771        if (f == NULL)
 772                arp_packet_handler = dummy_handler;
 773        else
 774                arp_packet_handler = f;
 775}
 776
 777#ifdef CONFIG_CMD_TFTPPUT
 778void net_set_icmp_handler(rxhand_icmp_f *f)
 779{
 780        packet_icmp_handler = f;
 781}
 782#endif
 783
 784void net_set_timeout_handler(ulong iv, thand_f *f)
 785{
 786        if (iv == 0) {
 787                debug_cond(DEBUG_INT_STATE,
 788                           "--- net_loop timeout handler cancelled\n");
 789                time_handler = (thand_f *)0;
 790        } else {
 791                debug_cond(DEBUG_INT_STATE,
 792                           "--- net_loop timeout handler set (%p)\n", f);
 793                time_handler = f;
 794                time_start = get_timer(0);
 795                time_delta = iv * CONFIG_SYS_HZ / 1000;
 796        }
 797}
 798
 799uchar *net_get_async_tx_pkt_buf(void)
 800{
 801        if (arp_is_waiting())
 802                return arp_tx_packet; /* If we are waiting, we already sent */
 803        else
 804                return net_tx_packet;
 805}
 806
 807int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport,
 808                int payload_len)
 809{
 810        return net_send_ip_packet(ether, dest, dport, sport, payload_len,
 811                                  IPPROTO_UDP, 0, 0, 0);
 812}
 813
 814int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
 815                       int payload_len, int proto, u8 action, u32 tcp_seq_num,
 816                       u32 tcp_ack_num)
 817{
 818        uchar *pkt;
 819        int eth_hdr_size;
 820        int pkt_hdr_size;
 821
 822        /* make sure the net_tx_packet is initialized (net_init() was called) */
 823        assert(net_tx_packet != NULL);
 824        if (net_tx_packet == NULL)
 825                return -1;
 826
 827        /* convert to new style broadcast */
 828        if (dest.s_addr == 0)
 829                dest.s_addr = 0xFFFFFFFF;
 830
 831        /* if broadcast, make the ether address a broadcast and don't do ARP */
 832        if (dest.s_addr == 0xFFFFFFFF)
 833                ether = (uchar *)net_bcast_ethaddr;
 834
 835        pkt = (uchar *)net_tx_packet;
 836
 837        eth_hdr_size = net_set_ether(pkt, ether, PROT_IP);
 838
 839        switch (proto) {
 840        case IPPROTO_UDP:
 841                net_set_udp_header(pkt + eth_hdr_size, dest, dport, sport,
 842                                   payload_len);
 843                pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
 844                break;
 845        default:
 846                return -EINVAL;
 847        }
 848
 849        /* if MAC address was not discovered yet, do an ARP request */
 850        if (memcmp(ether, net_null_ethaddr, 6) == 0) {
 851                debug_cond(DEBUG_DEV_PKT, "sending ARP for %pI4\n", &dest);
 852
 853                /* save the ip and eth addr for the packet to send after arp */
 854                net_arp_wait_packet_ip = dest;
 855                arp_wait_packet_ethaddr = ether;
 856
 857                /* size of the waiting packet */
 858                arp_wait_tx_packet_size = pkt_hdr_size + payload_len;
 859
 860                /* and do the ARP request */
 861                arp_wait_try = 1;
 862                arp_wait_timer_start = get_timer(0);
 863                arp_request();
 864                return 1;       /* waiting */
 865        } else {
 866                debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n",
 867                           &dest, ether);
 868                net_send_packet(net_tx_packet, pkt_hdr_size + payload_len);
 869                return 0;       /* transmitted */
 870        }
 871}
 872
 873#ifdef CONFIG_IP_DEFRAG
 874/*
 875 * This function collects fragments in a single packet, according
 876 * to the algorithm in RFC815. It returns NULL or the pointer to
 877 * a complete packet, in static storage
 878 */
 879#ifndef CONFIG_NET_MAXDEFRAG
 880#define CONFIG_NET_MAXDEFRAG 16384
 881#endif
 882#define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG)
 883
 884#define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE)
 885
 886/*
 887 * this is the packet being assembled, either data or frag control.
 888 * Fragments go by 8 bytes, so this union must be 8 bytes long
 889 */
 890struct hole {
 891        /* first_byte is address of this structure */
 892        u16 last_byte;  /* last byte in this hole + 1 (begin of next hole) */
 893        u16 next_hole;  /* index of next (in 8-b blocks), 0 == none */
 894        u16 prev_hole;  /* index of prev, 0 == none */
 895        u16 unused;
 896};
 897
 898static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp)
 899{
 900        static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
 901        static u16 first_hole, total_len;
 902        struct hole *payload, *thisfrag, *h, *newh;
 903        struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff;
 904        uchar *indata = (uchar *)ip;
 905        int offset8, start, len, done = 0;
 906        u16 ip_off = ntohs(ip->ip_off);
 907
 908        /* payload starts after IP header, this fragment is in there */
 909        payload = (struct hole *)(pkt_buff + IP_HDR_SIZE);
 910        offset8 =  (ip_off & IP_OFFS);
 911        thisfrag = payload + offset8;
 912        start = offset8 * 8;
 913        len = ntohs(ip->ip_len) - IP_HDR_SIZE;
 914
 915        if (start + len > IP_MAXUDP) /* fragment extends too far */
 916                return NULL;
 917
 918        if (!total_len || localip->ip_id != ip->ip_id) {
 919                /* new (or different) packet, reset structs */
 920                total_len = 0xffff;
 921                payload[0].last_byte = ~0;
 922                payload[0].next_hole = 0;
 923                payload[0].prev_hole = 0;
 924                first_hole = 0;
 925                /* any IP header will work, copy the first we received */
 926                memcpy(localip, ip, IP_HDR_SIZE);
 927        }
 928
 929        /*
 930         * What follows is the reassembly algorithm. We use the payload
 931         * array as a linked list of hole descriptors, as each hole starts
 932         * at a multiple of 8 bytes. However, last byte can be whatever value,
 933         * so it is represented as byte count, not as 8-byte blocks.
 934         */
 935
 936        h = payload + first_hole;
 937        while (h->last_byte < start) {
 938                if (!h->next_hole) {
 939                        /* no hole that far away */
 940                        return NULL;
 941                }
 942                h = payload + h->next_hole;
 943        }
 944
 945        /* last fragment may be 1..7 bytes, the "+7" forces acceptance */
 946        if (offset8 + ((len + 7) / 8) <= h - payload) {
 947                /* no overlap with holes (dup fragment?) */
 948                return NULL;
 949        }
 950
 951        if (!(ip_off & IP_FLAGS_MFRAG)) {
 952                /* no more fragmentss: truncate this (last) hole */
 953                total_len = start + len;
 954                h->last_byte = start + len;
 955        }
 956
 957        /*
 958         * There is some overlap: fix the hole list. This code doesn't
 959         * deal with a fragment that overlaps with two different holes
 960         * (thus being a superset of a previously-received fragment).
 961         */
 962
 963        if ((h >= thisfrag) && (h->last_byte <= start + len)) {
 964                /* complete overlap with hole: remove hole */
 965                if (!h->prev_hole && !h->next_hole) {
 966                        /* last remaining hole */
 967                        done = 1;
 968                } else if (!h->prev_hole) {
 969                        /* first hole */
 970                        first_hole = h->next_hole;
 971                        payload[h->next_hole].prev_hole = 0;
 972                } else if (!h->next_hole) {
 973                        /* last hole */
 974                        payload[h->prev_hole].next_hole = 0;
 975                } else {
 976                        /* in the middle of the list */
 977                        payload[h->next_hole].prev_hole = h->prev_hole;
 978                        payload[h->prev_hole].next_hole = h->next_hole;
 979                }
 980
 981        } else if (h->last_byte <= start + len) {
 982                /* overlaps with final part of the hole: shorten this hole */
 983                h->last_byte = start;
 984
 985        } else if (h >= thisfrag) {
 986                /* overlaps with initial part of the hole: move this hole */
 987                newh = thisfrag + (len / 8);
 988                *newh = *h;
 989                h = newh;
 990                if (h->next_hole)
 991                        payload[h->next_hole].prev_hole = (h - payload);
 992                if (h->prev_hole)
 993                        payload[h->prev_hole].next_hole = (h - payload);
 994                else
 995                        first_hole = (h - payload);
 996
 997        } else {
 998                /* fragment sits in the middle: split the hole */
 999                newh = thisfrag + (len / 8);
1000                *newh = *h;
1001                h->last_byte = start;
1002                h->next_hole = (newh - payload);
1003                newh->prev_hole = (h - payload);
1004                if (newh->next_hole)
1005                        payload[newh->next_hole].prev_hole = (newh - payload);
1006        }
1007
1008        /* finally copy this fragment and possibly return whole packet */
1009        memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len);
1010        if (!done)
1011                return NULL;
1012
1013        localip->ip_len = htons(total_len);
1014        *lenp = total_len + IP_HDR_SIZE;
1015        return localip;
1016}
1017
1018static inline struct ip_udp_hdr *net_defragment(struct ip_udp_hdr *ip,
1019        int *lenp)
1020{
1021        u16 ip_off = ntohs(ip->ip_off);
1022        if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1023                return ip; /* not a fragment */
1024        return __net_defragment(ip, lenp);
1025}
1026
1027#else /* !CONFIG_IP_DEFRAG */
1028
1029static inline struct ip_udp_hdr *net_defragment(struct ip_udp_hdr *ip,
1030        int *lenp)
1031{
1032        u16 ip_off = ntohs(ip->ip_off);
1033        if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
1034                return ip; /* not a fragment */
1035        return NULL;
1036}
1037#endif
1038
1039/**
1040 * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
1041 * drop others.
1042 *
1043 * @parma ip    IP packet containing the ICMP
1044 */
1045static void receive_icmp(struct ip_udp_hdr *ip, int len,
1046                        struct in_addr src_ip, struct ethernet_hdr *et)
1047{
1048        struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src;
1049
1050        switch (icmph->type) {
1051        case ICMP_REDIRECT:
1052                if (icmph->code != ICMP_REDIR_HOST)
1053                        return;
1054                printf(" ICMP Host Redirect to %pI4 ",
1055                       &icmph->un.gateway);
1056                break;
1057        default:
1058#if defined(CONFIG_CMD_PING)
1059                ping_receive(et, ip, len);
1060#endif
1061#ifdef CONFIG_CMD_TFTPPUT
1062                if (packet_icmp_handler)
1063                        packet_icmp_handler(icmph->type, icmph->code,
1064                                            ntohs(ip->udp_dst), src_ip,
1065                                            ntohs(ip->udp_src), icmph->un.data,
1066                                            ntohs(ip->udp_len));
1067#endif
1068                break;
1069        }
1070}
1071
1072void net_process_received_packet(uchar *in_packet, int len)
1073{
1074        struct ethernet_hdr *et;
1075        struct ip_udp_hdr *ip;
1076        struct in_addr dst_ip;
1077        struct in_addr src_ip;
1078        int eth_proto;
1079#if defined(CONFIG_CMD_CDP)
1080        int iscdp;
1081#endif
1082        ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
1083
1084        debug_cond(DEBUG_NET_PKT, "packet received\n");
1085
1086        net_rx_packet = in_packet;
1087        net_rx_packet_len = len;
1088        et = (struct ethernet_hdr *)in_packet;
1089
1090        /* too small packet? */
1091        if (len < ETHER_HDR_SIZE)
1092                return;
1093
1094#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
1095        if (push_packet) {
1096                (*push_packet)(in_packet, len);
1097                return;
1098        }
1099#endif
1100
1101#if defined(CONFIG_CMD_CDP)
1102        /* keep track if packet is CDP */
1103        iscdp = is_cdp_packet(et->et_dest);
1104#endif
1105
1106        myvlanid = ntohs(net_our_vlan);
1107        if (myvlanid == (ushort)-1)
1108                myvlanid = VLAN_NONE;
1109        mynvlanid = ntohs(net_native_vlan);
1110        if (mynvlanid == (ushort)-1)
1111                mynvlanid = VLAN_NONE;
1112
1113        eth_proto = ntohs(et->et_protlen);
1114
1115        if (eth_proto < 1514) {
1116                struct e802_hdr *et802 = (struct e802_hdr *)et;
1117                /*
1118                 *      Got a 802.2 packet.  Check the other protocol field.
1119                 *      XXX VLAN over 802.2+SNAP not implemented!
1120                 */
1121                eth_proto = ntohs(et802->et_prot);
1122
1123                ip = (struct ip_udp_hdr *)(in_packet + E802_HDR_SIZE);
1124                len -= E802_HDR_SIZE;
1125
1126        } else if (eth_proto != PROT_VLAN) {    /* normal packet */
1127                ip = (struct ip_udp_hdr *)(in_packet + ETHER_HDR_SIZE);
1128                len -= ETHER_HDR_SIZE;
1129
1130        } else {                        /* VLAN packet */
1131                struct vlan_ethernet_hdr *vet =
1132                        (struct vlan_ethernet_hdr *)et;
1133
1134                debug_cond(DEBUG_NET_PKT, "VLAN packet received\n");
1135
1136                /* too small packet? */
1137                if (len < VLAN_ETHER_HDR_SIZE)
1138                        return;
1139
1140                /* if no VLAN active */
1141                if ((ntohs(net_our_vlan) & VLAN_IDMASK) == VLAN_NONE
1142#if defined(CONFIG_CMD_CDP)
1143                                && iscdp == 0
1144#endif
1145                                )
1146                        return;
1147
1148                cti = ntohs(vet->vet_tag);
1149                vlanid = cti & VLAN_IDMASK;
1150                eth_proto = ntohs(vet->vet_type);
1151
1152                ip = (struct ip_udp_hdr *)(in_packet + VLAN_ETHER_HDR_SIZE);
1153                len -= VLAN_ETHER_HDR_SIZE;
1154        }
1155
1156        debug_cond(DEBUG_NET_PKT, "Receive from protocol 0x%x\n", eth_proto);
1157
1158#if defined(CONFIG_CMD_CDP)
1159        if (iscdp) {
1160                cdp_receive((uchar *)ip, len);
1161                return;
1162        }
1163#endif
1164
1165        if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
1166                if (vlanid == VLAN_NONE)
1167                        vlanid = (mynvlanid & VLAN_IDMASK);
1168                /* not matched? */
1169                if (vlanid != (myvlanid & VLAN_IDMASK))
1170                        return;
1171        }
1172
1173        switch (eth_proto) {
1174        case PROT_ARP:
1175                arp_receive(et, ip, len);
1176                break;
1177
1178#ifdef CONFIG_CMD_RARP
1179        case PROT_RARP:
1180                rarp_receive(ip, len);
1181                break;
1182#endif
1183        case PROT_IP:
1184                debug_cond(DEBUG_NET_PKT, "Got IP\n");
1185                /* Before we start poking the header, make sure it is there */
1186                if (len < IP_UDP_HDR_SIZE) {
1187                        debug("len bad %d < %lu\n", len,
1188                              (ulong)IP_UDP_HDR_SIZE);
1189                        return;
1190                }
1191                /* Check the packet length */
1192                if (len < ntohs(ip->ip_len)) {
1193                        debug("len bad %d < %d\n", len, ntohs(ip->ip_len));
1194                        return;
1195                }
1196                len = ntohs(ip->ip_len);
1197                debug_cond(DEBUG_NET_PKT, "len=%d, v=%02x\n",
1198                           len, ip->ip_hl_v & 0xff);
1199
1200                /* Can't deal with anything except IPv4 */
1201                if ((ip->ip_hl_v & 0xf0) != 0x40)
1202                        return;
1203                /* Can't deal with IP options (headers != 20 bytes) */
1204                if ((ip->ip_hl_v & 0x0f) > 0x05)
1205                        return;
1206                /* Check the Checksum of the header */
1207                if (!ip_checksum_ok((uchar *)ip, IP_HDR_SIZE)) {
1208                        debug("checksum bad\n");
1209                        return;
1210                }
1211                /* If it is not for us, ignore it */
1212                dst_ip = net_read_ip(&ip->ip_dst);
1213                if (net_ip.s_addr && dst_ip.s_addr != net_ip.s_addr &&
1214                    dst_ip.s_addr != 0xFFFFFFFF) {
1215                                return;
1216                }
1217                /* Read source IP address for later use */
1218                src_ip = net_read_ip(&ip->ip_src);
1219                /*
1220                 * The function returns the unchanged packet if it's not
1221                 * a fragment, and either the complete packet or NULL if
1222                 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
1223                 */
1224                ip = net_defragment(ip, &len);
1225                if (!ip)
1226                        return;
1227                /*
1228                 * watch for ICMP host redirects
1229                 *
1230                 * There is no real handler code (yet). We just watch
1231                 * for ICMP host redirect messages. In case anybody
1232                 * sees these messages: please contact me
1233                 * (wd@denx.de), or - even better - send me the
1234                 * necessary fixes :-)
1235                 *
1236                 * Note: in all cases where I have seen this so far
1237                 * it was a problem with the router configuration,
1238                 * for instance when a router was configured in the
1239                 * BOOTP reply, but the TFTP server was on the same
1240                 * subnet. So this is probably a warning that your
1241                 * configuration might be wrong. But I'm not really
1242                 * sure if there aren't any other situations.
1243                 *
1244                 * Simon Glass <sjg@chromium.org>: We get an ICMP when
1245                 * we send a tftp packet to a dead connection, or when
1246                 * there is no server at the other end.
1247                 */
1248                if (ip->ip_p == IPPROTO_ICMP) {
1249                        receive_icmp(ip, len, src_ip, et);
1250                        return;
1251                } else if (ip->ip_p != IPPROTO_UDP) {   /* Only UDP packets */
1252                        return;
1253                }
1254
1255                debug_cond(DEBUG_DEV_PKT,
1256                           "received UDP (to=%pI4, from=%pI4, len=%d)\n",
1257                           &dst_ip, &src_ip, len);
1258
1259#ifdef CONFIG_UDP_CHECKSUM
1260                if (ip->udp_xsum != 0) {
1261                        ulong   xsum;
1262                        ushort *sumptr;
1263                        ushort  sumlen;
1264
1265                        xsum  = ip->ip_p;
1266                        xsum += (ntohs(ip->udp_len));
1267                        xsum += (ntohl(ip->ip_src.s_addr) >> 16) & 0x0000ffff;
1268                        xsum += (ntohl(ip->ip_src.s_addr) >>  0) & 0x0000ffff;
1269                        xsum += (ntohl(ip->ip_dst.s_addr) >> 16) & 0x0000ffff;
1270                        xsum += (ntohl(ip->ip_dst.s_addr) >>  0) & 0x0000ffff;
1271
1272                        sumlen = ntohs(ip->udp_len);
1273                        sumptr = (ushort *)&(ip->udp_src);
1274
1275                        while (sumlen > 1) {
1276                                ushort sumdata;
1277
1278                                sumdata = *sumptr++;
1279                                xsum += ntohs(sumdata);
1280                                sumlen -= 2;
1281                        }
1282                        if (sumlen > 0) {
1283                                ushort sumdata;
1284
1285                                sumdata = *(unsigned char *)sumptr;
1286                                sumdata = (sumdata << 8) & 0xff00;
1287                                xsum += sumdata;
1288                        }
1289                        while ((xsum >> 16) != 0) {
1290                                xsum = (xsum & 0x0000ffff) +
1291                                       ((xsum >> 16) & 0x0000ffff);
1292                        }
1293                        if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
1294                                printf(" UDP wrong checksum %08lx %08x\n",
1295                                       xsum, ntohs(ip->udp_xsum));
1296                                return;
1297                        }
1298                }
1299#endif
1300
1301#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
1302                nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE,
1303                                src_ip,
1304                                ntohs(ip->udp_dst),
1305                                ntohs(ip->udp_src),
1306                                ntohs(ip->udp_len) - UDP_HDR_SIZE);
1307#endif
1308                /*
1309                 * IP header OK.  Pass the packet to the current handler.
1310                 */
1311                (*udp_packet_handler)((uchar *)ip + IP_UDP_HDR_SIZE,
1312                                      ntohs(ip->udp_dst),
1313                                      src_ip,
1314                                      ntohs(ip->udp_src),
1315                                      ntohs(ip->udp_len) - UDP_HDR_SIZE);
1316                break;
1317#ifdef CONFIG_CMD_WOL
1318        case PROT_WOL:
1319                wol_receive(ip, len);
1320                break;
1321#endif
1322        }
1323}
1324
1325/**********************************************************************/
1326
1327static int net_check_prereq(enum proto_t protocol)
1328{
1329        switch (protocol) {
1330                /* Fall through */
1331#if defined(CONFIG_CMD_PING)
1332        case PING:
1333                if (net_ping_ip.s_addr == 0) {
1334                        puts("*** ERROR: ping address not given\n");
1335                        return 1;
1336                }
1337                goto common;
1338#endif
1339#if defined(CONFIG_CMD_SNTP)
1340        case SNTP:
1341                if (net_ntp_server.s_addr == 0) {
1342                        puts("*** ERROR: NTP server address not given\n");
1343                        return 1;
1344                }
1345                goto common;
1346#endif
1347#if defined(CONFIG_CMD_DNS)
1348        case DNS:
1349                if (net_dns_server.s_addr == 0) {
1350                        puts("*** ERROR: DNS server address not given\n");
1351                        return 1;
1352                }
1353                goto common;
1354#endif
1355#if defined(CONFIG_CMD_NFS)
1356        case NFS:
1357#endif
1358                /* Fall through */
1359        case TFTPGET:
1360        case TFTPPUT:
1361                if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) {
1362                        puts("*** ERROR: `serverip' not set\n");
1363                        return 1;
1364                }
1365#if     defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
1366        defined(CONFIG_CMD_DNS)
1367common:
1368#endif
1369                /* Fall through */
1370
1371        case NETCONS:
1372        case FASTBOOT:
1373        case TFTPSRV:
1374                if (net_ip.s_addr == 0) {
1375                        puts("*** ERROR: `ipaddr' not set\n");
1376                        return 1;
1377                }
1378                /* Fall through */
1379
1380#ifdef CONFIG_CMD_RARP
1381        case RARP:
1382#endif
1383        case BOOTP:
1384        case CDP:
1385        case DHCP:
1386        case LINKLOCAL:
1387                if (memcmp(net_ethaddr, "\0\0\0\0\0\0", 6) == 0) {
1388                        int num = eth_get_dev_index();
1389
1390                        switch (num) {
1391                        case -1:
1392                                puts("*** ERROR: No ethernet found.\n");
1393                                return 1;
1394                        case 0:
1395                                puts("*** ERROR: `ethaddr' not set\n");
1396                                break;
1397                        default:
1398                                printf("*** ERROR: `eth%daddr' not set\n",
1399                                       num);
1400                                break;
1401                        }
1402
1403                        net_start_again();
1404                        return 2;
1405                }
1406                /* Fall through */
1407        default:
1408                return 0;
1409        }
1410        return 0;               /* OK */
1411}
1412/**********************************************************************/
1413
1414int
1415net_eth_hdr_size(void)
1416{
1417        ushort myvlanid;
1418
1419        myvlanid = ntohs(net_our_vlan);
1420        if (myvlanid == (ushort)-1)
1421                myvlanid = VLAN_NONE;
1422
1423        return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE :
1424                VLAN_ETHER_HDR_SIZE;
1425}
1426
1427int net_set_ether(uchar *xet, const uchar *dest_ethaddr, uint prot)
1428{
1429        struct ethernet_hdr *et = (struct ethernet_hdr *)xet;
1430        ushort myvlanid;
1431
1432        myvlanid = ntohs(net_our_vlan);
1433        if (myvlanid == (ushort)-1)
1434                myvlanid = VLAN_NONE;
1435
1436        memcpy(et->et_dest, dest_ethaddr, 6);
1437        memcpy(et->et_src, net_ethaddr, 6);
1438        if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
1439                et->et_protlen = htons(prot);
1440                return ETHER_HDR_SIZE;
1441        } else {
1442                struct vlan_ethernet_hdr *vet =
1443                        (struct vlan_ethernet_hdr *)xet;
1444
1445                vet->vet_vlan_type = htons(PROT_VLAN);
1446                vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
1447                vet->vet_type = htons(prot);
1448                return VLAN_ETHER_HDR_SIZE;
1449        }
1450}
1451
1452int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot)
1453{
1454        ushort protlen;
1455
1456        memcpy(et->et_dest, addr, 6);
1457        memcpy(et->et_src, net_ethaddr, 6);
1458        protlen = ntohs(et->et_protlen);
1459        if (protlen == PROT_VLAN) {
1460                struct vlan_ethernet_hdr *vet =
1461                        (struct vlan_ethernet_hdr *)et;
1462                vet->vet_type = htons(prot);
1463                return VLAN_ETHER_HDR_SIZE;
1464        } else if (protlen > 1514) {
1465                et->et_protlen = htons(prot);
1466                return ETHER_HDR_SIZE;
1467        } else {
1468                /* 802.2 + SNAP */
1469                struct e802_hdr *et802 = (struct e802_hdr *)et;
1470                et802->et_prot = htons(prot);
1471                return E802_HDR_SIZE;
1472        }
1473}
1474
1475void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source,
1476                       u16 pkt_len, u8 proto)
1477{
1478        struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
1479
1480        /*
1481         *      Construct an IP header.
1482         */
1483        /* IP_HDR_SIZE / 4 (not including UDP) */
1484        ip->ip_hl_v  = 0x45;
1485        ip->ip_tos   = 0;
1486        ip->ip_len   = htons(pkt_len);
1487        ip->ip_p     = proto;
1488        ip->ip_id    = htons(net_ip_id++);
1489        ip->ip_off   = htons(IP_FLAGS_DFRAG);   /* Don't fragment */
1490        ip->ip_ttl   = 255;
1491        ip->ip_sum   = 0;
1492        /* already in network byte order */
1493        net_copy_ip((void *)&ip->ip_src, &source);
1494        /* already in network byte order */
1495        net_copy_ip((void *)&ip->ip_dst, &dest);
1496
1497        ip->ip_sum   = compute_ip_checksum(ip, IP_HDR_SIZE);
1498}
1499
1500void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport,
1501                        int len)
1502{
1503        struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;
1504
1505        /*
1506         *      If the data is an odd number of bytes, zero the
1507         *      byte after the last byte so that the checksum
1508         *      will work.
1509         */
1510        if (len & 1)
1511                pkt[IP_UDP_HDR_SIZE + len] = 0;
1512
1513        net_set_ip_header(pkt, dest, net_ip, IP_UDP_HDR_SIZE + len,
1514                          IPPROTO_UDP);
1515
1516        ip->udp_src  = htons(sport);
1517        ip->udp_dst  = htons(dport);
1518        ip->udp_len  = htons(UDP_HDR_SIZE + len);
1519        ip->udp_xsum = 0;
1520}
1521
1522void copy_filename(char *dst, const char *src, int size)
1523{
1524        if (src && *src && (*src == '"')) {
1525                ++src;
1526                --size;
1527        }
1528
1529        while ((--size > 0) && src && *src && (*src != '"'))
1530                *dst++ = *src++;
1531        *dst = '\0';
1532}
1533
1534int is_serverip_in_cmd(void)
1535{
1536        return !!strchr(net_boot_file_name, ':');
1537}
1538
1539int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len)
1540{
1541        char *colon;
1542
1543        if (net_boot_file_name[0] == '\0')
1544                return 0;
1545
1546        colon = strchr(net_boot_file_name, ':');
1547        if (colon) {
1548                if (ipaddr)
1549                        *ipaddr = string_to_ip(net_boot_file_name);
1550                strncpy(filename, colon + 1, max_len);
1551        } else {
1552                strncpy(filename, net_boot_file_name, max_len);
1553        }
1554        filename[max_len - 1] = '\0';
1555
1556        return 1;
1557}
1558
1559#if     defined(CONFIG_CMD_NFS)         || \
1560        defined(CONFIG_CMD_SNTP)        || \
1561        defined(CONFIG_CMD_DNS)
1562/*
1563 * make port a little random (1024-17407)
1564 * This keeps the math somewhat trivial to compute, and seems to work with
1565 * all supported protocols/clients/servers
1566 */
1567unsigned int random_port(void)
1568{
1569        return 1024 + (get_timer(0) % 0x4000);
1570}
1571#endif
1572
1573void ip_to_string(struct in_addr x, char *s)
1574{
1575        x.s_addr = ntohl(x.s_addr);
1576        sprintf(s, "%d.%d.%d.%d",
1577                (int) ((x.s_addr >> 24) & 0xff),
1578                (int) ((x.s_addr >> 16) & 0xff),
1579                (int) ((x.s_addr >> 8) & 0xff),
1580                (int) ((x.s_addr >> 0) & 0xff)
1581        );
1582}
1583
1584void vlan_to_string(ushort x, char *s)
1585{
1586        x = ntohs(x);
1587
1588        if (x == (ushort)-1)
1589                x = VLAN_NONE;
1590
1591        if (x == VLAN_NONE)
1592                strcpy(s, "none");
1593        else
1594                sprintf(s, "%d", x & VLAN_IDMASK);
1595}
1596
1597ushort string_to_vlan(const char *s)
1598{
1599        ushort id;
1600
1601        if (s == NULL)
1602                return htons(VLAN_NONE);
1603
1604        if (*s < '0' || *s > '9')
1605                id = VLAN_NONE;
1606        else
1607                id = (ushort)simple_strtoul(s, NULL, 10);
1608
1609        return htons(id);
1610}
1611
1612ushort env_get_vlan(char *var)
1613{
1614        return string_to_vlan(env_get(var));
1615}
1616