uboot/net/bootp.c
<<
>>
Prefs
   1/*
   2 *      Based on LiMon - BOOTP.
   3 *
   4 *      Copyright 1994, 1995, 2000 Neil Russell.
   5 *      (See License)
   6 *      Copyright 2000 Roland Borde
   7 *      Copyright 2000 Paolo Scaffardi
   8 *      Copyright 2000-2004 Wolfgang Denk, wd@denx.de
   9 */
  10
  11#include <common.h>
  12#include <bootstage.h>
  13#include <command.h>
  14#include <env.h>
  15#include <efi_loader.h>
  16#include <log.h>
  17#include <net.h>
  18#include <rand.h>
  19#include <uuid.h>
  20#include <linux/delay.h>
  21#include <net/tftp.h>
  22#include "bootp.h"
  23#ifdef CONFIG_LED_STATUS
  24#include <status_led.h>
  25#endif
  26#ifdef CONFIG_BOOTP_RANDOM_DELAY
  27#include "net_rand.h"
  28#endif
  29
  30#define BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie */
  31
  32/*
  33 * The timeout for the initial BOOTP/DHCP request used to be described by a
  34 * counter of fixed-length timeout periods. TIMEOUT_COUNT represents
  35 * that counter
  36 *
  37 * Now that the timeout periods are variable (exponential backoff and retry)
  38 * we convert the timeout count to the absolute time it would have take to
  39 * execute that many retries, and keep sending retry packets until that time
  40 * is reached.
  41 */
  42#ifndef CONFIG_NET_RETRY_COUNT
  43# define TIMEOUT_COUNT  5               /* # of timeouts before giving up */
  44#else
  45# define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
  46#endif
  47#define TIMEOUT_MS      ((3 + (TIMEOUT_COUNT * 5)) * 1000)
  48
  49#define PORT_BOOTPS     67              /* BOOTP server UDP port */
  50#define PORT_BOOTPC     68              /* BOOTP client UDP port */
  51
  52#ifndef CONFIG_DHCP_MIN_EXT_LEN         /* minimal length of extension list */
  53#define CONFIG_DHCP_MIN_EXT_LEN 64
  54#endif
  55
  56#ifndef CONFIG_BOOTP_ID_CACHE_SIZE
  57#define CONFIG_BOOTP_ID_CACHE_SIZE 4
  58#endif
  59
  60u32             bootp_ids[CONFIG_BOOTP_ID_CACHE_SIZE];
  61unsigned int    bootp_num_ids;
  62int             bootp_try;
  63ulong           bootp_start;
  64ulong           bootp_timeout;
  65char net_nis_domain[32] = {0,}; /* Our NIS domain */
  66char net_hostname[32] = {0,}; /* Our hostname */
  67char net_root_path[64] = {0,}; /* Our bootpath */
  68
  69static ulong time_taken_max;
  70
  71#if defined(CONFIG_CMD_DHCP)
  72static dhcp_state_t dhcp_state = INIT;
  73static u32 dhcp_leasetime;
  74static struct in_addr dhcp_server_ip;
  75static u8 dhcp_option_overload;
  76#define OVERLOAD_FILE 1
  77#define OVERLOAD_SNAME 2
  78static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
  79                        unsigned src, unsigned len);
  80
  81/* For Debug */
  82#if 0
  83static char *dhcpmsg2str(int type)
  84{
  85        switch (type) {
  86        case 1:  return "DHCPDISCOVER"; break;
  87        case 2:  return "DHCPOFFER";    break;
  88        case 3:  return "DHCPREQUEST";  break;
  89        case 4:  return "DHCPDECLINE";  break;
  90        case 5:  return "DHCPACK";      break;
  91        case 6:  return "DHCPNACK";     break;
  92        case 7:  return "DHCPRELEASE";  break;
  93        default: return "UNKNOWN/INVALID MSG TYPE"; break;
  94        }
  95}
  96#endif
  97#endif
  98
  99static void bootp_add_id(ulong id)
 100{
 101        if (bootp_num_ids >= ARRAY_SIZE(bootp_ids)) {
 102                size_t size = sizeof(bootp_ids) - sizeof(id);
 103
 104                memmove(bootp_ids, &bootp_ids[1], size);
 105                bootp_ids[bootp_num_ids - 1] = id;
 106        } else {
 107                bootp_ids[bootp_num_ids] = id;
 108                bootp_num_ids++;
 109        }
 110}
 111
 112static bool bootp_match_id(ulong id)
 113{
 114        unsigned int i;
 115
 116        for (i = 0; i < bootp_num_ids; i++)
 117                if (bootp_ids[i] == id)
 118                        return true;
 119
 120        return false;
 121}
 122
 123static int check_reply_packet(uchar *pkt, unsigned dest, unsigned src,
 124                              unsigned len)
 125{
 126        struct bootp_hdr *bp = (struct bootp_hdr *)pkt;
 127        int retval = 0;
 128
 129        if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
 130                retval = -1;
 131        else if (len < sizeof(struct bootp_hdr) - OPT_FIELD_SIZE)
 132                retval = -2;
 133        else if (bp->bp_op != OP_BOOTREPLY)
 134                retval = -3;
 135        else if (bp->bp_htype != HWT_ETHER)
 136                retval = -4;
 137        else if (bp->bp_hlen != HWL_ETHER)
 138                retval = -5;
 139        else if (!bootp_match_id(net_read_u32(&bp->bp_id)))
 140                retval = -6;
 141        else if (memcmp(bp->bp_chaddr, net_ethaddr, HWL_ETHER) != 0)
 142                retval = -7;
 143
 144        debug("Filtering pkt = %d\n", retval);
 145
 146        return retval;
 147}
 148
 149static void store_bootp_params(struct bootp_hdr *bp)
 150{
 151#if !defined(CONFIG_BOOTP_SERVERIP)
 152        struct in_addr tmp_ip;
 153        bool overwrite_serverip = true;
 154
 155#if defined(CONFIG_BOOTP_PREFER_SERVERIP)
 156        overwrite_serverip = false;
 157#endif
 158
 159        net_copy_ip(&tmp_ip, &bp->bp_siaddr);
 160        if (tmp_ip.s_addr != 0 && (overwrite_serverip || !net_server_ip.s_addr))
 161                net_copy_ip(&net_server_ip, &bp->bp_siaddr);
 162        memcpy(net_server_ethaddr,
 163               ((struct ethernet_hdr *)net_rx_packet)->et_src, 6);
 164        if (
 165#if defined(CONFIG_CMD_DHCP)
 166            !(dhcp_option_overload & OVERLOAD_FILE) &&
 167#endif
 168            (strlen(bp->bp_file) > 0) &&
 169            !net_boot_file_name_explicit) {
 170                copy_filename(net_boot_file_name, bp->bp_file,
 171                              sizeof(net_boot_file_name));
 172        }
 173
 174        debug("net_boot_file_name: %s\n", net_boot_file_name);
 175
 176        /* Propagate to environment:
 177         * don't delete exising entry when BOOTP / DHCP reply does
 178         * not contain a new value
 179         */
 180        if (*net_boot_file_name)
 181                env_set("bootfile", net_boot_file_name);
 182#endif
 183}
 184
 185/*
 186 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 187 */
 188static void store_net_params(struct bootp_hdr *bp)
 189{
 190#if !defined(CONFIG_SERVERIP_FROM_PROXYDHCP)
 191        store_bootp_params(bp);
 192#endif
 193        net_copy_ip(&net_ip, &bp->bp_yiaddr);
 194}
 195
 196static int truncate_sz(const char *name, int maxlen, int curlen)
 197{
 198        if (curlen >= maxlen) {
 199                printf("*** WARNING: %s is too long (%d - max: %d)"
 200                        " - truncated\n", name, curlen, maxlen);
 201                curlen = maxlen - 1;
 202        }
 203        return curlen;
 204}
 205
 206#if !defined(CONFIG_CMD_DHCP)
 207
 208static void bootp_process_vendor_field(u8 *ext)
 209{
 210        int size = *(ext + 1);
 211
 212        debug("[BOOTP] Processing extension %d... (%d bytes)\n", *ext,
 213              *(ext + 1));
 214
 215        net_boot_file_expected_size_in_blocks = 0;
 216
 217        switch (*ext) {
 218                /* Fixed length fields */
 219        case 1:                 /* Subnet mask */
 220                if (net_netmask.s_addr == 0)
 221                        net_copy_ip(&net_netmask, (struct in_addr *)(ext + 2));
 222                break;
 223        case 2:                 /* Time offset - Not yet supported */
 224                break;
 225                /* Variable length fields */
 226        case 3:                 /* Gateways list */
 227                if (net_gateway.s_addr == 0)
 228                        net_copy_ip(&net_gateway, (struct in_addr *)(ext + 2));
 229                break;
 230        case 4:                 /* Time server - Not yet supported */
 231                break;
 232        case 5:                 /* IEN-116 name server - Not yet supported */
 233                break;
 234        case 6:
 235                if (net_dns_server.s_addr == 0)
 236                        net_copy_ip(&net_dns_server,
 237                                    (struct in_addr *)(ext + 2));
 238#if defined(CONFIG_BOOTP_DNS2)
 239                if ((net_dns_server2.s_addr == 0) && (size > 4))
 240                        net_copy_ip(&net_dns_server2,
 241                                    (struct in_addr *)(ext + 2 + 4));
 242#endif
 243                break;
 244        case 7:                 /* Log server - Not yet supported */
 245                break;
 246        case 8:                 /* Cookie/Quote server - Not yet supported */
 247                break;
 248        case 9:                 /* LPR server - Not yet supported */
 249                break;
 250        case 10:                /* Impress server - Not yet supported */
 251                break;
 252        case 11:                /* RPL server - Not yet supported */
 253                break;
 254        case 12:                /* Host name */
 255                if (net_hostname[0] == 0) {
 256                        size = truncate_sz("Host Name",
 257                                sizeof(net_hostname), size);
 258                        memcpy(&net_hostname, ext + 2, size);
 259                        net_hostname[size] = 0;
 260                }
 261                break;
 262        case 13:                /* Boot file size */
 263                if (size == 2)
 264                        net_boot_file_expected_size_in_blocks =
 265                                ntohs(*(ushort *)(ext + 2));
 266                else if (size == 4)
 267                        net_boot_file_expected_size_in_blocks =
 268                                ntohl(*(ulong *)(ext + 2));
 269                break;
 270        case 14:                /* Merit dump file - Not yet supported */
 271                break;
 272        case 15:                /* Domain name - Not yet supported */
 273                break;
 274        case 16:                /* Swap server - Not yet supported */
 275                break;
 276        case 17:                /* Root path */
 277                if (net_root_path[0] == 0) {
 278                        size = truncate_sz("Root Path",
 279                                sizeof(net_root_path), size);
 280                        memcpy(&net_root_path, ext + 2, size);
 281                        net_root_path[size] = 0;
 282                }
 283                break;
 284        case 18:                /* Extension path - Not yet supported */
 285                /*
 286                 * This can be used to send the information of the
 287                 * vendor area in another file that the client can
 288                 * access via TFTP.
 289                 */
 290                break;
 291                /* IP host layer fields */
 292        case 40:                /* NIS Domain name */
 293                if (net_nis_domain[0] == 0) {
 294                        size = truncate_sz("NIS Domain Name",
 295                                sizeof(net_nis_domain), size);
 296                        memcpy(&net_nis_domain, ext + 2, size);
 297                        net_nis_domain[size] = 0;
 298                }
 299                break;
 300#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
 301        case 42:        /* NTP server IP */
 302                net_copy_ip(&net_ntp_server, (struct in_addr *)(ext + 2));
 303                break;
 304#endif
 305                /* Application layer fields */
 306        case 43:                /* Vendor specific info - Not yet supported */
 307                /*
 308                 * Binary information to exchange specific
 309                 * product information.
 310                 */
 311                break;
 312                /* Reserved (custom) fields (128..254) */
 313        }
 314}
 315
 316static void bootp_process_vendor(u8 *ext, int size)
 317{
 318        u8 *end = ext + size;
 319
 320        debug("[BOOTP] Checking extension (%d bytes)...\n", size);
 321
 322        while ((ext < end) && (*ext != 0xff)) {
 323                if (*ext == 0) {
 324                        ext++;
 325                } else {
 326                        u8 *opt = ext;
 327
 328                        ext += ext[1] + 2;
 329                        if (ext <= end)
 330                                bootp_process_vendor_field(opt);
 331                }
 332        }
 333
 334        debug("[BOOTP] Received fields:\n");
 335        if (net_netmask.s_addr)
 336                debug("net_netmask : %pI4\n", &net_netmask);
 337
 338        if (net_gateway.s_addr)
 339                debug("net_gateway      : %pI4", &net_gateway);
 340
 341        if (net_boot_file_expected_size_in_blocks)
 342                debug("net_boot_file_expected_size_in_blocks : %d\n",
 343                      net_boot_file_expected_size_in_blocks);
 344
 345        if (net_hostname[0])
 346                debug("net_hostname  : %s\n", net_hostname);
 347
 348        if (net_root_path[0])
 349                debug("net_root_path  : %s\n", net_root_path);
 350
 351        if (net_nis_domain[0])
 352                debug("net_nis_domain : %s\n", net_nis_domain);
 353
 354#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
 355        if (net_ntp_server.s_addr)
 356                debug("net_ntp_server : %pI4\n", &net_ntp_server);
 357#endif
 358}
 359
 360/*
 361 *      Handle a BOOTP received packet.
 362 */
 363static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
 364                          unsigned src, unsigned len)
 365{
 366        struct bootp_hdr *bp;
 367
 368        debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n",
 369              src, dest, len, sizeof(struct bootp_hdr));
 370
 371        bp = (struct bootp_hdr *)pkt;
 372
 373        /* Filter out pkts we don't want */
 374        if (check_reply_packet(pkt, dest, src, len))
 375                return;
 376
 377        /*
 378         *      Got a good BOOTP reply.  Copy the data into our variables.
 379         */
 380#if defined(CONFIG_LED_STATUS) && defined(CONFIG_LED_STATUS_BOOT_ENABLE)
 381        status_led_set(CONFIG_LED_STATUS_BOOT, CONFIG_LED_STATUS_OFF);
 382#endif
 383
 384        store_net_params(bp);           /* Store net parameters from reply */
 385
 386        /* Retrieve extended information (we must parse the vendor area) */
 387        if (net_read_u32((u32 *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
 388                bootp_process_vendor((uchar *)&bp->bp_vend[4], len);
 389
 390        net_set_timeout_handler(0, (thand_f *)0);
 391        bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop");
 392
 393        debug("Got good BOOTP\n");
 394
 395        net_auto_load();
 396}
 397#endif
 398
 399/*
 400 *      Timeout on BOOTP/DHCP request.
 401 */
 402static void bootp_timeout_handler(void)
 403{
 404        ulong time_taken = get_timer(bootp_start);
 405
 406        if (time_taken >= time_taken_max) {
 407#ifdef CONFIG_BOOTP_MAY_FAIL
 408                char *ethrotate;
 409
 410                ethrotate = env_get("ethrotate");
 411                if ((ethrotate && strcmp(ethrotate, "no") == 0) ||
 412                    net_restart_wrap) {
 413                        puts("\nRetry time exceeded\n");
 414                        net_set_state(NETLOOP_FAIL);
 415                } else
 416#endif
 417                {
 418                        puts("\nRetry time exceeded; starting again\n");
 419                        net_start_again();
 420                }
 421        } else {
 422                bootp_timeout *= 2;
 423                if (bootp_timeout > 2000)
 424                        bootp_timeout = 2000;
 425                net_set_timeout_handler(bootp_timeout, bootp_timeout_handler);
 426                bootp_request();
 427        }
 428}
 429
 430#define put_vci(e, str)                                         \
 431        do {                                                    \
 432                size_t vci_strlen = strlen(str);                \
 433                *e++ = 60;      /* Vendor Class Identifier */   \
 434                *e++ = vci_strlen;                              \
 435                memcpy(e, str, vci_strlen);                     \
 436                e += vci_strlen;                                \
 437        } while (0)
 438
 439static u8 *add_vci(u8 *e)
 440{
 441        char *vci = NULL;
 442        char *env_vci = env_get("bootp_vci");
 443
 444#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING)
 445        vci = CONFIG_SPL_NET_VCI_STRING;
 446#elif defined(CONFIG_BOOTP_VCI_STRING)
 447        vci = CONFIG_BOOTP_VCI_STRING;
 448#endif
 449
 450        if (env_vci)
 451                vci = env_vci;
 452
 453        if (vci)
 454                put_vci(e, vci);
 455
 456        return e;
 457}
 458
 459/*
 460 *      Initialize BOOTP extension fields in the request.
 461 */
 462#if defined(CONFIG_CMD_DHCP)
 463static int dhcp_extended(u8 *e, int message_type, struct in_addr server_ip,
 464                        struct in_addr requested_ip)
 465{
 466        u8 *start = e;
 467        u8 *cnt;
 468#ifdef CONFIG_LIB_UUID
 469        char *uuid;
 470#endif
 471        int clientarch = -1;
 472
 473#if defined(CONFIG_BOOTP_VENDOREX)
 474        u8 *x;
 475#endif
 476#if defined(CONFIG_BOOTP_SEND_HOSTNAME)
 477        char *hostname;
 478#endif
 479
 480        *e++ = 99;              /* RFC1048 Magic Cookie */
 481        *e++ = 130;
 482        *e++ = 83;
 483        *e++ = 99;
 484
 485        *e++ = 53;              /* DHCP Message Type */
 486        *e++ = 1;
 487        *e++ = message_type;
 488
 489        *e++ = 57;              /* Maximum DHCP Message Size */
 490        *e++ = 2;
 491        *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 8;
 492        *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
 493
 494        if (server_ip.s_addr) {
 495                int tmp = ntohl(server_ip.s_addr);
 496
 497                *e++ = 54;      /* ServerID */
 498                *e++ = 4;
 499                *e++ = tmp >> 24;
 500                *e++ = tmp >> 16;
 501                *e++ = tmp >> 8;
 502                *e++ = tmp & 0xff;
 503        }
 504
 505        if (requested_ip.s_addr) {
 506                int tmp = ntohl(requested_ip.s_addr);
 507
 508                *e++ = 50;      /* Requested IP */
 509                *e++ = 4;
 510                *e++ = tmp >> 24;
 511                *e++ = tmp >> 16;
 512                *e++ = tmp >> 8;
 513                *e++ = tmp & 0xff;
 514        }
 515#if defined(CONFIG_BOOTP_SEND_HOSTNAME)
 516        hostname = env_get("hostname");
 517        if (hostname) {
 518                int hostnamelen = strlen(hostname);
 519
 520                *e++ = 12;      /* Hostname */
 521                *e++ = hostnamelen;
 522                memcpy(e, hostname, hostnamelen);
 523                e += hostnamelen;
 524        }
 525#endif
 526
 527#ifdef CONFIG_BOOTP_PXE_CLIENTARCH
 528        clientarch = CONFIG_BOOTP_PXE_CLIENTARCH;
 529#endif
 530
 531        if (env_get("bootp_arch"))
 532                clientarch = env_get_ulong("bootp_arch", 16, clientarch);
 533
 534        if (clientarch > 0) {
 535                *e++ = 93;      /* Client System Architecture */
 536                *e++ = 2;
 537                *e++ = (clientarch >> 8) & 0xff;
 538                *e++ = clientarch & 0xff;
 539        }
 540
 541        *e++ = 94;      /* Client Network Interface Identifier */
 542        *e++ = 3;
 543        *e++ = 1;       /* type field for UNDI */
 544        *e++ = 0;       /* major revision */
 545        *e++ = 0;       /* minor revision */
 546
 547#ifdef CONFIG_LIB_UUID
 548        uuid = env_get("pxeuuid");
 549
 550        if (uuid) {
 551                if (uuid_str_valid(uuid)) {
 552                        *e++ = 97;      /* Client Machine Identifier */
 553                        *e++ = 17;
 554                        *e++ = 0;       /* type 0 - UUID */
 555
 556                        uuid_str_to_bin(uuid, e, UUID_STR_FORMAT_STD);
 557                        e += 16;
 558                } else {
 559                        printf("Invalid pxeuuid: %s\n", uuid);
 560                }
 561        }
 562#endif
 563
 564        e = add_vci(e);
 565
 566#if defined(CONFIG_BOOTP_VENDOREX)
 567        x = dhcp_vendorex_prep(e);
 568        if (x)
 569                return x - start;
 570#endif
 571
 572        *e++ = 55;              /* Parameter Request List */
 573         cnt = e++;             /* Pointer to count of requested items */
 574        *cnt = 0;
 575#if defined(CONFIG_BOOTP_SUBNETMASK)
 576        *e++  = 1;              /* Subnet Mask */
 577        *cnt += 1;
 578#endif
 579#if defined(CONFIG_BOOTP_TIMEOFFSET)
 580        *e++  = 2;
 581        *cnt += 1;
 582#endif
 583#if defined(CONFIG_BOOTP_GATEWAY)
 584        *e++  = 3;              /* Router Option */
 585        *cnt += 1;
 586#endif
 587#if defined(CONFIG_BOOTP_DNS)
 588        *e++  = 6;              /* DNS Server(s) */
 589        *cnt += 1;
 590#endif
 591#if defined(CONFIG_BOOTP_HOSTNAME)
 592        *e++  = 12;             /* Hostname */
 593        *cnt += 1;
 594#endif
 595#if defined(CONFIG_BOOTP_BOOTFILESIZE)
 596        *e++  = 13;             /* Boot File Size */
 597        *cnt += 1;
 598#endif
 599#if defined(CONFIG_BOOTP_BOOTPATH)
 600        *e++  = 17;             /* Boot path */
 601        *cnt += 1;
 602#endif
 603#if defined(CONFIG_BOOTP_NISDOMAIN)
 604        *e++  = 40;             /* NIS Domain name request */
 605        *cnt += 1;
 606#endif
 607#if defined(CONFIG_BOOTP_NTPSERVER)
 608        *e++  = 42;
 609        *cnt += 1;
 610#endif
 611        /* no options, so back up to avoid sending an empty request list */
 612        if (*cnt == 0)
 613                e -= 2;
 614
 615        *e++  = 255;            /* End of the list */
 616
 617        /* Pad to minimal length */
 618#ifdef  CONFIG_DHCP_MIN_EXT_LEN
 619        while ((e - start) < CONFIG_DHCP_MIN_EXT_LEN)
 620                *e++ = 0;
 621#endif
 622
 623        return e - start;
 624}
 625
 626#else
 627/*
 628 * Warning: no field size check - change CONFIG_BOOTP_* at your own risk!
 629 */
 630static int bootp_extended(u8 *e)
 631{
 632        u8 *start = e;
 633
 634        *e++ = 99;              /* RFC1048 Magic Cookie */
 635        *e++ = 130;
 636        *e++ = 83;
 637        *e++ = 99;
 638
 639#if defined(CONFIG_CMD_DHCP)
 640        *e++ = 53;              /* DHCP Message Type */
 641        *e++ = 1;
 642        *e++ = DHCP_DISCOVER;
 643
 644        *e++ = 57;              /* Maximum DHCP Message Size */
 645        *e++ = 2;
 646        *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 16;
 647        *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
 648#endif
 649
 650        add_vci(e);
 651
 652#if defined(CONFIG_BOOTP_SUBNETMASK)
 653        *e++ = 1;               /* Subnet mask request */
 654        *e++ = 4;
 655        e   += 4;
 656#endif
 657
 658#if defined(CONFIG_BOOTP_GATEWAY)
 659        *e++ = 3;               /* Default gateway request */
 660        *e++ = 4;
 661        e   += 4;
 662#endif
 663
 664#if defined(CONFIG_BOOTP_DNS)
 665        *e++ = 6;               /* Domain Name Server */
 666        *e++ = 4;
 667        e   += 4;
 668#endif
 669
 670#if defined(CONFIG_BOOTP_HOSTNAME)
 671        *e++ = 12;              /* Host name request */
 672        *e++ = 32;
 673        e   += 32;
 674#endif
 675
 676#if defined(CONFIG_BOOTP_BOOTFILESIZE)
 677        *e++ = 13;              /* Boot file size */
 678        *e++ = 2;
 679        e   += 2;
 680#endif
 681
 682#if defined(CONFIG_BOOTP_BOOTPATH)
 683        *e++ = 17;              /* Boot path */
 684        *e++ = 32;
 685        e   += 32;
 686#endif
 687
 688#if defined(CONFIG_BOOTP_NISDOMAIN)
 689        *e++ = 40;              /* NIS Domain name request */
 690        *e++ = 32;
 691        e   += 32;
 692#endif
 693#if defined(CONFIG_BOOTP_NTPSERVER)
 694        *e++ = 42;
 695        *e++ = 4;
 696        e   += 4;
 697#endif
 698
 699        *e++ = 255;             /* End of the list */
 700
 701        /*
 702         * If nothing in list, remove it altogether. Some DHCP servers get
 703         * upset by this minor faux pas and do not respond at all.
 704         */
 705        if (e == start + 3) {
 706                printf("*** Warning: no DHCP options requested\n");
 707                e -= 3;
 708        }
 709
 710        return e - start;
 711}
 712#endif
 713
 714void bootp_reset(void)
 715{
 716        bootp_num_ids = 0;
 717        bootp_try = 0;
 718        bootp_start = get_timer(0);
 719        bootp_timeout = 250;
 720}
 721
 722void bootp_request(void)
 723{
 724        uchar *pkt, *iphdr;
 725        struct bootp_hdr *bp;
 726        int extlen, pktlen, iplen;
 727        int eth_hdr_size;
 728#ifdef CONFIG_BOOTP_RANDOM_DELAY
 729        ulong rand_ms;
 730#endif
 731        u32 bootp_id;
 732        struct in_addr zero_ip;
 733        struct in_addr bcast_ip;
 734        char *ep;  /* Environment pointer */
 735
 736        bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start");
 737#if defined(CONFIG_CMD_DHCP)
 738        dhcp_state = INIT;
 739#endif
 740
 741        ep = env_get("bootpretryperiod");
 742        if (ep != NULL)
 743                time_taken_max = dectoul(ep, NULL);
 744        else
 745                time_taken_max = TIMEOUT_MS;
 746
 747#ifdef CONFIG_BOOTP_RANDOM_DELAY                /* Random BOOTP delay */
 748        if (bootp_try == 0)
 749                srand_mac();
 750
 751        if (bootp_try <= 2)     /* Start with max 1024 * 1ms */
 752                rand_ms = rand() >> (22 - bootp_try);
 753        else            /* After 3rd BOOTP request max 8192 * 1ms */
 754                rand_ms = rand() >> 19;
 755
 756        printf("Random delay: %ld ms...\n", rand_ms);
 757        mdelay(rand_ms);
 758
 759#endif  /* CONFIG_BOOTP_RANDOM_DELAY */
 760
 761        printf("BOOTP broadcast %d\n", ++bootp_try);
 762        pkt = net_tx_packet;
 763        memset((void *)pkt, 0, PKTSIZE);
 764
 765        eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_IP);
 766        pkt += eth_hdr_size;
 767
 768        /*
 769         * Next line results in incorrect packet size being transmitted,
 770         * resulting in errors in some DHCP servers, reporting missing bytes.
 771         * Size must be set in packet header after extension length has been
 772         * determined.
 773         * C. Hallinan, DS4.COM, Inc.
 774         */
 775        /* net_set_udp_header(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC,
 776                sizeof (struct bootp_hdr)); */
 777        iphdr = pkt;    /* We need this later for net_set_udp_header() */
 778        pkt += IP_UDP_HDR_SIZE;
 779
 780        bp = (struct bootp_hdr *)pkt;
 781        bp->bp_op = OP_BOOTREQUEST;
 782        bp->bp_htype = HWT_ETHER;
 783        bp->bp_hlen = HWL_ETHER;
 784        bp->bp_hops = 0;
 785        /*
 786         * according to RFC1542, should be 0 on first request, secs since
 787         * first request otherwise
 788         */
 789        bp->bp_secs = htons(get_timer(bootp_start) / 1000);
 790        zero_ip.s_addr = 0;
 791        net_write_ip(&bp->bp_ciaddr, zero_ip);
 792        net_write_ip(&bp->bp_yiaddr, zero_ip);
 793        net_write_ip(&bp->bp_siaddr, zero_ip);
 794        net_write_ip(&bp->bp_giaddr, zero_ip);
 795        memcpy(bp->bp_chaddr, net_ethaddr, 6);
 796        copy_filename(bp->bp_file, net_boot_file_name, sizeof(bp->bp_file));
 797
 798        /* Request additional information from the BOOTP/DHCP server */
 799#if defined(CONFIG_CMD_DHCP)
 800        extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, zero_ip,
 801                               zero_ip);
 802#else
 803        extlen = bootp_extended((u8 *)bp->bp_vend);
 804#endif
 805
 806        /*
 807         *      Bootp ID is the lower 4 bytes of our ethernet address
 808         *      plus the current time in ms.
 809         */
 810        bootp_id = ((u32)net_ethaddr[2] << 24)
 811                | ((u32)net_ethaddr[3] << 16)
 812                | ((u32)net_ethaddr[4] << 8)
 813                | (u32)net_ethaddr[5];
 814        bootp_id += get_timer(0);
 815        bootp_id = htonl(bootp_id);
 816        bootp_add_id(bootp_id);
 817        net_copy_u32(&bp->bp_id, &bootp_id);
 818
 819        /*
 820         * Calculate proper packet lengths taking into account the
 821         * variable size of the options field
 822         */
 823        iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
 824        pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
 825        bcast_ip.s_addr = 0xFFFFFFFFL;
 826        net_set_udp_header(iphdr, bcast_ip, PORT_BOOTPS, PORT_BOOTPC, iplen);
 827        net_set_timeout_handler(bootp_timeout, bootp_timeout_handler);
 828
 829#if defined(CONFIG_CMD_DHCP)
 830        dhcp_state = SELECTING;
 831        net_set_udp_handler(dhcp_handler);
 832#else
 833        net_set_udp_handler(bootp_handler);
 834#endif
 835        net_send_packet(net_tx_packet, pktlen);
 836}
 837
 838#if defined(CONFIG_CMD_DHCP)
 839static void dhcp_process_options(uchar *popt, uchar *end)
 840{
 841        int oplen, size;
 842#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
 843        int *to_ptr;
 844#endif
 845
 846        while (popt < end && *popt != 0xff) {
 847                oplen = *(popt + 1);
 848                switch (*popt) {
 849                case 0:
 850                        oplen = -1; /* Pad omits len byte */
 851                        break;
 852                case 1:
 853                        net_copy_ip(&net_netmask, (popt + 2));
 854                        break;
 855#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
 856                case 2:         /* Time offset  */
 857                        to_ptr = &net_ntp_time_offset;
 858                        net_copy_u32((u32 *)to_ptr, (u32 *)(popt + 2));
 859                        net_ntp_time_offset = ntohl(net_ntp_time_offset);
 860                        break;
 861#endif
 862                case 3:
 863                        net_copy_ip(&net_gateway, (popt + 2));
 864                        break;
 865                case 6:
 866                        net_copy_ip(&net_dns_server, (popt + 2));
 867#if defined(CONFIG_BOOTP_DNS2)
 868                        if (*(popt + 1) > 4)
 869                                net_copy_ip(&net_dns_server2, (popt + 2 + 4));
 870#endif
 871                        break;
 872                case 12:
 873                        size = truncate_sz("Host Name",
 874                                sizeof(net_hostname), oplen);
 875                        memcpy(&net_hostname, popt + 2, size);
 876                        net_hostname[size] = 0;
 877                        break;
 878                case 15:        /* Ignore Domain Name Option */
 879                        break;
 880                case 17:
 881                        size = truncate_sz("Root Path",
 882                                sizeof(net_root_path), oplen);
 883                        memcpy(&net_root_path, popt + 2, size);
 884                        net_root_path[size] = 0;
 885                        break;
 886                case 28:        /* Ignore Broadcast Address Option */
 887                        break;
 888#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
 889                case 42:        /* NTP server IP */
 890                        net_copy_ip(&net_ntp_server, (popt + 2));
 891                        break;
 892#endif
 893                case 51:
 894                        net_copy_u32(&dhcp_leasetime, (u32 *)(popt + 2));
 895                        break;
 896                case 52:
 897                        dhcp_option_overload = popt[2];
 898                        break;
 899                case 53:        /* Ignore Message Type Option */
 900                        break;
 901                case 54:
 902                        net_copy_ip(&dhcp_server_ip, (popt + 2));
 903                        break;
 904                case 58:        /* Ignore Renewal Time Option */
 905                        break;
 906                case 59:        /* Ignore Rebinding Time Option */
 907                        break;
 908                case 66:        /* Ignore TFTP server name */
 909                        break;
 910                case 67:        /* Bootfile option */
 911                        if (!net_boot_file_name_explicit) {
 912                                size = truncate_sz("Bootfile",
 913                                                   sizeof(net_boot_file_name),
 914                                                   oplen);
 915                                memcpy(&net_boot_file_name, popt + 2, size);
 916                                net_boot_file_name[size] = 0;
 917                        }
 918                        break;
 919                default:
 920#if defined(CONFIG_BOOTP_VENDOREX)
 921                        if (dhcp_vendorex_proc(popt))
 922                                break;
 923#endif
 924                        printf("*** Unhandled DHCP Option in OFFER/ACK:"
 925                               " %d\n", *popt);
 926                        break;
 927                }
 928                popt += oplen + 2;      /* Process next option */
 929        }
 930}
 931
 932static void dhcp_packet_process_options(struct bootp_hdr *bp)
 933{
 934        uchar *popt = (uchar *)&bp->bp_vend[4];
 935        uchar *end = popt + BOOTP_HDR_SIZE;
 936
 937        if (net_read_u32((u32 *)&bp->bp_vend[0]) != htonl(BOOTP_VENDOR_MAGIC))
 938                return;
 939
 940        dhcp_option_overload = 0;
 941
 942        /*
 943         * The 'options' field MUST be interpreted first, 'file' next,
 944         * 'sname' last.
 945         */
 946        dhcp_process_options(popt, end);
 947
 948        if (dhcp_option_overload & OVERLOAD_FILE) {
 949                popt = (uchar *)bp->bp_file;
 950                end = popt + sizeof(bp->bp_file);
 951                dhcp_process_options(popt, end);
 952        }
 953
 954        if (dhcp_option_overload & OVERLOAD_SNAME) {
 955                popt = (uchar *)bp->bp_sname;
 956                end = popt + sizeof(bp->bp_sname);
 957                dhcp_process_options(popt, end);
 958        }
 959}
 960
 961static int dhcp_message_type(unsigned char *popt)
 962{
 963        if (net_read_u32((u32 *)popt) != htonl(BOOTP_VENDOR_MAGIC))
 964                return -1;
 965
 966        popt += 4;
 967        while (*popt != 0xff) {
 968                if (*popt == 53)        /* DHCP Message Type */
 969                        return *(popt + 2);
 970                if (*popt == 0) {
 971                        /* Pad */
 972                        popt += 1;
 973                } else {
 974                        /* Scan through all options */
 975                        popt += *(popt + 1) + 2;
 976                }
 977        }
 978        return -1;
 979}
 980
 981static void dhcp_send_request_packet(struct bootp_hdr *bp_offer)
 982{
 983        uchar *pkt, *iphdr;
 984        struct bootp_hdr *bp;
 985        int pktlen, iplen, extlen;
 986        int eth_hdr_size;
 987        struct in_addr offered_ip;
 988        struct in_addr zero_ip;
 989        struct in_addr bcast_ip;
 990
 991        debug("dhcp_send_request_packet: Sending DHCPREQUEST\n");
 992        pkt = net_tx_packet;
 993        memset((void *)pkt, 0, PKTSIZE);
 994
 995        eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_IP);
 996        pkt += eth_hdr_size;
 997
 998        iphdr = pkt;    /* We'll need this later to set proper pkt size */
 999        pkt += IP_UDP_HDR_SIZE;
1000
1001        bp = (struct bootp_hdr *)pkt;
1002        bp->bp_op = OP_BOOTREQUEST;
1003        bp->bp_htype = HWT_ETHER;
1004        bp->bp_hlen = HWL_ETHER;
1005        bp->bp_hops = 0;
1006        bp->bp_secs = htons(get_timer(bootp_start) / 1000);
1007        /* Do not set the client IP, your IP, or server IP yet, since it
1008         * hasn't been ACK'ed by the server yet */
1009
1010        /*
1011         * RFC3046 requires Relay Agents to discard packets with
1012         * nonzero and offered giaddr
1013         */
1014        zero_ip.s_addr = 0;
1015        net_write_ip(&bp->bp_giaddr, zero_ip);
1016
1017        memcpy(bp->bp_chaddr, net_ethaddr, 6);
1018        copy_filename(bp->bp_file, net_boot_file_name, sizeof(bp->bp_file));
1019
1020        /*
1021         * ID is the id of the OFFER packet
1022         */
1023
1024        net_copy_u32(&bp->bp_id, &bp_offer->bp_id);
1025
1026        /*
1027         * Copy options from OFFER packet if present
1028         */
1029
1030        /* Copy offered IP into the parameters request list */
1031        net_copy_ip(&offered_ip, &bp_offer->bp_yiaddr);
1032        extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST,
1033                dhcp_server_ip, offered_ip);
1034
1035        iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
1036        pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
1037        bcast_ip.s_addr = 0xFFFFFFFFL;
1038        net_set_udp_header(iphdr, bcast_ip, PORT_BOOTPS, PORT_BOOTPC, iplen);
1039
1040#ifdef CONFIG_BOOTP_DHCP_REQUEST_DELAY
1041        udelay(CONFIG_BOOTP_DHCP_REQUEST_DELAY);
1042#endif  /* CONFIG_BOOTP_DHCP_REQUEST_DELAY */
1043        debug("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
1044        net_send_packet(net_tx_packet, pktlen);
1045}
1046
1047/*
1048 *      Handle DHCP received packets.
1049 */
1050static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
1051                         unsigned src, unsigned len)
1052{
1053        struct bootp_hdr *bp = (struct bootp_hdr *)pkt;
1054
1055        debug("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
1056              src, dest, len, dhcp_state);
1057
1058        /* Filter out pkts we don't want */
1059        if (check_reply_packet(pkt, dest, src, len))
1060                return;
1061
1062        debug("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: "
1063              "%d\n", src, dest, len, dhcp_state);
1064
1065        if (net_read_ip(&bp->bp_yiaddr).s_addr == 0) {
1066#if defined(CONFIG_SERVERIP_FROM_PROXYDHCP)
1067                store_bootp_params(bp);
1068#endif
1069                return;
1070        }
1071
1072        switch (dhcp_state) {
1073        case SELECTING:
1074                /*
1075                 * Wait an appropriate time for any potential DHCPOFFER packets
1076                 * to arrive.  Then select one, and generate DHCPREQUEST
1077                 * response.  If filename is in format we recognize, assume it
1078                 * is a valid OFFER from a server we want.
1079                 */
1080                debug("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
1081#ifdef CONFIG_SYS_BOOTFILE_PREFIX
1082                if (strncmp(bp->bp_file,
1083                            CONFIG_SYS_BOOTFILE_PREFIX,
1084                            strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) {
1085#endif  /* CONFIG_SYS_BOOTFILE_PREFIX */
1086                        dhcp_packet_process_options(bp);
1087                        efi_net_set_dhcp_ack(pkt, len);
1088
1089#if defined(CONFIG_SERVERIP_FROM_PROXYDHCP)
1090                        if (!net_server_ip.s_addr)
1091                                udelay(CONFIG_SERVERIP_FROM_PROXYDHCP_DELAY_MS *
1092                                        1000);
1093#endif  /* CONFIG_SERVERIP_FROM_PROXYDHCP */
1094
1095                        debug("TRANSITIONING TO REQUESTING STATE\n");
1096                        dhcp_state = REQUESTING;
1097
1098                        net_set_timeout_handler(5000, bootp_timeout_handler);
1099                        dhcp_send_request_packet(bp);
1100#ifdef CONFIG_SYS_BOOTFILE_PREFIX
1101                }
1102#endif  /* CONFIG_SYS_BOOTFILE_PREFIX */
1103
1104                return;
1105                break;
1106        case REQUESTING:
1107                debug("DHCP State: REQUESTING\n");
1108
1109                if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) {
1110                        dhcp_packet_process_options(bp);
1111                        /* Store net params from reply */
1112                        store_net_params(bp);
1113                        dhcp_state = BOUND;
1114                        printf("DHCP client bound to address %pI4 (%lu ms)\n",
1115                               &net_ip, get_timer(bootp_start));
1116                        net_set_timeout_handler(0, (thand_f *)0);
1117                        bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP,
1118                                            "bootp_stop");
1119
1120                        net_auto_load();
1121                        return;
1122                }
1123                break;
1124        case BOUND:
1125                /* DHCP client bound to address */
1126                break;
1127        default:
1128                puts("DHCP: INVALID STATE\n");
1129                break;
1130        }
1131}
1132
1133void dhcp_request(void)
1134{
1135        bootp_request();
1136}
1137#endif  /* CONFIG_CMD_DHCP */
1138