busybox/networking/udhcp/dhcpc.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * udhcp client
   4 * Russ Dill <Russ.Dill@asu.edu> July 2001
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20//applet:IF_UDHCPC(APPLET(udhcpc, BB_DIR_SBIN, BB_SUID_DROP))
  21
  22//kbuild:lib-$(CONFIG_UDHCPC) += common.o packet.o signalpipe.o socket.o
  23//kbuild:lib-$(CONFIG_UDHCPC) += dhcpc.o
  24//kbuild:lib-$(CONFIG_FEATURE_UDHCPC_ARPING) += arpping.o
  25//kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o
  26
  27#include <syslog.h>
  28/* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */
  29#define WANT_PIDFILE 1
  30#include "common.h"
  31#include "dhcpd.h"
  32#include "dhcpc.h"
  33
  34#include <netinet/if_ether.h>
  35#include <linux/filter.h>
  36#include <linux/if_packet.h>
  37
  38#ifndef PACKET_AUXDATA
  39# define PACKET_AUXDATA 8
  40struct tpacket_auxdata {
  41        uint32_t tp_status;
  42        uint32_t tp_len;
  43        uint32_t tp_snaplen;
  44        uint16_t tp_mac;
  45        uint16_t tp_net;
  46        uint16_t tp_vlan_tci;
  47        uint16_t tp_padding;
  48};
  49#endif
  50
  51
  52/* "struct client_config_t client_config" is in bb_common_bufsiz1 */
  53
  54
  55#if ENABLE_LONG_OPTS
  56static const char udhcpc_longopts[] ALIGN1 =
  57        "clientid-none\0"  No_argument       "C"
  58        "vendorclass\0"    Required_argument "V"
  59        "hostname\0"       Required_argument "H"
  60        "fqdn\0"           Required_argument "F"
  61        "interface\0"      Required_argument "i"
  62        "now\0"            No_argument       "n"
  63        "pidfile\0"        Required_argument "p"
  64        "quit\0"           No_argument       "q"
  65        "release\0"        No_argument       "R"
  66        "request\0"        Required_argument "r"
  67        "script\0"         Required_argument "s"
  68        "timeout\0"        Required_argument "T"
  69        "retries\0"        Required_argument "t"
  70        "tryagain\0"       Required_argument "A"
  71        "syslog\0"         No_argument       "S"
  72        "request-option\0" Required_argument "O"
  73        "no-default-options\0" No_argument   "o"
  74        "foreground\0"     No_argument       "f"
  75        USE_FOR_MMU(
  76        "background\0"     No_argument       "b"
  77        )
  78        "broadcast\0"      No_argument       "B"
  79        IF_FEATURE_UDHCPC_ARPING("arping\0"     Optional_argument "a")
  80        IF_FEATURE_UDHCP_PORT("client-port\0"   Required_argument "P")
  81        ;
  82#endif
  83/* Must match getopt32 option string order */
  84enum {
  85        OPT_C = 1 << 0,
  86        OPT_V = 1 << 1,
  87        OPT_H = 1 << 2,
  88        OPT_h = 1 << 3,
  89        OPT_F = 1 << 4,
  90        OPT_i = 1 << 5,
  91        OPT_n = 1 << 6,
  92        OPT_p = 1 << 7,
  93        OPT_q = 1 << 8,
  94        OPT_R = 1 << 9,
  95        OPT_r = 1 << 10,
  96        OPT_s = 1 << 11,
  97        OPT_T = 1 << 12,
  98        OPT_t = 1 << 13,
  99        OPT_S = 1 << 14,
 100        OPT_A = 1 << 15,
 101        OPT_O = 1 << 16,
 102        OPT_o = 1 << 17,
 103        OPT_x = 1 << 18,
 104        OPT_f = 1 << 19,
 105        OPT_B = 1 << 20,
 106/* The rest has variable bit positions, need to be clever */
 107        OPTBIT_B = 20,
 108        USE_FOR_MMU(             OPTBIT_b,)
 109        IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
 110        IF_FEATURE_UDHCP_PORT(   OPTBIT_P,)
 111        USE_FOR_MMU(             OPT_b = 1 << OPTBIT_b,)
 112        IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
 113        IF_FEATURE_UDHCP_PORT(   OPT_P = 1 << OPTBIT_P,)
 114};
 115
 116
 117/*** Script execution code ***/
 118
 119/* get a rough idea of how long an option will be (rounding up...) */
 120static const uint8_t len_of_option_as_string[] ALIGN1 = {
 121        [OPTION_IP              ] = sizeof("255.255.255.255 "),
 122        [OPTION_IP_PAIR         ] = sizeof("255.255.255.255 ") * 2,
 123        [OPTION_STATIC_ROUTES   ] = sizeof("255.255.255.255/32 255.255.255.255 "),
 124        [OPTION_6RD             ] = sizeof("132 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
 125        [OPTION_STRING          ] = 1,
 126        [OPTION_STRING_HOST     ] = 1,
 127#if ENABLE_FEATURE_UDHCP_RFC3397
 128        [OPTION_DNS_STRING      ] = 1, /* unused */
 129        /* Hmmm, this severely overestimates size if SIP_SERVERS option
 130         * is in domain name form: N-byte option in binary form
 131         * mallocs ~16*N bytes. But it is freed almost at once.
 132         */
 133        [OPTION_SIP_SERVERS     ] = sizeof("255.255.255.255 "),
 134#endif
 135//      [OPTION_BOOLEAN         ] = sizeof("yes "),
 136        [OPTION_U8              ] = sizeof("255 "),
 137        [OPTION_U16             ] = sizeof("65535 "),
 138//      [OPTION_S16             ] = sizeof("-32768 "),
 139        [OPTION_U32             ] = sizeof("4294967295 "),
 140        [OPTION_S32             ] = sizeof("-2147483684 "),
 141};
 142
 143/* note: ip is a pointer to an IP in network order, possibly misaliged */
 144static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
 145{
 146        return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
 147}
 148
 149/* really simple implementation, just count the bits */
 150static int mton(uint32_t mask)
 151{
 152        int i = 0;
 153        mask = ntohl(mask); /* 111110000-like bit pattern */
 154        while (mask) {
 155                i++;
 156                mask <<= 1;
 157        }
 158        return i;
 159}
 160
 161#if ENABLE_FEATURE_UDHCPC_SANITIZEOPT
 162/* Check if a given label represents a valid DNS label
 163 * Return pointer to the first character after the label upon success,
 164 * NULL otherwise.
 165 * See RFC1035, 2.3.1
 166 */
 167/* We don't need to be particularly anal. For example, allowing _, hyphen
 168 * at the end, or leading and trailing dots would be ok, since it
 169 * can't be used for attacks. (Leading hyphen can be, if someone uses
 170 * cmd "$hostname"
 171 * in the script: then hostname may be treated as an option)
 172 */
 173static const char *valid_domain_label(const char *label)
 174{
 175        unsigned char ch;
 176        unsigned pos = 0;
 177
 178        for (;;) {
 179                ch = *label;
 180                if ((ch|0x20) < 'a' || (ch|0x20) > 'z') {
 181                        if (ch < '0' || ch > '9') {
 182                                if (ch == '\0' || ch == '.')
 183                                        return label;
 184                                /* DNS allows only '-', but we are more permissive */
 185                                if (ch != '-' && ch != '_')
 186                                        return NULL;
 187                        }
 188                }
 189                label++;
 190                pos++;
 191                //Do we want this?
 192                //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */
 193                //      return NULL;
 194        }
 195}
 196
 197/* Check if a given name represents a valid DNS name */
 198/* See RFC1035, 2.3.1 */
 199static int good_hostname(const char *name)
 200{
 201        //const char *start = name;
 202
 203        for (;;) {
 204                name = valid_domain_label(name);
 205                if (!name)
 206                        return 0;
 207                if (!name[0])
 208                        return 1;
 209                        //Do we want this?
 210                        //return ((name - start) < 1025); /* NS_MAXDNAME */
 211                name++;
 212                if (*name == '\0')
 213                        return 1; // We allow trailing dot too
 214        }
 215}
 216#else
 217# define good_hostname(name) 1
 218#endif
 219
 220/* Create "opt_name=opt_value" string */
 221static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name)
 222{
 223        unsigned upper_length;
 224        int len, type, optlen;
 225        char *dest, *ret;
 226
 227        /* option points to OPT_DATA, need to go back to get OPT_LEN */
 228        len = option[-OPT_DATA + OPT_LEN];
 229
 230        type = optflag->flags & OPTION_TYPE_MASK;
 231        optlen = dhcp_option_lengths[type];
 232        upper_length = len_of_option_as_string[type]
 233                * ((unsigned)(len + optlen) / (unsigned)optlen);
 234
 235        dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
 236        dest += sprintf(ret, "%s=", opt_name);
 237
 238        while (len >= optlen) {
 239                switch (type) {
 240                case OPTION_IP:
 241                case OPTION_IP_PAIR:
 242                        dest += sprint_nip(dest, "", option);
 243                        if (type == OPTION_IP)
 244                                break;
 245                        dest += sprint_nip(dest, "/", option + 4);
 246                        break;
 247//              case OPTION_BOOLEAN:
 248//                      dest += sprintf(dest, *option ? "yes" : "no");
 249//                      break;
 250                case OPTION_U8:
 251                        dest += sprintf(dest, "%u", *option);
 252                        break;
 253//              case OPTION_S16:
 254                case OPTION_U16: {
 255                        uint16_t val_u16;
 256                        move_from_unaligned16(val_u16, option);
 257                        dest += sprintf(dest, "%u", ntohs(val_u16));
 258                        break;
 259                }
 260                case OPTION_S32:
 261                case OPTION_U32: {
 262                        uint32_t val_u32;
 263                        move_from_unaligned32(val_u32, option);
 264                        dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32));
 265                        break;
 266                }
 267                /* Note: options which use 'return' instead of 'break'
 268                 * (for example, OPTION_STRING) skip the code which handles
 269                 * the case of list of options.
 270                 */
 271                case OPTION_STRING:
 272                case OPTION_STRING_HOST:
 273                        memcpy(dest, option, len);
 274                        dest[len] = '\0';
 275                        if (type == OPTION_STRING_HOST && !good_hostname(dest))
 276                                safe_strncpy(dest, "bad", len);
 277                        return ret;
 278                case OPTION_STATIC_ROUTES: {
 279                        /* Option binary format:
 280                         * mask [one byte, 0..32]
 281                         * ip [big endian, 0..4 bytes depending on mask]
 282                         * router [big endian, 4 bytes]
 283                         * may be repeated
 284                         *
 285                         * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2"
 286                         */
 287                        const char *pfx = "";
 288
 289                        while (len >= 1 + 4) { /* mask + 0-byte ip + router */
 290                                uint32_t nip;
 291                                uint8_t *p;
 292                                unsigned mask;
 293                                int bytes;
 294
 295                                mask = *option++;
 296                                if (mask > 32)
 297                                        break;
 298                                len--;
 299
 300                                nip = 0;
 301                                p = (void*) &nip;
 302                                bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */
 303                                while (--bytes >= 0) {
 304                                        *p++ = *option++;
 305                                        len--;
 306                                }
 307                                if (len < 4)
 308                                        break;
 309
 310                                /* print ip/mask */
 311                                dest += sprint_nip(dest, pfx, (void*) &nip);
 312                                pfx = " ";
 313                                dest += sprintf(dest, "/%u ", mask);
 314                                /* print router */
 315                                dest += sprint_nip(dest, "", option);
 316                                option += 4;
 317                                len -= 4;
 318                        }
 319
 320                        return ret;
 321                }
 322                case OPTION_6RD:
 323                        /* Option binary format (see RFC 5969):
 324                         *  0                   1                   2                   3
 325                         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 326                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 327                         * |  OPTION_6RD   | option-length |  IPv4MaskLen  |  6rdPrefixLen |
 328                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 329                         * |                           6rdPrefix                           |
 330                         * ...                        (16 octets)                        ...
 331                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 332                         * ...                   6rdBRIPv4Address(es)                    ...
 333                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 334                         * We convert it to a string
 335                         * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..."
 336                         *
 337                         * Sanity check: ensure that our length is at least 22 bytes, that
 338                         * IPv4MaskLen <= 32,
 339                         * 6rdPrefixLen <= 128,
 340                         * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128
 341                         * (2nd condition need no check - it follows from 1st and 3rd).
 342                         * Else, return envvar with empty value ("optname=")
 343                         */
 344                        if (len >= (1 + 1 + 16 + 4)
 345                         && option[0] <= 32
 346                         && (option[1] + 32 - option[0]) <= 128
 347                        ) {
 348                                /* IPv4MaskLen */
 349                                dest += sprintf(dest, "%u ", *option++);
 350                                /* 6rdPrefixLen */
 351                                dest += sprintf(dest, "%u ", *option++);
 352                                /* 6rdPrefix */
 353                                dest += sprint_nip6(dest, /* "", */ option);
 354                                option += 16;
 355                                len -= 1 + 1 + 16 + 4;
 356                                /* "+ 4" above corresponds to the length of IPv4 addr
 357                                 * we consume in the loop below */
 358                                while (1) {
 359                                        /* 6rdBRIPv4Address(es) */
 360                                        dest += sprint_nip(dest, " ", option);
 361                                        option += 4;
 362                                        len -= 4; /* do we have yet another 4+ bytes? */
 363                                        if (len < 0)
 364                                                break; /* no */
 365                                }
 366                        }
 367
 368                        return ret;
 369#if ENABLE_FEATURE_UDHCP_RFC3397
 370                case OPTION_DNS_STRING:
 371                        /* unpack option into dest; use ret for prefix (i.e., "optname=") */
 372                        dest = dname_dec(option, len, ret);
 373                        if (dest) {
 374                                free(ret);
 375                                return dest;
 376                        }
 377                        /* error. return "optname=" string */
 378                        return ret;
 379                case OPTION_SIP_SERVERS:
 380                        /* Option binary format:
 381                         * type: byte
 382                         * type=0: domain names, dns-compressed
 383                         * type=1: IP addrs
 384                         */
 385                        option++;
 386                        len--;
 387                        if (option[-1] == 0) {
 388                                dest = dname_dec(option, len, ret);
 389                                if (dest) {
 390                                        free(ret);
 391                                        return dest;
 392                                }
 393                        } else
 394                        if (option[-1] == 1) {
 395                                const char *pfx = "";
 396                                while (1) {
 397                                        len -= 4;
 398                                        if (len < 0)
 399                                                break;
 400                                        dest += sprint_nip(dest, pfx, option);
 401                                        pfx = " ";
 402                                        option += 4;
 403                                }
 404                        }
 405                        return ret;
 406#endif
 407                } /* switch */
 408
 409                /* If we are here, try to format any remaining data
 410                 * in the option as another, similarly-formatted option
 411                 */
 412                option += optlen;
 413                len -= optlen;
 414// TODO: it can be a list only if (optflag->flags & OPTION_LIST).
 415// Should we bail out/warn if we see multi-ip option which is
 416// not allowed to be such (for example, DHCP_BROADCAST)? -
 417                if (len < optlen /* || !(optflag->flags & OPTION_LIST) */)
 418                        break;
 419                *dest++ = ' ';
 420                *dest = '\0';
 421        } /* while */
 422
 423        return ret;
 424}
 425
 426/* put all the parameters into the environment */
 427static char **fill_envp(struct dhcp_packet *packet)
 428{
 429        int envc;
 430        int i;
 431        char **envp, **curr;
 432        const char *opt_name;
 433        uint8_t *temp;
 434        uint8_t overload = 0;
 435
 436#define BITMAP unsigned
 437#define BBITS (sizeof(BITMAP) * 8)
 438#define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1)))
 439#define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS])
 440        BITMAP found_opts[256 / BBITS];
 441
 442        memset(found_opts, 0, sizeof(found_opts));
 443
 444        /* We need 6 elements for:
 445         * "interface=IFACE"
 446         * "ip=N.N.N.N" from packet->yiaddr
 447         * "siaddr=IP" from packet->siaddr_nip (unless 0)
 448         * "boot_file=FILE" from packet->file (unless overloaded)
 449         * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded)
 450         * terminating NULL
 451         */
 452        envc = 6;
 453        /* +1 element for each option, +2 for subnet option: */
 454        if (packet) {
 455                /* note: do not search for "pad" (0) and "end" (255) options */
 456//TODO: change logic to scan packet _once_
 457                for (i = 1; i < 255; i++) {
 458                        temp = udhcp_get_option(packet, i);
 459                        if (temp) {
 460                                if (i == DHCP_OPTION_OVERLOAD)
 461                                        overload |= *temp;
 462                                else if (i == DHCP_SUBNET)
 463                                        envc++; /* for $mask */
 464                                envc++;
 465                                /*if (i != DHCP_MESSAGE_TYPE)*/
 466                                FOUND_OPTS(i) |= BMASK(i);
 467                        }
 468                }
 469        }
 470        curr = envp = xzalloc(sizeof(envp[0]) * envc);
 471
 472        *curr = xasprintf("interface=%s", client_config.interface);
 473        putenv(*curr++);
 474
 475        if (!packet)
 476                return envp;
 477
 478        /* Export BOOTP fields. Fields we don't (yet?) export:
 479         * uint8_t op;      // always BOOTREPLY
 480         * uint8_t htype;   // hardware address type. 1 = 10mb ethernet
 481         * uint8_t hlen;    // hardware address length
 482         * uint8_t hops;    // used by relay agents only
 483         * uint32_t xid;
 484         * uint16_t secs;   // elapsed since client began acquisition/renewal
 485         * uint16_t flags;  // only one flag so far: bcast. Never set by server
 486         * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different
 487         *                  // if during renew server wants to give us different IP?)
 488         * uint32_t gateway_nip; // relay agent IP address
 489         * uint8_t chaddr[16]; // link-layer client hardware address (MAC)
 490         * TODO: export gateway_nip as $giaddr?
 491         */
 492        /* Most important one: yiaddr as $ip */
 493        *curr = xmalloc(sizeof("ip=255.255.255.255"));
 494        sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr);
 495        putenv(*curr++);
 496        if (packet->siaddr_nip) {
 497                /* IP address of next server to use in bootstrap */
 498                *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
 499                sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
 500                putenv(*curr++);
 501        }
 502        if (!(overload & FILE_FIELD) && packet->file[0]) {
 503                /* watch out for invalid packets */
 504                *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
 505                putenv(*curr++);
 506        }
 507        if (!(overload & SNAME_FIELD) && packet->sname[0]) {
 508                /* watch out for invalid packets */
 509                *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
 510                putenv(*curr++);
 511        }
 512
 513        /* Export known DHCP options */
 514        opt_name = dhcp_option_strings;
 515        i = 0;
 516        while (*opt_name) {
 517                uint8_t code = dhcp_optflags[i].code;
 518                BITMAP *found_ptr = &FOUND_OPTS(code);
 519                BITMAP found_mask = BMASK(code);
 520                if (!(*found_ptr & found_mask))
 521                        goto next;
 522                *found_ptr &= ~found_mask; /* leave only unknown options */
 523                temp = udhcp_get_option(packet, code);
 524                *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);
 525                putenv(*curr++);
 526                if (code == DHCP_SUBNET) {
 527                        /* Subnet option: make things like "$ip/$mask" possible */
 528                        uint32_t subnet;
 529                        move_from_unaligned32(subnet, temp);
 530                        *curr = xasprintf("mask=%u", mton(subnet));
 531                        putenv(*curr++);
 532                }
 533 next:
 534                opt_name += strlen(opt_name) + 1;
 535                i++;
 536        }
 537        /* Export unknown options */
 538        for (i = 0; i < 256;) {
 539                BITMAP bitmap = FOUND_OPTS(i);
 540                if (!bitmap) {
 541                        i += BBITS;
 542                        continue;
 543                }
 544                if (bitmap & BMASK(i)) {
 545                        unsigned len, ofs;
 546
 547                        temp = udhcp_get_option(packet, i);
 548                        /* udhcp_get_option returns ptr to data portion,
 549                         * need to go back to get len
 550                         */
 551                        len = temp[-OPT_DATA + OPT_LEN];
 552                        *curr = xmalloc(sizeof("optNNN=") + 1 + len*2);
 553                        ofs = sprintf(*curr, "opt%u=", i);
 554                        *bin2hex(*curr + ofs, (void*) temp, len) = '\0';
 555                        putenv(*curr++);
 556                }
 557                i++;
 558        }
 559
 560        return envp;
 561}
 562
 563/* Call a script with a par file and env vars */
 564static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
 565{
 566        char **envp, **curr;
 567        char *argv[3];
 568
 569        envp = fill_envp(packet);
 570
 571        /* call script */
 572        log1("executing %s %s", client_config.script, name);
 573        argv[0] = (char*) client_config.script;
 574        argv[1] = (char*) name;
 575        argv[2] = NULL;
 576        spawn_and_wait(argv);
 577
 578        for (curr = envp; *curr; curr++) {
 579                log2(" %s", *curr);
 580                bb_unsetenv_and_free(*curr);
 581        }
 582        free(envp);
 583}
 584
 585
 586/*** Sending/receiving packets ***/
 587
 588static ALWAYS_INLINE uint32_t random_xid(void)
 589{
 590        return rand();
 591}
 592
 593/* Initialize the packet with the proper defaults */
 594static void init_packet(struct dhcp_packet *packet, char type)
 595{
 596        uint16_t secs;
 597
 598        /* Fill in: op, htype, hlen, cookie fields; message type option: */
 599        udhcp_init_header(packet, type);
 600
 601        packet->xid = random_xid();
 602
 603        client_config.last_secs = monotonic_sec();
 604        if (client_config.first_secs == 0)
 605                client_config.first_secs = client_config.last_secs;
 606        secs = client_config.last_secs - client_config.first_secs;
 607        packet->secs = htons(secs);
 608
 609        memcpy(packet->chaddr, client_config.client_mac, 6);
 610        if (client_config.clientid)
 611                udhcp_add_binary_option(packet, client_config.clientid);
 612}
 613
 614static void add_client_options(struct dhcp_packet *packet)
 615{
 616        int i, end, len;
 617
 618        udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE));
 619
 620        /* Add a "param req" option with the list of options we'd like to have
 621         * from stubborn DHCP servers. Pull the data from the struct in common.c.
 622         * No bounds checking because it goes towards the head of the packet. */
 623        end = udhcp_end_option(packet->options);
 624        len = 0;
 625        for (i = 1; i < DHCP_END; i++) {
 626                if (client_config.opt_mask[i >> 3] & (1 << (i & 7))) {
 627                        packet->options[end + OPT_DATA + len] = i;
 628                        len++;
 629                }
 630        }
 631        if (len) {
 632                packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
 633                packet->options[end + OPT_LEN] = len;
 634                packet->options[end + OPT_DATA + len] = DHCP_END;
 635        }
 636
 637        if (client_config.vendorclass)
 638                udhcp_add_binary_option(packet, client_config.vendorclass);
 639        if (client_config.hostname)
 640                udhcp_add_binary_option(packet, client_config.hostname);
 641        if (client_config.fqdn)
 642                udhcp_add_binary_option(packet, client_config.fqdn);
 643
 644        /* Request broadcast replies if we have no IP addr */
 645        if ((option_mask32 & OPT_B) && packet->ciaddr == 0)
 646                packet->flags |= htons(BROADCAST_FLAG);
 647
 648        /* Add -x options if any */
 649        {
 650                struct option_set *curr = client_config.options;
 651                while (curr) {
 652                        udhcp_add_binary_option(packet, curr->data);
 653                        curr = curr->next;
 654                }
 655//              if (client_config.sname)
 656//                      strncpy((char*)packet->sname, client_config.sname, sizeof(packet->sname) - 1);
 657//              if (client_config.boot_file)
 658//                      strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1);
 659        }
 660
 661        // This will be needed if we remove -V VENDOR_STR in favor of
 662        // -x vendor:VENDOR_STR
 663        //if (!udhcp_find_option(packet.options, DHCP_VENDOR))
 664        //      /* not set, set the default vendor ID */
 665        //      ...add (DHCP_VENDOR, "udhcp "BB_VER) opt...
 666}
 667
 668/* RFC 2131
 669 * 4.4.4 Use of broadcast and unicast
 670 *
 671 * The DHCP client broadcasts DHCPDISCOVER, DHCPREQUEST and DHCPINFORM
 672 * messages, unless the client knows the address of a DHCP server.
 673 * The client unicasts DHCPRELEASE messages to the server. Because
 674 * the client is declining the use of the IP address supplied by the server,
 675 * the client broadcasts DHCPDECLINE messages.
 676 *
 677 * When the DHCP client knows the address of a DHCP server, in either
 678 * INIT or REBOOTING state, the client may use that address
 679 * in the DHCPDISCOVER or DHCPREQUEST rather than the IP broadcast address.
 680 * The client may also use unicast to send DHCPINFORM messages
 681 * to a known DHCP server. If the client receives no response to DHCP
 682 * messages sent to the IP address of a known DHCP server, the DHCP
 683 * client reverts to using the IP broadcast address.
 684 */
 685
 686static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip)
 687{
 688        return udhcp_send_raw_packet(packet,
 689                /*src*/ src_nip, CLIENT_PORT,
 690                /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
 691                client_config.ifindex);
 692}
 693
 694static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server)
 695{
 696        if (server)
 697                return udhcp_send_kernel_packet(packet,
 698                        ciaddr, CLIENT_PORT,
 699                        server, SERVER_PORT);
 700        return raw_bcast_from_client_config_ifindex(packet, ciaddr);
 701}
 702
 703/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
 704/* NOINLINE: limit stack usage in caller */
 705static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
 706{
 707        struct dhcp_packet packet;
 708
 709        /* Fill in: op, htype, hlen, cookie, chaddr fields,
 710         * random xid field (we override it below),
 711         * client-id option (unless -C), message type option:
 712         */
 713        init_packet(&packet, DHCPDISCOVER);
 714
 715        packet.xid = xid;
 716        if (requested)
 717                udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
 718
 719        /* Add options: maxsize,
 720         * optionally: hostname, fqdn, vendorclass,
 721         * "param req" option according to -O, options specified with -x
 722         */
 723        add_client_options(&packet);
 724
 725        bb_error_msg("sending %s", "discover");
 726        return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
 727}
 728
 729/* Broadcast a DHCP request message */
 730/* RFC 2131 3.1 paragraph 3:
 731 * "The client _broadcasts_ a DHCPREQUEST message..."
 732 */
 733/* NOINLINE: limit stack usage in caller */
 734static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested)
 735{
 736        struct dhcp_packet packet;
 737        struct in_addr temp_addr;
 738
 739/*
 740 * RFC 2131 4.3.2 DHCPREQUEST message
 741 * ...
 742 * If the DHCPREQUEST message contains a 'server identifier'
 743 * option, the message is in response to a DHCPOFFER message.
 744 * Otherwise, the message is a request to verify or extend an
 745 * existing lease. If the client uses a 'client identifier'
 746 * in a DHCPREQUEST message, it MUST use that same 'client identifier'
 747 * in all subsequent messages. If the client included a list
 748 * of requested parameters in a DHCPDISCOVER message, it MUST
 749 * include that list in all subsequent messages.
 750 */
 751        /* Fill in: op, htype, hlen, cookie, chaddr fields,
 752         * random xid field (we override it below),
 753         * client-id option (unless -C), message type option:
 754         */
 755        init_packet(&packet, DHCPREQUEST);
 756
 757        packet.xid = xid;
 758        udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
 759
 760        udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
 761
 762        /* Add options: maxsize,
 763         * optionally: hostname, fqdn, vendorclass,
 764         * "param req" option according to -O, and options specified with -x
 765         */
 766        add_client_options(&packet);
 767
 768        temp_addr.s_addr = requested;
 769        bb_error_msg("sending select for %s", inet_ntoa(temp_addr));
 770        return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
 771}
 772
 773/* Unicast or broadcast a DHCP renew message */
 774/* NOINLINE: limit stack usage in caller */
 775static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
 776{
 777        struct dhcp_packet packet;
 778        struct in_addr temp_addr;
 779
 780/*
 781 * RFC 2131 4.3.2 DHCPREQUEST message
 782 * ...
 783 * DHCPREQUEST generated during RENEWING state:
 784 *
 785 * 'server identifier' MUST NOT be filled in, 'requested IP address'
 786 * option MUST NOT be filled in, 'ciaddr' MUST be filled in with
 787 * client's IP address. In this situation, the client is completely
 788 * configured, and is trying to extend its lease. This message will
 789 * be unicast, so no relay agents will be involved in its
 790 * transmission.  Because 'giaddr' is therefore not filled in, the
 791 * DHCP server will trust the value in 'ciaddr', and use it when
 792 * replying to the client.
 793 */
 794        /* Fill in: op, htype, hlen, cookie, chaddr fields,
 795         * random xid field (we override it below),
 796         * client-id option (unless -C), message type option:
 797         */
 798        init_packet(&packet, DHCPREQUEST);
 799
 800        packet.xid = xid;
 801        packet.ciaddr = ciaddr;
 802
 803        /* Add options: maxsize,
 804         * optionally: hostname, fqdn, vendorclass,
 805         * "param req" option according to -O, and options specified with -x
 806         */
 807        add_client_options(&packet);
 808
 809        temp_addr.s_addr = server;
 810        bb_error_msg("sending renew to %s", inet_ntoa(temp_addr));
 811        return bcast_or_ucast(&packet, ciaddr, server);
 812}
 813
 814#if ENABLE_FEATURE_UDHCPC_ARPING
 815/* Broadcast a DHCP decline message */
 816/* NOINLINE: limit stack usage in caller */
 817static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t requested)
 818{
 819        struct dhcp_packet packet;
 820
 821        /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields,
 822         * client-id option (unless -C), message type option:
 823         */
 824        init_packet(&packet, DHCPDECLINE);
 825
 826#if 0
 827        /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client,
 828         * but in case the server is buggy and wants DHCPDECLINE's xid
 829         * to match the xid which started entire handshake,
 830         * we use the same xid we used in initial DHCPDISCOVER:
 831         */
 832        packet.xid = xid;
 833#endif
 834        /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */
 835        udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
 836
 837        udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
 838
 839        bb_error_msg("sending %s", "decline");
 840        return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
 841}
 842#endif
 843
 844/* Unicast a DHCP release message */
 845static int send_release(uint32_t server, uint32_t ciaddr)
 846{
 847        struct dhcp_packet packet;
 848
 849        /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields,
 850         * client-id option (unless -C), message type option:
 851         */
 852        init_packet(&packet, DHCPRELEASE);
 853
 854        /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */
 855        packet.ciaddr = ciaddr;
 856
 857        udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
 858
 859        bb_error_msg("sending %s", "release");
 860        /* Note: normally we unicast here since "server" is not zero.
 861         * However, there _are_ people who run "address-less" DHCP servers,
 862         * and reportedly ISC dhcp client and Windows allow that.
 863         */
 864        return bcast_or_ucast(&packet, ciaddr, server);
 865}
 866
 867/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
 868/* NOINLINE: limit stack usage in caller */
 869static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
 870{
 871        int bytes;
 872        struct ip_udp_dhcp_packet packet;
 873        uint16_t check;
 874        unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
 875        struct iovec iov;
 876        struct msghdr msg;
 877        struct cmsghdr *cmsg;
 878
 879        /* used to use just safe_read(fd, &packet, sizeof(packet))
 880         * but we need to check for TP_STATUS_CSUMNOTREADY :(
 881         */
 882        iov.iov_base = &packet;
 883        iov.iov_len = sizeof(packet);
 884        memset(&msg, 0, sizeof(msg));
 885        msg.msg_iov = &iov;
 886        msg.msg_iovlen = 1;
 887        msg.msg_control = cmsgbuf;
 888        msg.msg_controllen = sizeof(cmsgbuf);
 889        for (;;) {
 890                bytes = recvmsg(fd, &msg, 0);
 891                if (bytes < 0) {
 892                        if (errno == EINTR)
 893                                continue;
 894                        log1("packet read error, ignoring");
 895                        /* NB: possible down interface, etc. Caller should pause. */
 896                        return bytes; /* returns -1 */
 897                }
 898                break;
 899        }
 900
 901        if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
 902                log1("packet is too short, ignoring");
 903                return -2;
 904        }
 905
 906        if (bytes < ntohs(packet.ip.tot_len)) {
 907                /* packet is bigger than sizeof(packet), we did partial read */
 908                log1("oversized packet, ignoring");
 909                return -2;
 910        }
 911
 912        /* ignore any extra garbage bytes */
 913        bytes = ntohs(packet.ip.tot_len);
 914
 915        /* make sure its the right packet for us, and that it passes sanity checks */
 916        if (packet.ip.protocol != IPPROTO_UDP
 917         || packet.ip.version != IPVERSION
 918         || packet.ip.ihl != (sizeof(packet.ip) >> 2)
 919         || packet.udp.dest != htons(CLIENT_PORT)
 920        /* || bytes > (int) sizeof(packet) - can't happen */
 921         || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip))
 922        ) {
 923                log1("unrelated/bogus packet, ignoring");
 924                return -2;
 925        }
 926
 927        /* verify IP checksum */
 928        check = packet.ip.check;
 929        packet.ip.check = 0;
 930        if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
 931                log1("bad IP header checksum, ignoring");
 932                return -2;
 933        }
 934
 935        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
 936                if (cmsg->cmsg_level == SOL_PACKET
 937                 && cmsg->cmsg_type == PACKET_AUXDATA
 938                ) {
 939                        /* some VMs don't checksum UDP and TCP data
 940                         * they send to the same physical machine,
 941                         * here we detect this case:
 942                         */
 943                        struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
 944                        if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
 945                                goto skip_udp_sum_check;
 946                }
 947        }
 948
 949        /* verify UDP checksum. IP header has to be modified for this */
 950        memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
 951        /* ip.xx fields which are not memset: protocol, check, saddr, daddr */
 952        packet.ip.tot_len = packet.udp.len; /* yes, this is needed */
 953        check = packet.udp.check;
 954        packet.udp.check = 0;
 955        if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
 956                log1("packet with bad UDP checksum received, ignoring");
 957                return -2;
 958        }
 959 skip_udp_sum_check:
 960
 961        if (packet.data.cookie != htonl(DHCP_MAGIC)) {
 962                bb_error_msg("packet with bad magic, ignoring");
 963                return -2;
 964        }
 965
 966        log1("received %s", "a packet");
 967        udhcp_dump_packet(&packet.data);
 968
 969        bytes -= sizeof(packet.ip) + sizeof(packet.udp);
 970        memcpy(dhcp_pkt, &packet.data, bytes);
 971        return bytes;
 972}
 973
 974
 975/*** Main ***/
 976
 977static int sockfd = -1;
 978
 979#define LISTEN_NONE   0
 980#define LISTEN_KERNEL 1
 981#define LISTEN_RAW    2
 982static smallint listen_mode;
 983
 984/* initial state: (re)start DHCP negotiation */
 985#define INIT_SELECTING  0
 986/* discover was sent, DHCPOFFER reply received */
 987#define REQUESTING      1
 988/* select/renew was sent, DHCPACK reply received */
 989#define BOUND           2
 990/* half of lease passed, want to renew it by sending unicast renew requests */
 991#define RENEWING        3
 992/* renew requests were not answered, lease is almost over, send broadcast renew */
 993#define REBINDING       4
 994/* manually requested renew (SIGUSR1) */
 995#define RENEW_REQUESTED 5
 996/* release, possibly manually requested (SIGUSR2) */
 997#define RELEASED        6
 998static smallint state;
 999
1000static int udhcp_raw_socket(int ifindex)
1001{
1002        int fd;
1003        struct sockaddr_ll sock;
1004
1005        log2("opening raw socket on ifindex %d", ifindex);
1006
1007        fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
1008        /* ^^^^^
1009         * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them)
1010         * ETH_P_IP: want to receive only packets with IPv4 eth type
1011         */
1012        log2("got raw socket fd");
1013
1014        memset(&sock, 0, sizeof(sock)); /* let's be deterministic */
1015        sock.sll_family = AF_PACKET;
1016        sock.sll_protocol = htons(ETH_P_IP);
1017        sock.sll_ifindex = ifindex;
1018        /*sock.sll_hatype = ARPHRD_???;*/
1019        /*sock.sll_pkttype = PACKET_???;*/
1020        /*sock.sll_halen = ???;*/
1021        /*sock.sll_addr[8] = ???;*/
1022        xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
1023
1024#if 0 /* Several users reported breakage when BPF filter is used */
1025        if (CLIENT_PORT == 68) {
1026                /* Use only if standard port is in use */
1027                /*
1028                 *      I've selected not to see LL header, so BPF doesn't see it, too.
1029                 *      The filter may also pass non-IP and non-ARP packets, but we do
1030                 *      a more complete check when receiving the message in userspace.
1031                 *
1032                 * and filter shamelessly stolen from:
1033                 *
1034                 *      http://www.flamewarmaster.de/software/dhcpclient/
1035                 *
1036                 * There are a few other interesting ideas on that page (look under
1037                 * "Motivation").  Use of netlink events is most interesting.  Think
1038                 * of various network servers listening for events and reconfiguring.
1039                 * That would obsolete sending HUP signals and/or make use of restarts.
1040                 *
1041                 * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>.
1042                 * License: GPL v2.
1043                 */
1044                static const struct sock_filter filter_instr[] = {
1045                        /* load 9th byte (protocol) */
1046                        BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
1047                        /* jump to L1 if it is IPPROTO_UDP, else to L4 */
1048                        BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
1049                        /* L1: load halfword from offset 6 (flags and frag offset) */
1050                        BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
1051                        /* jump to L4 if any bits in frag offset field are set, else to L2 */
1052                        BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
1053                        /* L2: skip IP header (load index reg with header len) */
1054                        BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
1055                        /* load udp destination port from halfword[header_len + 2] */
1056                        BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
1057                        /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */
1058                        BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
1059                        /* L3: accept packet ("accept 0x7fffffff bytes") */
1060                        /* Accepting 0xffffffff works too but kernel 2.6.19 is buggy */
1061                        BPF_STMT(BPF_RET|BPF_K, 0x7fffffff),
1062                        /* L4: discard packet ("accept zero bytes") */
1063                        BPF_STMT(BPF_RET|BPF_K, 0),
1064                };
1065                static const struct sock_fprog filter_prog = {
1066                        .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
1067                        /* casting const away: */
1068                        .filter = (struct sock_filter *) filter_instr,
1069                };
1070                /* Ignoring error (kernel may lack support for this) */
1071                if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
1072                                sizeof(filter_prog)) >= 0)
1073                        log1("attached filter to raw socket fd"); // log?
1074        }
1075#endif
1076
1077        if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) {
1078                if (errno != ENOPROTOOPT)
1079                        log1("can't set PACKET_AUXDATA on raw socket");
1080        }
1081
1082        log1("created raw socket");
1083
1084        return fd;
1085}
1086
1087static void change_listen_mode(int new_mode)
1088{
1089        log1("entering listen mode: %s",
1090                new_mode != LISTEN_NONE
1091                        ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
1092                        : "none"
1093        );
1094
1095        listen_mode = new_mode;
1096        if (sockfd >= 0) {
1097                close(sockfd);
1098                sockfd = -1;
1099        }
1100        if (new_mode == LISTEN_KERNEL)
1101                sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface);
1102        else if (new_mode != LISTEN_NONE)
1103                sockfd = udhcp_raw_socket(client_config.ifindex);
1104        /* else LISTEN_NONE: sockfd stays closed */
1105}
1106
1107/* Called only on SIGUSR1 */
1108static void perform_renew(void)
1109{
1110        bb_error_msg("performing DHCP renew");
1111        switch (state) {
1112        case BOUND:
1113                change_listen_mode(LISTEN_KERNEL);
1114        case RENEWING:
1115        case REBINDING:
1116                state = RENEW_REQUESTED;
1117                break;
1118        case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
1119                udhcp_run_script(NULL, "deconfig");
1120        case REQUESTING:
1121        case RELEASED:
1122                change_listen_mode(LISTEN_RAW);
1123                state = INIT_SELECTING;
1124                break;
1125        case INIT_SELECTING:
1126                break;
1127        }
1128}
1129
1130static void perform_release(uint32_t server_addr, uint32_t requested_ip)
1131{
1132        char buffer[sizeof("255.255.255.255")];
1133        struct in_addr temp_addr;
1134
1135        /* send release packet */
1136        if (state == BOUND
1137         || state == RENEWING
1138         || state == REBINDING
1139         || state == RENEW_REQUESTED
1140        ) {
1141                temp_addr.s_addr = server_addr;
1142                strcpy(buffer, inet_ntoa(temp_addr));
1143                temp_addr.s_addr = requested_ip;
1144                bb_error_msg("unicasting a release of %s to %s",
1145                                inet_ntoa(temp_addr), buffer);
1146                send_release(server_addr, requested_ip); /* unicast */
1147        }
1148        bb_error_msg("entering released state");
1149/*
1150 * We can be here on: SIGUSR2,
1151 * or on exit (SIGTERM) and -R "release on quit" is specified.
1152 * Users requested to be notified in all cases, even if not in one
1153 * of the states above.
1154 */
1155        udhcp_run_script(NULL, "deconfig");
1156
1157        change_listen_mode(LISTEN_NONE);
1158        state = RELEASED;
1159}
1160
1161static uint8_t* alloc_dhcp_option(int code, const char *str, int extra)
1162{
1163        uint8_t *storage;
1164        int len = strnlen(str, 255);
1165        storage = xzalloc(len + extra + OPT_DATA);
1166        storage[OPT_CODE] = code;
1167        storage[OPT_LEN] = len + extra;
1168        memcpy(storage + extra + OPT_DATA, str, len);
1169        return storage;
1170}
1171
1172#if BB_MMU
1173static void client_background(void)
1174{
1175        bb_daemonize(0);
1176        logmode &= ~LOGMODE_STDIO;
1177        /* rewrite pidfile, as our pid is different now */
1178        write_pidfile(client_config.pidfile);
1179}
1180#endif
1181
1182//usage:#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
1183//usage:# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
1184//usage:#else
1185//usage:# define IF_UDHCP_VERBOSE(...)
1186//usage:#endif
1187//usage:#define udhcpc_trivial_usage
1188//usage:       "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n"
1189//usage:       "        [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n"
1190//usage:       "        [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..."
1191//usage:#define udhcpc_full_usage "\n"
1192//usage:     "\n        -i IFACE        Interface to use (default eth0)"
1193//usage:        IF_FEATURE_UDHCP_PORT(
1194//usage:     "\n        -P PORT         Use PORT (default 68)"
1195//usage:        )
1196//usage:     "\n        -s PROG         Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
1197//usage:     "\n        -p FILE         Create pidfile"
1198//usage:     "\n        -B              Request broadcast replies"
1199//usage:     "\n        -t N            Send up to N discover packets (default 3)"
1200//usage:     "\n        -T SEC          Pause between packets (default 3)"
1201//usage:     "\n        -A SEC          Wait if lease is not obtained (default 20)"
1202//usage:     "\n        -n              Exit if lease is not obtained"
1203//usage:     "\n        -q              Exit after obtaining lease"
1204//usage:     "\n        -R              Release IP on exit"
1205//usage:     "\n        -f              Run in foreground"
1206//usage:        USE_FOR_MMU(
1207//usage:     "\n        -b              Background if lease is not obtained"
1208//usage:        )
1209//usage:     "\n        -S              Log to syslog too"
1210//usage:        IF_FEATURE_UDHCPC_ARPING(
1211//usage:     "\n        -a[MSEC]        Validate offered address with ARP ping"
1212//usage:        )
1213//usage:     "\n        -r IP           Request this IP address"
1214//usage:     "\n        -o              Don't request any options (unless -O is given)"
1215//usage:     "\n        -O OPT          Request option OPT from server (cumulative)"
1216//usage:     "\n        -x OPT:VAL      Include option OPT in sent packets (cumulative)"
1217//usage:     "\n                        Examples of string, numeric, and hex byte opts:"
1218//usage:     "\n                        -x hostname:bbox - option 12"
1219//usage:     "\n                        -x lease:3600 - option 51 (lease time)"
1220//usage:     "\n                        -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
1221//usage:     "\n                        -x 14:'\"dumpfile\"' - option 14 (shell-quoted)"
1222//usage:     "\n        -F NAME         Ask server to update DNS mapping for NAME"
1223//usage:     "\n        -V VENDOR       Vendor identifier (default 'udhcp VERSION')"
1224//usage:     "\n        -C              Don't send MAC as client identifier"
1225//usage:        IF_UDHCP_VERBOSE(
1226//usage:     "\n        -v              Verbose"
1227//usage:        )
1228//usage:     "\nSignals:"
1229//usage:     "\n        USR1    Renew lease"
1230//usage:     "\n        USR2    Release lease"
1231
1232
1233int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1234int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1235{
1236        uint8_t *message;
1237        const char *str_V, *str_h, *str_F, *str_r;
1238        IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";)
1239        IF_FEATURE_UDHCP_PORT(char *str_P;)
1240        void *clientid_mac_ptr;
1241        llist_t *list_O = NULL;
1242        llist_t *list_x = NULL;
1243        int tryagain_timeout = 20;
1244        int discover_timeout = 3;
1245        int discover_retries = 3;
1246        uint32_t server_addr = server_addr; /* for compiler */
1247        uint32_t requested_ip = 0;
1248        uint32_t xid = xid; /* for compiler */
1249        int packet_num;
1250        int timeout; /* must be signed */
1251        unsigned already_waited_sec;
1252        unsigned opt;
1253        IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1254        int retval;
1255
1256        setup_common_bufsiz();
1257
1258        /* Default options */
1259        IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
1260        IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
1261        client_config.interface = "eth0";
1262        client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT;
1263        str_V = "udhcp "BB_VER;
1264
1265        /* Parse command line */
1266        opt = getopt32long(argv, "^"
1267                /* O,x: list; -T,-t,-A take numeric param */
1268                "CV:H:h:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB"
1269                USE_FOR_MMU("b")
1270                IF_FEATURE_UDHCPC_ARPING("a::")
1271                IF_FEATURE_UDHCP_PORT("P:")
1272                "v"
1273                "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */
1274                , udhcpc_longopts
1275                , &str_V, &str_h, &str_h, &str_F
1276                , &client_config.interface, &client_config.pidfile /* i,p */
1277                , &str_r /* r */
1278                , &client_config.script /* s */
1279                , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
1280                , &list_O
1281                , &list_x
1282                IF_FEATURE_UDHCPC_ARPING(, &str_a)
1283                IF_FEATURE_UDHCP_PORT(, &str_P)
1284                IF_UDHCP_VERBOSE(, &dhcp_verbose)
1285        );
1286        if (opt & (OPT_h|OPT_H)) {
1287                //msg added 2011-11
1288                bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME");
1289                client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
1290        }
1291        if (opt & OPT_F) {
1292                /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */
1293                client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
1294                /* Flag bits: 0000NEOS
1295                 * S: 1 = Client requests server to update A RR in DNS as well as PTR
1296                 * O: 1 = Server indicates to client that DNS has been updated regardless
1297                 * E: 1 = Name is in DNS format, i.e. <4>host<6>domain<3>com<0>,
1298                 *    not "host.domain.com". Format 0 is obsolete.
1299                 * N: 1 = Client requests server to not update DNS (S must be 0 then)
1300                 * Two [0] bytes which follow are deprecated and must be 0.
1301                 */
1302                client_config.fqdn[OPT_DATA + 0] = 0x1;
1303                /*client_config.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */
1304                /*client_config.fqdn[OPT_DATA + 2] = 0; */
1305        }
1306        if (opt & OPT_r)
1307                requested_ip = inet_addr(str_r);
1308#if ENABLE_FEATURE_UDHCP_PORT
1309        if (opt & OPT_P) {
1310                CLIENT_PORT = xatou16(str_P);
1311                SERVER_PORT = CLIENT_PORT - 1;
1312        }
1313#endif
1314        IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);)
1315        while (list_O) {
1316                char *optstr = llist_pop(&list_O);
1317                unsigned n = bb_strtou(optstr, NULL, 0);
1318                if (errno || n > 254) {
1319                        n = udhcp_option_idx(optstr, dhcp_option_strings);
1320                        n = dhcp_optflags[n].code;
1321                }
1322                client_config.opt_mask[n >> 3] |= 1 << (n & 7);
1323        }
1324        if (!(opt & OPT_o)) {
1325                unsigned i, n;
1326                for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) {
1327                        if (dhcp_optflags[i].flags & OPTION_REQ) {
1328                                client_config.opt_mask[n >> 3] |= 1 << (n & 7);
1329                        }
1330                }
1331        }
1332        while (list_x) {
1333                char *optstr = xstrdup(llist_pop(&list_x));
1334                udhcp_str2optset(optstr, &client_config.options,
1335                                dhcp_optflags, dhcp_option_strings,
1336                                /*dhcpv6:*/ 0
1337                );
1338                free(optstr);
1339        }
1340
1341        if (udhcp_read_interface(client_config.interface,
1342                        &client_config.ifindex,
1343                        NULL,
1344                        client_config.client_mac)
1345        ) {
1346                return 1;
1347        }
1348
1349        clientid_mac_ptr = NULL;
1350        if (!(opt & OPT_C) && !udhcp_find_option(client_config.options, DHCP_CLIENT_ID)) {
1351                /* not suppressed and not set, set the default client ID */
1352                client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
1353                client_config.clientid[OPT_DATA] = 1; /* type: ethernet */
1354                clientid_mac_ptr = client_config.clientid + OPT_DATA+1;
1355                memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1356        }
1357        if (str_V[0] != '\0') {
1358                // can drop -V, str_V, client_config.vendorclass,
1359                // but need to add "vendor" to the list of recognized
1360                // string opts for this to work;
1361                // and need to tweak add_client_options() too...
1362                // ...so the question is, should we?
1363                //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR");
1364                client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
1365        }
1366
1367#if !BB_MMU
1368        /* on NOMMU reexec (i.e., background) early */
1369        if (!(opt & OPT_f)) {
1370                bb_daemonize_or_rexec(0 /* flags */, argv);
1371                logmode = LOGMODE_NONE;
1372        }
1373#endif
1374        if (opt & OPT_S) {
1375                openlog(applet_name, LOG_PID, LOG_DAEMON);
1376                logmode |= LOGMODE_SYSLOG;
1377        }
1378
1379        /* Make sure fd 0,1,2 are open */
1380        bb_sanitize_stdio();
1381        /* Create pidfile */
1382        write_pidfile(client_config.pidfile);
1383        /* Goes to stdout (unless NOMMU) and possibly syslog */
1384        bb_error_msg("started, v"BB_VER);
1385        /* Set up the signal pipe */
1386        udhcp_sp_setup();
1387        /* We want random_xid to be random... */
1388        srand(monotonic_us());
1389
1390        state = INIT_SELECTING;
1391        udhcp_run_script(NULL, "deconfig");
1392        change_listen_mode(LISTEN_RAW);
1393        packet_num = 0;
1394        timeout = 0;
1395        already_waited_sec = 0;
1396
1397        /* Main event loop. select() waits on signal pipe and possibly
1398         * on sockfd.
1399         * "continue" statements in code below jump to the top of the loop.
1400         */
1401        for (;;) {
1402                int tv;
1403                struct pollfd pfds[2];
1404                struct dhcp_packet packet;
1405                /* silence "uninitialized!" warning */
1406                unsigned timestamp_before_wait = timestamp_before_wait;
1407
1408                //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode);
1409
1410                /* Was opening raw or udp socket here
1411                 * if (listen_mode != LISTEN_NONE && sockfd < 0),
1412                 * but on fast network renew responses return faster
1413                 * than we open sockets. Thus this code is moved
1414                 * to change_listen_mode(). Thus we open listen socket
1415                 * BEFORE we send renew request (see "case BOUND:"). */
1416
1417                udhcp_sp_fd_set(pfds, sockfd);
1418
1419                tv = timeout - already_waited_sec;
1420                retval = 0;
1421                /* If we already timed out, fall through with retval = 0, else... */
1422                if (tv > 0) {
1423                        log1("waiting %u seconds", tv);
1424                        timestamp_before_wait = (unsigned)monotonic_sec();
1425                        retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX);
1426                        if (retval < 0) {
1427                                /* EINTR? A signal was caught, don't panic */
1428                                if (errno == EINTR) {
1429                                        already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1430                                        continue;
1431                                }
1432                                /* Else: an error occurred, panic! */
1433                                bb_perror_msg_and_die("poll");
1434                        }
1435                }
1436
1437                /* If timeout dropped to zero, time to become active:
1438                 * resend discover/renew/whatever
1439                 */
1440                if (retval == 0) {
1441                        /* When running on a bridge, the ifindex may have changed
1442                         * (e.g. if member interfaces were added/removed
1443                         * or if the status of the bridge changed).
1444                         * Refresh ifindex and client_mac:
1445                         */
1446                        if (udhcp_read_interface(client_config.interface,
1447                                        &client_config.ifindex,
1448                                        NULL,
1449                                        client_config.client_mac)
1450                        ) {
1451                                goto ret0; /* iface is gone? */
1452                        }
1453                        if (clientid_mac_ptr)
1454                                memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1455
1456                        /* We will restart the wait in any case */
1457                        already_waited_sec = 0;
1458
1459                        switch (state) {
1460                        case INIT_SELECTING:
1461                                if (!discover_retries || packet_num < discover_retries) {
1462                                        if (packet_num == 0)
1463                                                xid = random_xid();
1464                                        /* broadcast */
1465                                        send_discover(xid, requested_ip);
1466                                        timeout = discover_timeout;
1467                                        packet_num++;
1468                                        continue;
1469                                }
1470 leasefail:
1471                                udhcp_run_script(NULL, "leasefail");
1472#if BB_MMU /* -b is not supported on NOMMU */
1473                                if (opt & OPT_b) { /* background if no lease */
1474                                        bb_error_msg("no lease, forking to background");
1475                                        client_background();
1476                                        /* do not background again! */
1477                                        opt = ((opt & ~OPT_b) | OPT_f);
1478                                } else
1479#endif
1480                                if (opt & OPT_n) { /* abort if no lease */
1481                                        bb_error_msg("no lease, failing");
1482                                        retval = 1;
1483                                        goto ret;
1484                                }
1485                                /* wait before trying again */
1486                                timeout = tryagain_timeout;
1487                                packet_num = 0;
1488                                continue;
1489                        case REQUESTING:
1490                                if (packet_num < 3) {
1491                                        /* send broadcast select packet */
1492                                        send_select(xid, server_addr, requested_ip);
1493                                        timeout = discover_timeout;
1494                                        packet_num++;
1495                                        continue;
1496                                }
1497                                /* Timed out, go back to init state.
1498                                 * "discover...select...discover..." loops
1499                                 * were seen in the wild. Treat them similarly
1500                                 * to "no response to discover" case */
1501                                change_listen_mode(LISTEN_RAW);
1502                                state = INIT_SELECTING;
1503                                goto leasefail;
1504                        case BOUND:
1505                                /* 1/2 lease passed, enter renewing state */
1506                                state = RENEWING;
1507                                client_config.first_secs = 0; /* make secs field count from 0 */
1508                                change_listen_mode(LISTEN_KERNEL);
1509                                log1("entering renew state");
1510                                /* fall right through */
1511                        case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1512                        case_RENEW_REQUESTED:
1513                        case RENEWING:
1514                                if (timeout > 60) {
1515                                        /* send an unicast renew request */
1516                        /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1517                         * a new UDP socket for sending inside send_renew.
1518                         * I hazard to guess existing listening socket
1519                         * is somehow conflicting with it, but why is it
1520                         * not deterministic then?! Strange.
1521                         * Anyway, it does recover by eventually failing through
1522                         * into INIT_SELECTING state.
1523                         */
1524                                        if (send_renew(xid, server_addr, requested_ip) >= 0) {
1525                                                timeout >>= 1;
1526//TODO: the timeout to receive an answer for our renew should not be selected
1527//with "timeout = lease_seconds / 2; ...; timeout = timeout / 2": it is often huge.
1528//Waiting e.g. 4*3600 seconds for a reply does not make sense
1529//(if reply isn't coming, we keep an open socket for hours),
1530//it should be something like 10 seconds.
1531//Also, it's probably best to try sending renew in kernel mode a few (3-5) times
1532//and fall back to raw mode if it does not work.
1533                                                continue;
1534                                        }
1535                                        /* else: error sending.
1536                                         * example: ENETUNREACH seen with server
1537                                         * which gave us bogus server ID 1.1.1.1
1538                                         * which wasn't reachable (and probably did not exist).
1539                                         */
1540                                }
1541                                /* Timed out or error, enter rebinding state */
1542                                log1("entering rebinding state");
1543                                state = REBINDING;
1544                                /* fall right through */
1545                        case REBINDING:
1546                                /* Switch to bcast receive */
1547                                change_listen_mode(LISTEN_RAW);
1548                                /* Lease is *really* about to run out,
1549                                 * try to find DHCP server using broadcast */
1550                                if (timeout > 0) {
1551                                        /* send a broadcast renew request */
1552                                        send_renew(xid, 0 /*INADDR_ANY*/, requested_ip);
1553                                        timeout >>= 1;
1554                                        continue;
1555                                }
1556                                /* Timed out, enter init state */
1557                                bb_error_msg("lease lost, entering init state");
1558                                udhcp_run_script(NULL, "deconfig");
1559                                state = INIT_SELECTING;
1560                                client_config.first_secs = 0; /* make secs field count from 0 */
1561                                /*timeout = 0; - already is */
1562                                packet_num = 0;
1563                                continue;
1564                        /* case RELEASED: */
1565                        }
1566                        /* yah, I know, *you* say it would never happen */
1567                        timeout = INT_MAX;
1568                        continue; /* back to main loop */
1569                } /* if poll timed out */
1570
1571                /* poll() didn't timeout, something happened */
1572
1573                /* Is it a signal? */
1574                switch (udhcp_sp_read()) {
1575                case SIGUSR1:
1576                        client_config.first_secs = 0; /* make secs field count from 0 */
1577                        already_waited_sec = 0;
1578                        perform_renew();
1579                        if (state == RENEW_REQUESTED) {
1580                                /* We might be either on the same network
1581                                 * (in which case renew might work),
1582                                 * or we might be on a completely different one
1583                                 * (in which case renew won't ever succeed).
1584                                 * For the second case, must make sure timeout
1585                                 * is not too big, or else we can send
1586                                 * futile renew requests for hours.
1587                                 * (Ab)use -A TIMEOUT value (usually 20 sec)
1588                                 * as a cap on the timeout.
1589                                 */
1590                                if (timeout > tryagain_timeout)
1591                                        timeout = tryagain_timeout;
1592                                goto case_RENEW_REQUESTED;
1593                        }
1594                        /* Start things over */
1595                        packet_num = 0;
1596                        /* Kill any timeouts, user wants this to hurry along */
1597                        timeout = 0;
1598                        continue;
1599                case SIGUSR2:
1600                        perform_release(server_addr, requested_ip);
1601                        timeout = INT_MAX;
1602                        continue;
1603                case SIGTERM:
1604                        bb_error_msg("received %s", "SIGTERM");
1605                        goto ret0;
1606                }
1607
1608                /* Is it a packet? */
1609                if (!pfds[1].revents)
1610                        continue; /* no */
1611
1612                {
1613                        int len;
1614
1615                        /* A packet is ready, read it */
1616                        if (listen_mode == LISTEN_KERNEL)
1617                                len = udhcp_recv_kernel_packet(&packet, sockfd);
1618                        else
1619                                len = udhcp_recv_raw_packet(&packet, sockfd);
1620                        if (len == -1) {
1621                                /* Error is severe, reopen socket */
1622                                bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO);
1623                                sleep(discover_timeout); /* 3 seconds by default */
1624                                change_listen_mode(listen_mode); /* just close and reopen */
1625                        }
1626                        /* If this packet will turn out to be unrelated/bogus,
1627                         * we will go back and wait for next one.
1628                         * Be sure timeout is properly decreased. */
1629                        already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1630                        if (len < 0)
1631                                continue;
1632                }
1633
1634                if (packet.xid != xid) {
1635                        log1("xid %x (our is %x), ignoring packet",
1636                                (unsigned)packet.xid, (unsigned)xid);
1637                        continue;
1638                }
1639
1640                /* Ignore packets that aren't for us */
1641                if (packet.hlen != 6
1642                 || memcmp(packet.chaddr, client_config.client_mac, 6) != 0
1643                ) {
1644//FIXME: need to also check that last 10 bytes are zero
1645                        log1("chaddr does not match, ignoring packet"); // log2?
1646                        continue;
1647                }
1648
1649                message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
1650                if (message == NULL) {
1651                        bb_error_msg("no message type option, ignoring packet");
1652                        continue;
1653                }
1654
1655                switch (state) {
1656                case INIT_SELECTING:
1657                        /* Must be a DHCPOFFER */
1658                        if (*message == DHCPOFFER) {
1659                                uint8_t *temp;
1660
1661/* What exactly is server's IP? There are several values.
1662 * Example DHCP offer captured with tchdump:
1663 *
1664 * 10.34.25.254:67 > 10.34.25.202:68 // IP header's src
1665 * BOOTP fields:
1666 * Your-IP 10.34.25.202
1667 * Server-IP 10.34.32.125   // "next server" IP
1668 * Gateway-IP 10.34.25.254  // relay's address (if DHCP relays are in use)
1669 * DHCP options:
1670 * DHCP-Message Option 53, length 1: Offer
1671 * Server-ID Option 54, length 4: 10.34.255.7       // "server ID"
1672 * Default-Gateway Option 3, length 4: 10.34.25.254 // router
1673 *
1674 * We think that real server IP (one to use in renew/release)
1675 * is one in Server-ID option. But I am not 100% sure.
1676 * IP header's src and Gateway-IP (same in this example)
1677 * might work too.
1678 * "Next server" and router are definitely wrong ones to use, though...
1679 */
1680/* We used to ignore pcakets without DHCP_SERVER_ID.
1681 * I've got user reports from people who run "address-less" servers.
1682 * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all.
1683 * They say ISC DHCP client supports this case.
1684 */
1685                                server_addr = 0;
1686                                temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1687                                if (!temp) {
1688                                        bb_error_msg("no server ID, using 0.0.0.0");
1689                                } else {
1690                                        /* it IS unaligned sometimes, don't "optimize" */
1691                                        move_from_unaligned32(server_addr, temp);
1692                                }
1693                                /*xid = packet.xid; - already is */
1694                                requested_ip = packet.yiaddr;
1695
1696                                /* enter requesting state */
1697                                state = REQUESTING;
1698                                timeout = 0;
1699                                packet_num = 0;
1700                                already_waited_sec = 0;
1701                        }
1702                        continue;
1703                case REQUESTING:
1704                case RENEWING:
1705                case RENEW_REQUESTED:
1706                case REBINDING:
1707                        if (*message == DHCPACK) {
1708                                unsigned start;
1709                                uint32_t lease_seconds;
1710                                struct in_addr temp_addr;
1711                                uint8_t *temp;
1712
1713                                temp = udhcp_get_option(&packet, DHCP_LEASE_TIME);
1714                                if (!temp) {
1715                                        bb_error_msg("no lease time with ACK, using 1 hour lease");
1716                                        lease_seconds = 60 * 60;
1717                                } else {
1718                                        /* it IS unaligned sometimes, don't "optimize" */
1719                                        move_from_unaligned32(lease_seconds, temp);
1720                                        lease_seconds = ntohl(lease_seconds);
1721                                        /* paranoia: must not be too small and not prone to overflows */
1722                                        if (lease_seconds < 0x10)
1723                                                lease_seconds = 0x10;
1724                                        //if (lease_seconds > 0x7fffffff)
1725                                        //      lease_seconds = 0x7fffffff;
1726                                        //^^^not necessary since "timeout = lease_seconds / 2"
1727                                        //does not overflow even for 0xffffffff.
1728                                }
1729#if ENABLE_FEATURE_UDHCPC_ARPING
1730                                if (opt & OPT_a) {
1731/* RFC 2131 3.1 paragraph 5:
1732 * "The client receives the DHCPACK message with configuration
1733 * parameters. The client SHOULD perform a final check on the
1734 * parameters (e.g., ARP for allocated network address), and notes
1735 * the duration of the lease specified in the DHCPACK message. At this
1736 * point, the client is configured. If the client detects that the
1737 * address is already in use (e.g., through the use of ARP),
1738 * the client MUST send a DHCPDECLINE message to the server and restarts
1739 * the configuration process..." */
1740                                        if (!arpping(packet.yiaddr,
1741                                                        NULL,
1742                                                        (uint32_t) 0,
1743                                                        client_config.client_mac,
1744                                                        client_config.interface,
1745                                                        arpping_ms)
1746                                        ) {
1747                                                bb_error_msg("offered address is in use "
1748                                                        "(got ARP reply), declining");
1749                                                send_decline(/*xid,*/ server_addr, packet.yiaddr);
1750
1751                                                if (state != REQUESTING)
1752                                                        udhcp_run_script(NULL, "deconfig");
1753                                                change_listen_mode(LISTEN_RAW);
1754                                                state = INIT_SELECTING;
1755                                                client_config.first_secs = 0; /* make secs field count from 0 */
1756                                                requested_ip = 0;
1757                                                timeout = tryagain_timeout;
1758                                                packet_num = 0;
1759                                                already_waited_sec = 0;
1760                                                continue; /* back to main loop */
1761                                        }
1762                                }
1763#endif
1764                                /* enter bound state */
1765                                temp_addr.s_addr = packet.yiaddr;
1766                                bb_error_msg("lease of %s obtained, lease time %u",
1767                                        inet_ntoa(temp_addr), (unsigned)lease_seconds);
1768                                requested_ip = packet.yiaddr;
1769
1770                                start = monotonic_sec();
1771                                udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew");
1772                                already_waited_sec = (unsigned)monotonic_sec() - start;
1773                                timeout = lease_seconds / 2;
1774                                if ((unsigned)timeout < already_waited_sec) {
1775                                        /* Something went wrong. Back to discover state */
1776                                        timeout = already_waited_sec = 0;
1777                                }
1778
1779                                state = BOUND;
1780                                change_listen_mode(LISTEN_NONE);
1781                                if (opt & OPT_q) { /* quit after lease */
1782                                        goto ret0;
1783                                }
1784                                /* future renew failures should not exit (JM) */
1785                                opt &= ~OPT_n;
1786#if BB_MMU /* NOMMU case backgrounded earlier */
1787                                if (!(opt & OPT_f)) {
1788                                        client_background();
1789                                        /* do not background again! */
1790                                        opt = ((opt & ~OPT_b) | OPT_f);
1791                                }
1792#endif
1793                                /* make future renew packets use different xid */
1794                                /* xid = random_xid(); ...but why bother? */
1795
1796                                continue; /* back to main loop */
1797                        }
1798                        if (*message == DHCPNAK) {
1799                                /* If network has more than one DHCP server,
1800                                 * "wrong" server can reply first, with a NAK.
1801                                 * Do not interpret it as a NAK from "our" server.
1802                                 */
1803                                if (server_addr != 0) {
1804                                        uint32_t svid;
1805                                        uint8_t *temp;
1806
1807                                        temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1808                                        if (!temp) {
1809 non_matching_svid:
1810                                                log1("received DHCP NAK with wrong"
1811                                                        " server ID, ignoring packet");
1812                                                continue;
1813                                        }
1814                                        move_from_unaligned32(svid, temp);
1815                                        if (svid != server_addr)
1816                                                goto non_matching_svid;
1817                                }
1818                                /* return to init state */
1819                                bb_error_msg("received %s", "DHCP NAK");
1820                                udhcp_run_script(&packet, "nak");
1821                                if (state != REQUESTING)
1822                                        udhcp_run_script(NULL, "deconfig");
1823                                change_listen_mode(LISTEN_RAW);
1824                                sleep(3); /* avoid excessive network traffic */
1825                                state = INIT_SELECTING;
1826                                client_config.first_secs = 0; /* make secs field count from 0 */
1827                                requested_ip = 0;
1828                                timeout = 0;
1829                                packet_num = 0;
1830                                already_waited_sec = 0;
1831                        }
1832                        continue;
1833                /* case BOUND: - ignore all packets */
1834                /* case RELEASED: - ignore all packets */
1835                }
1836                /* back to main loop */
1837        } /* for (;;) - main loop ends */
1838
1839 ret0:
1840        if (opt & OPT_R) /* release on quit */
1841                perform_release(server_addr, requested_ip);
1842        retval = 0;
1843 ret:
1844        /*if (client_config.pidfile) - remove_pidfile has its own check */
1845                remove_pidfile(client_config.pidfile);
1846        return retval;
1847}
1848