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