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