busybox/networking/udhcp/dhcpc.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/* dhcpc.c
   3 *
   4 * udhcp DHCP client
   5 *
   6 * Russ Dill <Russ.Dill@asu.edu> July 2001
   7 *
   8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
   9 */
  10
  11#include <syslog.h>
  12
  13/* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */
  14#define WANT_PIDFILE 1
  15#include "common.h"
  16#include "dhcpd.h"
  17#include "dhcpc.h"
  18#include "options.h"
  19
  20
  21static int sockfd = -1;
  22
  23#define LISTEN_NONE 0
  24#define LISTEN_KERNEL 1
  25#define LISTEN_RAW 2
  26static smallint listen_mode;
  27
  28#define INIT_SELECTING  0
  29#define REQUESTING      1
  30#define BOUND           2
  31#define RENEWING        3
  32#define REBINDING       4
  33#define INIT_REBOOT     5
  34#define RENEW_REQUESTED 6
  35#define RELEASED        7
  36static smallint state;
  37
  38/* struct client_config_t client_config is in bb_common_bufsiz1 */
  39
  40
  41/* just a little helper */
  42static void change_listen_mode(int new_mode)
  43{
  44        DEBUG("entering %s listen mode",
  45                new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
  46        if (sockfd >= 0) {
  47                close(sockfd);
  48                sockfd = -1;
  49        }
  50        listen_mode = new_mode;
  51}
  52
  53
  54/* perform a renew */
  55static void perform_renew(void)
  56{
  57        bb_info_msg("Performing a DHCP renew");
  58        switch (state) {
  59        case BOUND:
  60                change_listen_mode(LISTEN_KERNEL);
  61        case RENEWING:
  62        case REBINDING:
  63                state = RENEW_REQUESTED;
  64                break;
  65        case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
  66                udhcp_run_script(NULL, "deconfig");
  67        case REQUESTING:
  68        case RELEASED:
  69                change_listen_mode(LISTEN_RAW);
  70                state = INIT_SELECTING;
  71                break;
  72        case INIT_SELECTING:
  73                break;
  74        }
  75}
  76
  77
  78/* perform a release */
  79static void perform_release(uint32_t requested_ip, uint32_t server_addr)
  80{
  81        char buffer[sizeof("255.255.255.255")];
  82        struct in_addr temp_addr;
  83
  84        /* send release packet */
  85        if (state == BOUND || state == RENEWING || state == REBINDING) {
  86                temp_addr.s_addr = server_addr;
  87                strcpy(buffer, inet_ntoa(temp_addr));
  88                temp_addr.s_addr = requested_ip;
  89                bb_info_msg("Unicasting a release of %s to %s",
  90                                inet_ntoa(temp_addr), buffer);
  91                send_release(server_addr, requested_ip); /* unicast */
  92                udhcp_run_script(NULL, "deconfig");
  93        }
  94        bb_info_msg("Entering released state");
  95
  96        change_listen_mode(LISTEN_NONE);
  97        state = RELEASED;
  98}
  99
 100
 101#if BB_MMU
 102static void client_background(void)
 103{
 104        bb_daemonize(0);
 105        logmode &= ~LOGMODE_STDIO;
 106        /* rewrite pidfile, as our pid is different now */
 107        write_pidfile(client_config.pidfile);
 108}
 109#endif
 110
 111
 112static uint8_t* alloc_dhcp_option(int code, const char *str, int extra)
 113{
 114        uint8_t *storage;
 115        int len = strlen(str);
 116        if (len > 255) len = 255;
 117        storage = xzalloc(len + extra + OPT_DATA);
 118        storage[OPT_CODE] = code;
 119        storage[OPT_LEN] = len + extra;
 120        memcpy(storage + extra + OPT_DATA, str, len);
 121        return storage;
 122}
 123
 124
 125int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 126int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 127{
 128        uint8_t *temp, *message;
 129        char *str_c, *str_V, *str_h, *str_F, *str_r;
 130        USE_FEATURE_UDHCP_PORT(char *str_P;)
 131        llist_t *list_O = NULL;
 132        int tryagain_timeout = 20;
 133        int discover_timeout = 3;
 134        int discover_retries = 3;
 135        uint32_t server_addr = server_addr; /* for compiler */
 136        uint32_t requested_ip = 0;
 137        uint32_t xid = 0;
 138        uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */
 139        int packet_num;
 140        int timeout; /* must be signed */
 141        unsigned already_waited_sec;
 142        unsigned opt;
 143        int max_fd;
 144        int retval;
 145        struct timeval tv;
 146        struct dhcpMessage packet;
 147        fd_set rfds;
 148
 149#if ENABLE_GETOPT_LONG
 150        static const char udhcpc_longopts[] ALIGN1 =
 151                "clientid\0"       Required_argument "c"
 152                "clientid-none\0"  No_argument       "C"
 153                "vendorclass\0"    Required_argument "V"
 154                "hostname\0"       Required_argument "H"
 155                "fqdn\0"           Required_argument "F"
 156                "interface\0"      Required_argument "i"
 157                "now\0"            No_argument       "n"
 158                "pidfile\0"        Required_argument "p"
 159                "quit\0"           No_argument       "q"
 160                "release\0"        No_argument       "R"
 161                "request\0"        Required_argument "r"
 162                "script\0"         Required_argument "s"
 163                "timeout\0"        Required_argument "T"
 164                "version\0"        No_argument       "v"
 165                "retries\0"        Required_argument "t"
 166                "tryagain\0"       Required_argument "A"
 167                "syslog\0"         No_argument       "S"
 168                "request-option\0" Required_argument "O"
 169                "no-default-options\0" No_argument   "o"
 170                "foreground\0"     No_argument       "f"
 171                "background\0"     No_argument       "b"
 172                USE_FEATURE_UDHCPC_ARPING("arping\0"    No_argument       "a")
 173                USE_FEATURE_UDHCP_PORT("client-port\0"  Required_argument "P")
 174                ;
 175#endif
 176        enum {
 177                OPT_c = 1 << 0,
 178                OPT_C = 1 << 1,
 179                OPT_V = 1 << 2,
 180                OPT_H = 1 << 3,
 181                OPT_h = 1 << 4,
 182                OPT_F = 1 << 5,
 183                OPT_i = 1 << 6,
 184                OPT_n = 1 << 7,
 185                OPT_p = 1 << 8,
 186                OPT_q = 1 << 9,
 187                OPT_R = 1 << 10,
 188                OPT_r = 1 << 11,
 189                OPT_s = 1 << 12,
 190                OPT_T = 1 << 13,
 191                OPT_t = 1 << 14,
 192                OPT_v = 1 << 15,
 193                OPT_S = 1 << 16,
 194                OPT_A = 1 << 17,
 195                OPT_O = 1 << 18,
 196                OPT_o = 1 << 19,
 197                OPT_f = 1 << 20,
 198/* The rest has variable bit positions, need to be clever */
 199                OPTBIT_f = 20,
 200                USE_FOR_MMU(              OPTBIT_b,)
 201                USE_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
 202                USE_FEATURE_UDHCP_PORT(   OPTBIT_P,)
 203                USE_FOR_MMU(              OPT_b = 1 << OPTBIT_b,)
 204                USE_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
 205                USE_FEATURE_UDHCP_PORT(   OPT_P = 1 << OPTBIT_P,)
 206        };
 207
 208        /* Default options. */
 209        USE_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
 210        USE_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
 211        client_config.interface = "eth0";
 212        client_config.script = DEFAULT_SCRIPT;
 213
 214        /* Parse command line */
 215        /* Cc: mutually exclusive; O: list; -T,-t,-A take numeric param */
 216        opt_complementary = "c--C:C--c:O::T+:t+:A+";
 217        USE_GETOPT_LONG(applet_long_options = udhcpc_longopts;)
 218        opt = getopt32(argv, "c:CV:H:h:F:i:np:qRr:s:T:t:vSA:O:of"
 219                USE_FOR_MMU("b")
 220                USE_FEATURE_UDHCPC_ARPING("a")
 221                USE_FEATURE_UDHCP_PORT("P:")
 222                , &str_c, &str_V, &str_h, &str_h, &str_F
 223                , &client_config.interface, &client_config.pidfile, &str_r /* i,p */
 224                , &client_config.script /* s */
 225                , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
 226                , &list_O
 227                USE_FEATURE_UDHCP_PORT(, &str_P)
 228                );
 229        if (opt & OPT_c)
 230                client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
 231        if (opt & OPT_V)
 232                client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
 233        if (opt & (OPT_h|OPT_H))
 234                client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
 235        if (opt & OPT_F) {
 236                client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
 237                /* Flags: 0000NEOS
 238                S: 1 => Client requests Server to update A RR in DNS as well as PTR
 239                O: 1 => Server indicates to client that DNS has been updated regardless
 240                E: 1 => Name data is DNS format, i.e. <4>host<6>domain<3>com<0> not "host.domain.com"
 241                N: 1 => Client requests Server to not update DNS
 242                */
 243                client_config.fqdn[OPT_DATA + 0] = 0x1;
 244                /* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */
 245                /* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */
 246        }
 247        if (opt & OPT_r)
 248                requested_ip = inet_addr(str_r);
 249        if (opt & OPT_v) {
 250                puts("version "BB_VER);
 251                return 0;
 252        }
 253#if ENABLE_FEATURE_UDHCP_PORT
 254        if (opt & OPT_P) {
 255                CLIENT_PORT = xatou16(str_P);
 256                SERVER_PORT = CLIENT_PORT - 1;
 257        }
 258#endif
 259        if (opt & OPT_o)
 260                client_config.no_default_options = 1;
 261        while (list_O) {
 262                char *optstr = llist_pop(&list_O);
 263                int n = index_in_strings(dhcp_option_strings, optstr);
 264                if (n < 0)
 265                        bb_error_msg_and_die("unknown option '%s'", optstr);
 266                n = dhcp_options[n].code;
 267                client_config.opt_mask[n >> 3] |= 1 << (n & 7);
 268        }
 269
 270        if (udhcp_read_interface(client_config.interface, &client_config.ifindex,
 271                           NULL, client_config.arp))
 272                return 1;
 273#if !BB_MMU
 274        /* on NOMMU reexec (i.e., background) early */
 275        if (!(opt & OPT_f)) {
 276                bb_daemonize_or_rexec(0 /* flags */, argv);
 277                logmode = 0;
 278        }
 279#endif
 280        if (opt & OPT_S) {
 281                openlog(applet_name, LOG_PID, LOG_LOCAL0);
 282                logmode |= LOGMODE_SYSLOG;
 283        }
 284
 285        /* Make sure fd 0,1,2 are open */
 286        bb_sanitize_stdio();
 287        /* Equivalent of doing a fflush after every \n */
 288        setlinebuf(stdout);
 289
 290        /* Create pidfile */
 291        write_pidfile(client_config.pidfile);
 292
 293        /* Goes to stdout (unless NOMMU) and possibly syslog */
 294        bb_info_msg("%s (v"BB_VER") started", applet_name);
 295
 296        /* if not set, and not suppressed, setup the default client ID */
 297        if (!client_config.clientid && !(opt & OPT_C)) {
 298                client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
 299                client_config.clientid[OPT_DATA] = 1;
 300                memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6);
 301        }
 302
 303        if (!client_config.vendorclass)
 304                client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
 305
 306        /* setup the signal pipe */
 307        udhcp_sp_setup();
 308
 309        state = INIT_SELECTING;
 310        udhcp_run_script(NULL, "deconfig");
 311        change_listen_mode(LISTEN_RAW);
 312        packet_num = 0;
 313        timeout = 0;
 314        already_waited_sec = 0;
 315
 316        /* Main event loop. select() waits on signal pipe and possibly
 317         * on sockfd.
 318         * "continue" statements in code below jump to the top of the loop.
 319         */
 320        for (;;) {
 321                unsigned timestamp_before_wait;
 322
 323                if (listen_mode != LISTEN_NONE && sockfd < 0) {
 324                        if (listen_mode == LISTEN_KERNEL)
 325                                sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface);
 326                        else
 327                                sockfd = udhcp_raw_socket(client_config.ifindex);
 328                }
 329                max_fd = udhcp_sp_fd_set(&rfds, sockfd);
 330
 331                tv.tv_sec = timeout - already_waited_sec;
 332                tv.tv_usec = 0;
 333                retval = 0; /* If we already timed out, fall through, else... */
 334                if (tv.tv_sec > 0) {
 335                        timestamp_before_wait = (unsigned)monotonic_sec();
 336                        DEBUG("Waiting on select...");
 337                        retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
 338                        if (retval < 0) {
 339                                /* EINTR? A signal was caught, don't panic */
 340                                if (errno == EINTR)
 341                                        continue;
 342                                /* Else: an error occured, panic! */
 343                                bb_perror_msg_and_die("select");
 344                        }
 345                }
 346
 347                /* If timeout dropped to zero, time to become active:
 348                 * resend discover/renew/whatever
 349                 */
 350                if (retval == 0) {
 351                        /* We will restart the wait in any case */
 352                        already_waited_sec = 0;
 353
 354                        switch (state) {
 355                        case INIT_SELECTING:
 356                                if (packet_num < discover_retries) {
 357                                        if (packet_num == 0)
 358                                                xid = random_xid();
 359
 360                                        send_discover(xid, requested_ip); /* broadcast */
 361
 362                                        timeout = discover_timeout;
 363                                        packet_num++;
 364                                        continue;
 365                                }
 366 leasefail:
 367                                udhcp_run_script(NULL, "leasefail");
 368#if BB_MMU /* -b is not supported on NOMMU */
 369                                if (opt & OPT_b) { /* background if no lease */
 370                                        bb_info_msg("No lease, forking to background");
 371                                        client_background();
 372                                        /* do not background again! */
 373                                        opt = ((opt & ~OPT_b) | OPT_f);
 374                                } else
 375#endif
 376                                if (opt & OPT_n) { /* abort if no lease */
 377                                        bb_info_msg("No lease, failing");
 378                                        retval = 1;
 379                                        goto ret;
 380                                }
 381                                /* wait before trying again */
 382                                timeout = tryagain_timeout;
 383                                packet_num = 0;
 384                                continue;
 385                        case RENEW_REQUESTED:
 386                        case REQUESTING:
 387                                if (packet_num < discover_retries) {
 388                                        /* send request packet */
 389                                        if (state == RENEW_REQUESTED) /* unicast */
 390                                                send_renew(xid, server_addr, requested_ip);
 391                                        else /* broadcast */
 392                                                send_select(xid, server_addr, requested_ip);
 393
 394                                        timeout = discover_timeout;
 395                                        packet_num++;
 396                                        continue;
 397                                }
 398                                /* timed out, go back to init state */
 399                                if (state == RENEW_REQUESTED)
 400                                        udhcp_run_script(NULL, "deconfig");
 401                                change_listen_mode(LISTEN_RAW);
 402                                /* "discover...select...discover..." loops
 403                                 * were seen in the wild. Treat them similarly
 404                                 * to "no response to discover" case */
 405                                if (state == REQUESTING) {
 406                                        state = INIT_SELECTING;
 407                                        goto leasefail;
 408                                }
 409                                state = INIT_SELECTING;
 410                                timeout = 0;
 411                                packet_num = 0;
 412                                continue;
 413                        case BOUND:
 414                                /* Half of the lease passed, time to enter renewing state */
 415                                change_listen_mode(LISTEN_KERNEL);
 416                                DEBUG("Entering renew state");
 417                                state = RENEWING;
 418                                /* fall right through */
 419                        case RENEWING:
 420                                if (timeout > 60) {
 421                                        /* send a request packet */
 422                                        send_renew(xid, server_addr, requested_ip); /* unicast */
 423                                        timeout >>= 1;
 424                                        continue;
 425                                }
 426                                /* Timed out, enter rebinding state */
 427                                DEBUG("Entering rebinding state");
 428                                state = REBINDING;
 429                                /* fall right through */
 430                        case REBINDING:
 431                                /* Lease is *really* about to run out,
 432                                 * try to find DHCP server using broadcast */
 433                                if (timeout > 0) {
 434                                        /* send a request packet */
 435                                        send_renew(xid, 0 /* INADDR_ANY*/, requested_ip); /* broadcast */
 436                                        timeout >>= 1;
 437                                        continue;
 438                                }
 439                                /* Timed out, enter init state */
 440                                bb_info_msg("Lease lost, entering init state");
 441                                udhcp_run_script(NULL, "deconfig");
 442                                change_listen_mode(LISTEN_RAW);
 443                                state = INIT_SELECTING;
 444                                /*timeout = 0; - already is */
 445                                packet_num = 0;
 446                                continue;
 447                        /* case RELEASED: */
 448                        }
 449                        /* yah, I know, *you* say it would never happen */
 450                        timeout = INT_MAX;
 451                        continue; /* back to main loop */
 452                }
 453
 454                /* select() didn't timeout, something did happen. */
 455                /* Is it a packet? */
 456                if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
 457                        int len;
 458                        /* A packet is ready, read it */
 459
 460                        if (listen_mode == LISTEN_KERNEL)
 461                                len = udhcp_recv_kernel_packet(&packet, sockfd);
 462                        else
 463                                len = udhcp_recv_raw_packet(&packet, sockfd);
 464                        if (len == -1) { /* error is severe, reopen socket */
 465                                DEBUG("error on read, %s, reopening socket", strerror(errno));
 466                                sleep(discover_timeout); /* 3 seconds by default */
 467                                change_listen_mode(listen_mode); /* just close and reopen */
 468                        }
 469                        /* If this packet will turn out to be unrelated/bogus,
 470                         * we will go back and wait for next one.
 471                         * Be sure timeout is properly decreased. */
 472                        already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
 473                        if (len < 0)
 474                                continue;
 475
 476                        if (packet.xid != xid) {
 477                                DEBUG("Ignoring xid %x (our xid is %x)",
 478                                        (unsigned)packet.xid, (unsigned)xid);
 479                                continue;
 480                        }
 481
 482                        /* Ignore packets that aren't for us */
 483                        if (memcmp(packet.chaddr, client_config.arp, 6)) {
 484                                DEBUG("Packet does not have our chaddr - ignoring");
 485                                continue;
 486                        }
 487
 488                        message = get_option(&packet, DHCP_MESSAGE_TYPE);
 489                        if (message == NULL) {
 490                                bb_error_msg("cannot get message type from packet - ignoring");
 491                                continue;
 492                        }
 493
 494                        switch (state) {
 495                        case INIT_SELECTING:
 496                                /* Must be a DHCPOFFER to one of our xid's */
 497                                if (*message == DHCPOFFER) {
 498                        /* TODO: why we don't just fetch server's IP from IP header? */
 499                                        temp = get_option(&packet, DHCP_SERVER_ID);
 500                                        if (!temp) {
 501                                                bb_error_msg("no server ID in message");
 502                                                continue;
 503                                                /* still selecting - this server looks bad */
 504                                        }
 505                                        /* it IS unaligned sometimes, don't "optimize" */
 506                                        server_addr = get_unaligned_u32p((uint32_t*)temp);
 507                                        xid = packet.xid;
 508                                        requested_ip = packet.yiaddr;
 509
 510                                        /* enter requesting state */
 511                                        state = REQUESTING;
 512                                        timeout = 0;
 513                                        packet_num = 0;
 514                                        already_waited_sec = 0;
 515                                }
 516                                continue;
 517                        case RENEW_REQUESTED:
 518                        case REQUESTING:
 519                        case RENEWING:
 520                        case REBINDING:
 521                                if (*message == DHCPACK) {
 522                                        temp = get_option(&packet, DHCP_LEASE_TIME);
 523                                        if (!temp) {
 524                                                bb_error_msg("no lease time with ACK, using 1 hour lease");
 525                                                lease_seconds = 60 * 60;
 526                                        } else {
 527                                                /* it IS unaligned sometimes, don't "optimize" */
 528                                                lease_seconds = get_unaligned_u32p((uint32_t*)temp);
 529                                                lease_seconds = ntohl(lease_seconds);
 530                                                lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */
 531                                                if (lease_seconds < 10) /* and not too small */
 532                                                        lease_seconds = 10;
 533                                        }
 534#if ENABLE_FEATURE_UDHCPC_ARPING
 535                                        if (opt & OPT_a) {
 536/* RFC 2131 3.1 paragraph 5:
 537 * "The client receives the DHCPACK message with configuration
 538 * parameters. The client SHOULD perform a final check on the
 539 * parameters (e.g., ARP for allocated network address), and notes
 540 * the duration of the lease specified in the DHCPACK message. At this
 541 * point, the client is configured. If the client detects that the
 542 * address is already in use (e.g., through the use of ARP),
 543 * the client MUST send a DHCPDECLINE message to the server and restarts
 544 * the configuration process..." */
 545                                                if (!arpping(packet.yiaddr,
 546                                                            (uint32_t) 0,
 547                                                            client_config.arp,
 548                                                            client_config.interface)
 549                                                ) {
 550                                                        bb_info_msg("offered address is in use "
 551                                                                "(got ARP reply), declining");
 552                                                        send_decline(xid, server_addr, packet.yiaddr);
 553
 554                                                        if (state != REQUESTING)
 555                                                                udhcp_run_script(NULL, "deconfig");
 556                                                        change_listen_mode(LISTEN_RAW);
 557                                                        state = INIT_SELECTING;
 558                                                        requested_ip = 0;
 559                                                        timeout = tryagain_timeout;
 560                                                        packet_num = 0;
 561                                                        already_waited_sec = 0;
 562                                                        continue; /* back to main loop */
 563                                                }
 564                                        }
 565#endif
 566                                        /* enter bound state */
 567                                        timeout = lease_seconds / 2;
 568                                        {
 569                                                struct in_addr temp_addr;
 570                                                temp_addr.s_addr = packet.yiaddr;
 571                                                bb_info_msg("Lease of %s obtained, lease time %u",
 572                                                        inet_ntoa(temp_addr), (unsigned)lease_seconds);
 573                                        }
 574                                        requested_ip = packet.yiaddr;
 575                                        udhcp_run_script(&packet,
 576                                                        ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
 577
 578                                        state = BOUND;
 579                                        change_listen_mode(LISTEN_NONE);
 580                                        if (opt & OPT_q) { /* quit after lease */
 581                                                if (opt & OPT_R) /* release on quit */
 582                                                        perform_release(requested_ip, server_addr);
 583                                                goto ret0;
 584                                        }
 585#if BB_MMU /* NOMMU case backgrounded earlier */
 586                                        if (!(opt & OPT_f)) {
 587                                                client_background();
 588                                                /* do not background again! */
 589                                                opt = ((opt & ~OPT_b) | OPT_f);
 590                                        }
 591#endif
 592                                        already_waited_sec = 0;
 593                                        continue; /* back to main loop */
 594                                }
 595                                if (*message == DHCPNAK) {
 596                                        /* return to init state */
 597                                        bb_info_msg("Received DHCP NAK");
 598                                        udhcp_run_script(&packet, "nak");
 599                                        if (state != REQUESTING)
 600                                                udhcp_run_script(NULL, "deconfig");
 601                                        change_listen_mode(LISTEN_RAW);
 602                                        sleep(3); /* avoid excessive network traffic */
 603                                        state = INIT_SELECTING;
 604                                        requested_ip = 0;
 605                                        timeout = 0;
 606                                        packet_num = 0;
 607                                        already_waited_sec = 0;
 608                                }
 609                                continue;
 610                        /* case BOUND, RELEASED: - ignore all packets */
 611                        }
 612                        continue; /* back to main loop */
 613                }
 614
 615                /* select() didn't timeout, something did happen.
 616                 * But it wasn't a packet. It's a signal pipe then. */
 617                {
 618                        int signo = udhcp_sp_read(&rfds);
 619                        switch (signo) {
 620                        case SIGUSR1:
 621                                perform_renew();
 622                                /* start things over */
 623                                packet_num = 0;
 624                                /* Kill any timeouts because the user wants this to hurry along */
 625                                timeout = 0;
 626                                break;
 627                        case SIGUSR2:
 628                                perform_release(requested_ip, server_addr);
 629                                timeout = INT_MAX;
 630                                break;
 631                        case SIGTERM:
 632                                bb_info_msg("Received SIGTERM");
 633                                if (opt & OPT_R) /* release on quit */
 634                                        perform_release(requested_ip, server_addr);
 635                                goto ret0;
 636                        }
 637                }
 638        } /* for (;;) - main loop ends */
 639
 640 ret0:
 641        retval = 0;
 642 ret:
 643        /*if (client_config.pidfile) - remove_pidfile has its own check */
 644                remove_pidfile(client_config.pidfile);
 645        return retval;
 646}
 647