Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/udhcp/dhcpc.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/networking/udhcp/dhcpc.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 /* dhcpc.c 3 * 4 * udhcp DHCP client 2 /* 3 * udhcp client 5 4 * 6 5 * Russ Dill <Russ.Dill@asu.edu> July 2001 7 6 * 8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 9 20 */ 10 11 #include <getopt.h>12 21 #include <syslog.h> 13 14 22 /* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */ 15 23 #define WANT_PIDFILE 1 … … 17 25 #include "dhcpd.h" 18 26 #include "dhcpc.h" 19 #include "options.h" 20 21 22 /* Something is definitely wrong here. IPv4 addresses 23 * in variables of type long?? BTW, we use inet_ntoa() 24 * in the code. Manpage says that struct in_addr has a member of type long (!) 25 * which holds IPv4 address, and the struct is passed by value (!!) 27 28 #include <asm/types.h> 29 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) 30 # include <netpacket/packet.h> 31 # include <net/ethernet.h> 32 #else 33 # include <linux/if_packet.h> 34 # include <linux/if_ether.h> 35 #endif 36 #include <linux/filter.h> 37 38 /* struct client_config_t client_config is in bb_common_bufsiz1 */ 39 40 41 /*** Script execution code ***/ 42 43 /* get a rough idea of how long an option will be (rounding up...) */ 44 static const uint8_t len_of_option_as_string[] = { 45 [OPTION_IP ] = sizeof("255.255.255.255 "), 46 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 47 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 48 [OPTION_STRING ] = 1, 49 #if ENABLE_FEATURE_UDHCP_RFC3397 50 [OPTION_DNS_STRING ] = 1, /* unused */ 51 /* Hmmm, this severely overestimates size if SIP_SERVERS option 52 * is in domain name form: N-byte option in binary form 53 * mallocs ~16*N bytes. But it is freed almost at once. 54 */ 55 [OPTION_SIP_SERVERS ] = sizeof("255.255.255.255 "), 56 #endif 57 // [OPTION_BOOLEAN ] = sizeof("yes "), 58 [OPTION_U8 ] = sizeof("255 "), 59 [OPTION_U16 ] = sizeof("65535 "), 60 // [OPTION_S16 ] = sizeof("-32768 "), 61 [OPTION_U32 ] = sizeof("4294967295 "), 62 [OPTION_S32 ] = sizeof("-2147483684 "), 63 }; 64 65 /* note: ip is a pointer to an IP in network order, possibly misaliged */ 66 static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) 67 { 68 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); 69 } 70 71 /* really simple implementation, just count the bits */ 72 static int mton(uint32_t mask) 73 { 74 int i = 0; 75 mask = ntohl(mask); /* 111110000-like bit pattern */ 76 while (mask) { 77 i++; 78 mask <<= 1; 79 } 80 return i; 81 } 82 83 /* Create "opt_name=opt_value" string */ 84 static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) 85 { 86 unsigned upper_length; 87 int len, type, optlen; 88 char *dest, *ret; 89 90 /* option points to OPT_DATA, need to go back and get OPT_LEN */ 91 len = option[OPT_LEN - OPT_DATA]; 92 93 type = optflag->flags & OPTION_TYPE_MASK; 94 optlen = dhcp_option_lengths[type]; 95 upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); 96 97 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); 98 dest += sprintf(ret, "%s=", opt_name); 99 100 while (len >= optlen) { 101 unsigned ip_ofs = 0; 102 103 switch (type) { 104 case OPTION_IP_PAIR: 105 dest += sprint_nip(dest, "", option); 106 *dest++ = '/'; 107 ip_ofs = 4; 108 /* fall through */ 109 case OPTION_IP: 110 dest += sprint_nip(dest, "", option + ip_ofs); 111 break; 112 // case OPTION_BOOLEAN: 113 // dest += sprintf(dest, *option ? "yes" : "no"); 114 // break; 115 case OPTION_U8: 116 dest += sprintf(dest, "%u", *option); 117 break; 118 // case OPTION_S16: 119 case OPTION_U16: { 120 uint16_t val_u16; 121 move_from_unaligned16(val_u16, option); 122 dest += sprintf(dest, "%u", ntohs(val_u16)); 123 break; 124 } 125 case OPTION_S32: 126 case OPTION_U32: { 127 uint32_t val_u32; 128 move_from_unaligned32(val_u32, option); 129 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32)); 130 break; 131 } 132 case OPTION_STRING: 133 memcpy(dest, option, len); 134 dest[len] = '\0'; 135 return ret; /* Short circuit this case */ 136 case OPTION_STATIC_ROUTES: { 137 /* Option binary format: 138 * mask [one byte, 0..32] 139 * ip [big endian, 0..4 bytes depending on mask] 140 * router [big endian, 4 bytes] 141 * may be repeated 142 * 143 * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2" 144 */ 145 const char *pfx = ""; 146 147 while (len >= 1 + 4) { /* mask + 0-byte ip + router */ 148 uint32_t nip; 149 uint8_t *p; 150 unsigned mask; 151 int bytes; 152 153 mask = *option++; 154 if (mask > 32) 155 break; 156 len--; 157 158 nip = 0; 159 p = (void*) &nip; 160 bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */ 161 while (--bytes >= 0) { 162 *p++ = *option++; 163 len--; 164 } 165 if (len < 4) 166 break; 167 168 /* print ip/mask */ 169 dest += sprint_nip(dest, pfx, (void*) &nip); 170 pfx = " "; 171 dest += sprintf(dest, "/%u ", mask); 172 /* print router */ 173 dest += sprint_nip(dest, "", option); 174 option += 4; 175 len -= 4; 176 } 177 178 return ret; 179 } 180 #if ENABLE_FEATURE_UDHCP_RFC3397 181 case OPTION_DNS_STRING: 182 /* unpack option into dest; use ret for prefix (i.e., "optname=") */ 183 dest = dname_dec(option, len, ret); 184 if (dest) { 185 free(ret); 186 return dest; 187 } 188 /* error. return "optname=" string */ 189 return ret; 190 case OPTION_SIP_SERVERS: 191 /* Option binary format: 192 * type: byte 193 * type=0: domain names, dns-compressed 194 * type=1: IP addrs 195 */ 196 option++; 197 len--; 198 if (option[-1] == 0) { 199 dest = dname_dec(option, len, ret); 200 if (dest) { 201 free(ret); 202 return dest; 203 } 204 } else 205 if (option[-1] == 1) { 206 const char *pfx = ""; 207 while (1) { 208 len -= 4; 209 if (len < 0) 210 break; 211 dest += sprint_nip(dest, pfx, option); 212 pfx = " "; 213 option += 4; 214 } 215 } 216 return ret; 217 #endif 218 } /* switch */ 219 option += optlen; 220 len -= optlen; 221 // TODO: it can be a list only if (optflag->flags & OPTION_LIST). 222 // Should we bail out/warn if we see multi-ip option which is 223 // not allowed to be such (for example, DHCP_BROADCAST)? - 224 if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */) 225 break; 226 *dest++ = ' '; 227 *dest = '\0'; 228 } 229 return ret; 230 } 231 232 /* put all the parameters into the environment */ 233 static char **fill_envp(struct dhcp_packet *packet) 234 { 235 int envc; 236 int i; 237 char **envp, **curr; 238 const char *opt_name; 239 uint8_t *temp; 240 uint8_t overload = 0; 241 242 /* We need 6 elements for: 243 * "interface=IFACE" 244 * "ip=N.N.N.N" from packet->yiaddr 245 * "siaddr=IP" from packet->siaddr_nip (unless 0) 246 * "boot_file=FILE" from packet->file (unless overloaded) 247 * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) 248 * terminating NULL 249 */ 250 envc = 6; 251 /* +1 element for each option, +2 for subnet option: */ 252 if (packet) { 253 for (i = 0; dhcp_optflags[i].code; i++) { 254 if (udhcp_get_option(packet, dhcp_optflags[i].code)) { 255 if (dhcp_optflags[i].code == DHCP_SUBNET) 256 envc++; /* for mton */ 257 envc++; 258 } 259 } 260 temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD); 261 if (temp) 262 overload = *temp; 263 } 264 curr = envp = xzalloc(sizeof(char *) * envc); 265 266 *curr = xasprintf("interface=%s", client_config.interface); 267 putenv(*curr++); 268 269 if (!packet) 270 return envp; 271 272 *curr = xmalloc(sizeof("ip=255.255.255.255")); 273 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); 274 putenv(*curr++); 275 276 opt_name = dhcp_option_strings; 277 i = 0; 278 while (*opt_name) { 279 temp = udhcp_get_option(packet, dhcp_optflags[i].code); 280 if (!temp) 281 goto next; 282 *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); 283 putenv(*curr++); 284 if (dhcp_optflags[i].code == DHCP_SUBNET) { 285 /* Subnet option: make things like "$ip/$mask" possible */ 286 uint32_t subnet; 287 move_from_unaligned32(subnet, temp); 288 *curr = xasprintf("mask=%d", mton(subnet)); 289 putenv(*curr++); 290 } 291 next: 292 opt_name += strlen(opt_name) + 1; 293 i++; 294 } 295 if (packet->siaddr_nip) { 296 *curr = xmalloc(sizeof("siaddr=255.255.255.255")); 297 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); 298 putenv(*curr++); 299 } 300 if (!(overload & FILE_FIELD) && packet->file[0]) { 301 /* watch out for invalid packets */ 302 *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); 303 putenv(*curr++); 304 } 305 if (!(overload & SNAME_FIELD) && packet->sname[0]) { 306 /* watch out for invalid packets */ 307 *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); 308 putenv(*curr++); 309 } 310 return envp; 311 } 312 313 /* Call a script with a par file and env vars */ 314 static void udhcp_run_script(struct dhcp_packet *packet, const char *name) 315 { 316 char **envp, **curr; 317 char *argv[3]; 318 319 if (client_config.script == NULL) 320 return; 321 322 envp = fill_envp(packet); 323 324 /* call script */ 325 log1("Executing %s %s", client_config.script, name); 326 argv[0] = (char*) client_config.script; 327 argv[1] = (char*) name; 328 argv[2] = NULL; 329 spawn_and_wait(argv); 330 331 for (curr = envp; *curr; curr++) { 332 log2(" %s", *curr); 333 bb_unsetenv_and_free(*curr); 334 } 335 free(envp); 336 } 337 338 339 /*** Sending/receiving packets ***/ 340 341 static ALWAYS_INLINE uint32_t random_xid(void) 342 { 343 return rand(); 344 } 345 346 /* Initialize the packet with the proper defaults */ 347 static void init_packet(struct dhcp_packet *packet, char type) 348 { 349 /* Fill in: op, htype, hlen, cookie fields; message type option: */ 350 udhcp_init_header(packet, type); 351 352 packet->xid = random_xid(); 353 354 memcpy(packet->chaddr, client_config.client_mac, 6); 355 if (client_config.clientid) 356 udhcp_add_binary_option(packet, client_config.clientid); 357 } 358 359 static void add_client_options(struct dhcp_packet *packet) 360 { 361 uint8_t c; 362 int i, end, len; 363 364 udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE)); 365 366 /* Add a "param req" option with the list of options we'd like to have 367 * from stubborn DHCP servers. Pull the data from the struct in common.c. 368 * No bounds checking because it goes towards the head of the packet. */ 369 end = udhcp_end_option(packet->options); 370 len = 0; 371 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { 372 if (( (dhcp_optflags[i].flags & OPTION_REQ) 373 && !client_config.no_default_options 374 ) 375 || (client_config.opt_mask[c >> 3] & (1 << (c & 7))) 376 ) { 377 packet->options[end + OPT_DATA + len] = c; 378 len++; 379 } 380 } 381 if (len) { 382 packet->options[end + OPT_CODE] = DHCP_PARAM_REQ; 383 packet->options[end + OPT_LEN] = len; 384 packet->options[end + OPT_DATA + len] = DHCP_END; 385 } 386 387 if (client_config.vendorclass) 388 udhcp_add_binary_option(packet, client_config.vendorclass); 389 if (client_config.hostname) 390 udhcp_add_binary_option(packet, client_config.hostname); 391 if (client_config.fqdn) 392 udhcp_add_binary_option(packet, client_config.fqdn); 393 394 /* Add -x options if any */ 395 { 396 struct option_set *curr = client_config.options; 397 while (curr) { 398 udhcp_add_binary_option(packet, curr->data); 399 curr = curr->next; 400 } 401 // if (client_config.sname) 402 // strncpy((char*)packet->sname, client_config.sname, sizeof(packet->sname) - 1); 403 // if (client_config.boot_file) 404 // strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1); 405 } 406 } 407 408 /* RFC 2131 409 * 4.4.4 Use of broadcast and unicast 410 * 411 * The DHCP client broadcasts DHCPDISCOVER, DHCPREQUEST and DHCPINFORM 412 * messages, unless the client knows the address of a DHCP server. 413 * The client unicasts DHCPRELEASE messages to the server. Because 414 * the client is declining the use of the IP address supplied by the server, 415 * the client broadcasts DHCPDECLINE messages. 416 * 417 * When the DHCP client knows the address of a DHCP server, in either 418 * INIT or REBOOTING state, the client may use that address 419 * in the DHCPDISCOVER or DHCPREQUEST rather than the IP broadcast address. 420 * The client may also use unicast to send DHCPINFORM messages 421 * to a known DHCP server. If the client receives no response to DHCP 422 * messages sent to the IP address of a known DHCP server, the DHCP 423 * client reverts to using the IP broadcast address. 26 424 */ 27 static unsigned timeout; 28 static uint32_t requested_ip; /* = 0 */ 29 static uint32_t server_addr; 30 static int packet_num; /* = 0 */ 425 426 static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet) 427 { 428 return udhcp_send_raw_packet(packet, 429 /*src*/ INADDR_ANY, CLIENT_PORT, 430 /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, 431 client_config.ifindex); 432 } 433 434 /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ 435 /* NOINLINE: limit stack usage in caller */ 436 static NOINLINE int send_discover(uint32_t xid, uint32_t requested) 437 { 438 struct dhcp_packet packet; 439 440 /* Fill in: op, htype, hlen, cookie, chaddr fields, 441 * random xid field (we override it below), 442 * client-id option (unless -C), message type option: 443 */ 444 init_packet(&packet, DHCPDISCOVER); 445 446 packet.xid = xid; 447 if (requested) 448 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 449 450 /* Add options: maxsize, 451 * optionally: hostname, fqdn, vendorclass, 452 * "param req" option according to -O, options specified with -x 453 */ 454 add_client_options(&packet); 455 456 bb_info_msg("Sending discover..."); 457 return raw_bcast_from_client_config_ifindex(&packet); 458 } 459 460 /* Broadcast a DHCP request message */ 461 /* RFC 2131 3.1 paragraph 3: 462 * "The client _broadcasts_ a DHCPREQUEST message..." 463 */ 464 /* NOINLINE: limit stack usage in caller */ 465 static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) 466 { 467 struct dhcp_packet packet; 468 struct in_addr addr; 469 470 /* 471 * RFC 2131 4.3.2 DHCPREQUEST message 472 * ... 473 * If the DHCPREQUEST message contains a 'server identifier' 474 * option, the message is in response to a DHCPOFFER message. 475 * Otherwise, the message is a request to verify or extend an 476 * existing lease. If the client uses a 'client identifier' 477 * in a DHCPREQUEST message, it MUST use that same 'client identifier' 478 * in all subsequent messages. If the client included a list 479 * of requested parameters in a DHCPDISCOVER message, it MUST 480 * include that list in all subsequent messages. 481 */ 482 /* Fill in: op, htype, hlen, cookie, chaddr fields, 483 * random xid field (we override it below), 484 * client-id option (unless -C), message type option: 485 */ 486 init_packet(&packet, DHCPREQUEST); 487 488 packet.xid = xid; 489 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 490 491 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 492 493 /* Add options: maxsize, 494 * optionally: hostname, fqdn, vendorclass, 495 * "param req" option according to -O, and options specified with -x 496 */ 497 add_client_options(&packet); 498 499 addr.s_addr = requested; 500 bb_info_msg("Sending select for %s...", inet_ntoa(addr)); 501 return raw_bcast_from_client_config_ifindex(&packet); 502 } 503 504 /* Unicast or broadcast a DHCP renew message */ 505 /* NOINLINE: limit stack usage in caller */ 506 static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) 507 { 508 struct dhcp_packet packet; 509 510 /* 511 * RFC 2131 4.3.2 DHCPREQUEST message 512 * ... 513 * DHCPREQUEST generated during RENEWING state: 514 * 515 * 'server identifier' MUST NOT be filled in, 'requested IP address' 516 * option MUST NOT be filled in, 'ciaddr' MUST be filled in with 517 * client's IP address. In this situation, the client is completely 518 * configured, and is trying to extend its lease. This message will 519 * be unicast, so no relay agents will be involved in its 520 * transmission. Because 'giaddr' is therefore not filled in, the 521 * DHCP server will trust the value in 'ciaddr', and use it when 522 * replying to the client. 523 */ 524 /* Fill in: op, htype, hlen, cookie, chaddr fields, 525 * random xid field (we override it below), 526 * client-id option (unless -C), message type option: 527 */ 528 init_packet(&packet, DHCPREQUEST); 529 530 packet.xid = xid; 531 packet.ciaddr = ciaddr; 532 533 /* Add options: maxsize, 534 * optionally: hostname, fqdn, vendorclass, 535 * "param req" option according to -O, and options specified with -x 536 */ 537 add_client_options(&packet); 538 539 bb_info_msg("Sending renew..."); 540 if (server) 541 return udhcp_send_kernel_packet(&packet, 542 ciaddr, CLIENT_PORT, 543 server, SERVER_PORT); 544 return raw_bcast_from_client_config_ifindex(&packet); 545 } 546 547 #if ENABLE_FEATURE_UDHCPC_ARPING 548 /* Broadcast a DHCP decline message */ 549 /* NOINLINE: limit stack usage in caller */ 550 static NOINLINE int send_decline(uint32_t xid, uint32_t server, uint32_t requested) 551 { 552 struct dhcp_packet packet; 553 554 /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, 555 * client-id option (unless -C), message type option: 556 */ 557 init_packet(&packet, DHCPDECLINE); 558 559 /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client, 560 * but in case the server is buggy and wants DHCPDECLINE's xid 561 * to match the xid which started entire handshake, 562 * we use the same xid we used in initial DHCPDISCOVER: 563 */ 564 packet.xid = xid; 565 /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ 566 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 567 568 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 569 570 bb_info_msg("Sending decline..."); 571 return raw_bcast_from_client_config_ifindex(&packet); 572 } 573 #endif 574 575 /* Unicast a DHCP release message */ 576 static int send_release(uint32_t server, uint32_t ciaddr) 577 { 578 struct dhcp_packet packet; 579 580 /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, 581 * client-id option (unless -C), message type option: 582 */ 583 init_packet(&packet, DHCPRELEASE); 584 585 /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */ 586 packet.ciaddr = ciaddr; 587 588 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 589 590 bb_info_msg("Sending release..."); 591 return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); 592 } 593 594 /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ 595 /* NOINLINE: limit stack usage in caller */ 596 static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) 597 { 598 int bytes; 599 struct ip_udp_dhcp_packet packet; 600 uint16_t check; 601 602 memset(&packet, 0, sizeof(packet)); 603 bytes = safe_read(fd, &packet, sizeof(packet)); 604 if (bytes < 0) { 605 log1("Packet read error, ignoring"); 606 /* NB: possible down interface, etc. Caller should pause. */ 607 return bytes; /* returns -1 */ 608 } 609 610 if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { 611 log1("Packet is too short, ignoring"); 612 return -2; 613 } 614 615 if (bytes < ntohs(packet.ip.tot_len)) { 616 /* packet is bigger than sizeof(packet), we did partial read */ 617 log1("Oversized packet, ignoring"); 618 return -2; 619 } 620 621 /* ignore any extra garbage bytes */ 622 bytes = ntohs(packet.ip.tot_len); 623 624 /* make sure its the right packet for us, and that it passes sanity checks */ 625 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION 626 || packet.ip.ihl != (sizeof(packet.ip) >> 2) 627 || packet.udp.dest != htons(CLIENT_PORT) 628 /* || bytes > (int) sizeof(packet) - can't happen */ 629 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) 630 ) { 631 log1("Unrelated/bogus packet, ignoring"); 632 return -2; 633 } 634 635 /* verify IP checksum */ 636 check = packet.ip.check; 637 packet.ip.check = 0; 638 if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) { 639 log1("Bad IP header checksum, ignoring"); 640 return -2; 641 } 642 643 /* verify UDP checksum. IP header has to be modified for this */ 644 memset(&packet.ip, 0, offsetof(struct iphdr, protocol)); 645 /* ip.xx fields which are not memset: protocol, check, saddr, daddr */ 646 packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ 647 check = packet.udp.check; 648 packet.udp.check = 0; 649 if (check && check != udhcp_checksum(&packet, bytes)) { 650 log1("Packet with bad UDP checksum received, ignoring"); 651 return -2; 652 } 653 654 memcpy(dhcp_pkt, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp))); 655 656 if (dhcp_pkt->cookie != htonl(DHCP_MAGIC)) { 657 bb_info_msg("Packet with bad magic, ignoring"); 658 return -2; 659 } 660 log1("Got valid DHCP packet"); 661 udhcp_dump_packet(dhcp_pkt); 662 return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); 663 } 664 665 666 /*** Main ***/ 667 31 668 static int sockfd = -1; 32 669 33 #define LISTEN_NONE 0670 #define LISTEN_NONE 0 34 671 #define LISTEN_KERNEL 1 35 #define LISTEN_RAW 2672 #define LISTEN_RAW 2 36 673 static smallint listen_mode; 37 674 675 /* initial state: (re)start DHCP negotiation */ 676 #define INIT_SELECTING 0 677 /* discover was sent, DHCPOFFER reply received */ 678 #define REQUESTING 1 679 /* select/renew was sent, DHCPACK reply received */ 680 #define BOUND 2 681 /* half of lease passed, want to renew it by sending unicast renew requests */ 682 #define RENEWING 3 683 /* renew requests were not answered, lease is almost over, send broadcast renew */ 684 #define REBINDING 4 685 /* manually requested renew (SIGUSR1) */ 686 #define RENEW_REQUESTED 5 687 /* release, possibly manually requested (SIGUSR2) */ 688 #define RELEASED 6 38 689 static smallint state; 39 690 40 struct client_config_t client_config; 41 42 43 /* just a little helper */ 44 static void change_mode(int new_mode) 45 { 46 DEBUG("entering %s listen mode", 47 new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); 691 static int udhcp_raw_socket(int ifindex) 692 { 693 int fd; 694 struct sockaddr_ll sock; 695 696 /* 697 * Comment: 698 * 699 * I've selected not to see LL header, so BPF doesn't see it, too. 700 * The filter may also pass non-IP and non-ARP packets, but we do 701 * a more complete check when receiving the message in userspace. 702 * 703 * and filter shamelessly stolen from: 704 * 705 * http://www.flamewarmaster.de/software/dhcpclient/ 706 * 707 * There are a few other interesting ideas on that page (look under 708 * "Motivation"). Use of netlink events is most interesting. Think 709 * of various network servers listening for events and reconfiguring. 710 * That would obsolete sending HUP signals and/or make use of restarts. 711 * 712 * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>. 713 * License: GPL v2. 714 * 715 * TODO: make conditional? 716 */ 717 #define SERVER_AND_CLIENT_PORTS ((67 << 16) + 68) 718 static const struct sock_filter filter_instr[] = { 719 /* check for udp */ 720 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9), 721 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 2, 0), /* L5, L1, is UDP? */ 722 /* ugly check for arp on ethernet-like and IPv4 */ 723 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), /* L1: */ 724 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x08000604, 3, 4), /* L3, L4 */ 725 /* skip IP header */ 726 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), /* L5: */ 727 /* check udp source and destination ports */ 728 BPF_STMT(BPF_LD|BPF_W|BPF_IND, 0), 729 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SERVER_AND_CLIENT_PORTS, 0, 1), /* L3, L4 */ 730 /* returns */ 731 BPF_STMT(BPF_RET|BPF_K, 0x0fffffff ), /* L3: pass */ 732 BPF_STMT(BPF_RET|BPF_K, 0), /* L4: reject */ 733 }; 734 static const struct sock_fprog filter_prog = { 735 .len = sizeof(filter_instr) / sizeof(filter_instr[0]), 736 /* casting const away: */ 737 .filter = (struct sock_filter *) filter_instr, 738 }; 739 740 log1("Opening raw socket on ifindex %d", ifindex); //log2? 741 742 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 743 log1("Got raw socket fd %d", fd); //log2? 744 745 if (SERVER_PORT == 67 && CLIENT_PORT == 68) { 746 /* Use only if standard ports are in use */ 747 /* Ignoring error (kernel may lack support for this) */ 748 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, 749 sizeof(filter_prog)) >= 0) 750 log1("Attached filter to raw socket fd %d", fd); // log? 751 } 752 753 sock.sll_family = AF_PACKET; 754 sock.sll_protocol = htons(ETH_P_IP); 755 sock.sll_ifindex = ifindex; 756 xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); 757 log1("Created raw socket"); 758 759 return fd; 760 } 761 762 static void change_listen_mode(int new_mode) 763 { 764 log1("Entering listen mode: %s", 765 new_mode != LISTEN_NONE 766 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw") 767 : "none" 768 ); 769 770 listen_mode = new_mode; 48 771 if (sockfd >= 0) { 49 772 close(sockfd); 50 773 sockfd = -1; 51 774 } 52 listen_mode = new_mode; 53 } 54 55 56 /* perform a renew */ 775 if (new_mode == LISTEN_KERNEL) 776 sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface); 777 else if (new_mode != LISTEN_NONE) 778 sockfd = udhcp_raw_socket(client_config.ifindex); 779 /* else LISTEN_NONE: sockfd stays closed */ 780 } 781 57 782 static void perform_renew(void) 58 783 { … … 60 785 switch (state) { 61 786 case BOUND: 62 change_ mode(LISTEN_KERNEL);787 change_listen_mode(LISTEN_KERNEL); 63 788 case RENEWING: 64 789 case REBINDING: … … 69 794 case REQUESTING: 70 795 case RELEASED: 71 change_ mode(LISTEN_RAW);796 change_listen_mode(LISTEN_RAW); 72 797 state = INIT_SELECTING; 73 798 break; … … 75 800 break; 76 801 } 77 78 /* start things over */ 79 packet_num = 0; 80 81 /* Kill any timeouts because the user wants this to hurry along */ 82 timeout = 0; 83 } 84 85 86 /* perform a release */ 87 static void perform_release(void) 802 } 803 804 static void perform_release(uint32_t requested_ip, uint32_t server_addr) 88 805 { 89 806 char buffer[sizeof("255.255.255.255")]; … … 102 819 bb_info_msg("Entering released state"); 103 820 104 change_ mode(LISTEN_NONE);821 change_listen_mode(LISTEN_NONE); 105 822 state = RELEASED; 106 timeout = INT_MAX; 107 } 108 109 110 static void client_background(void) 111 { 112 #if !BB_MMU 113 bb_error_msg("cannot background in uclinux (yet)"); 114 /* ... mainly because udhcpc calls client_background() 115 * in _the _middle _of _udhcpc _run_, not at the start! 116 * If that will be properly disabled for NOMMU, client_background() 117 * will work on NOMMU too */ 118 #else 119 bb_daemonize(0); 120 logmode &= ~LOGMODE_STDIO; 121 /* rewrite pidfile, as our pid is different now */ 122 write_pidfile(client_config.pidfile); 123 #endif 124 /* Do not fork again. */ 125 client_config.foreground = 1; 126 client_config.background_if_no_lease = 0; 127 } 128 823 } 129 824 130 825 static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) 131 826 { 132 827 uint8_t *storage; 133 int len = strlen(str); 134 if (len > 255) len = 255; 828 int len = strnlen(str, 255); 135 829 storage = xzalloc(len + extra + OPT_DATA); 136 830 storage[OPT_CODE] = code; … … 140 834 } 141 835 142 143 int udhcpc_main(int argc, char **argv); 144 int udhcpc_main(int argc, char **argv) 836 #if BB_MMU 837 static void client_background(void) 838 { 839 bb_daemonize(0); 840 logmode &= ~LOGMODE_STDIO; 841 /* rewrite pidfile, as our pid is different now */ 842 write_pidfile(client_config.pidfile); 843 } 844 #endif 845 846 //usage:#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 847 //usage:# define IF_UDHCP_VERBOSE(...) __VA_ARGS__ 848 //usage:#else 849 //usage:# define IF_UDHCP_VERBOSE(...) 850 //usage:#endif 851 //usage:#define udhcpc_trivial_usage 852 //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" 853 //usage: " [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") 854 //usage:#define udhcpc_full_usage "\n" 855 //usage: IF_LONG_OPTS( 856 //usage: "\n -i,--interface IFACE Interface to use (default eth0)" 857 //usage: "\n -p,--pidfile FILE Create pidfile" 858 //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 859 //usage: "\n -t,--retries N Send up to N discover packets" 860 //usage: "\n -T,--timeout N Pause between packets (default 3 seconds)" 861 //usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)" 862 //usage: "\n -f,--foreground Run in foreground" 863 //usage: USE_FOR_MMU( 864 //usage: "\n -b,--background Background if lease is not obtained" 865 //usage: ) 866 //usage: "\n -n,--now Exit if lease is not obtained" 867 //usage: "\n -q,--quit Exit after obtaining lease" 868 //usage: "\n -R,--release Release IP on exit" 869 //usage: "\n -S,--syslog Log to syslog too" 870 //usage: IF_FEATURE_UDHCP_PORT( 871 //usage: "\n -P,--client-port N Use port N (default 68)" 872 //usage: ) 873 //usage: IF_FEATURE_UDHCPC_ARPING( 874 //usage: "\n -a,--arping Use arping to validate offered address" 875 //usage: ) 876 //usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)" 877 //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" 878 //usage: "\n -r,--request IP Request this IP address" 879 //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" 880 //usage: "\n Examples of string, numeric, and hex byte opts:" 881 //usage: "\n -x hostname:bbox - option 12" 882 //usage: "\n -x lease:3600 - option 51 (lease time)" 883 //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" 884 //usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME" 885 //usage: "\n -H,-h,--hostname NAME Send NAME as client hostname (default none)" 886 //usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')" 887 //usage: "\n -C,--clientid-none Don't send MAC as client identifier" 888 //usage: IF_UDHCP_VERBOSE( 889 //usage: "\n -v Verbose" 890 //usage: ) 891 //usage: ) 892 //usage: IF_NOT_LONG_OPTS( 893 //usage: "\n -i IFACE Interface to use (default eth0)" 894 //usage: "\n -p FILE Create pidfile" 895 //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 896 //usage: "\n -t N Send up to N discover packets" 897 //usage: "\n -T N Pause between packets (default 3 seconds)" 898 //usage: "\n -A N Wait N seconds (default 20) after failure" 899 //usage: "\n -f Run in foreground" 900 //usage: USE_FOR_MMU( 901 //usage: "\n -b Background if lease is not obtained" 902 //usage: ) 903 //usage: "\n -n Exit if lease is not obtained" 904 //usage: "\n -q Exit after obtaining lease" 905 //usage: "\n -R Release IP on exit" 906 //usage: "\n -S Log to syslog too" 907 //usage: IF_FEATURE_UDHCP_PORT( 908 //usage: "\n -P N Use port N (default 68)" 909 //usage: ) 910 //usage: IF_FEATURE_UDHCPC_ARPING( 911 //usage: "\n -a Use arping to validate offered address" 912 //usage: ) 913 //usage: "\n -O OPT Request option OPT from server (cumulative)" 914 //usage: "\n -o Don't request any options (unless -O is given)" 915 //usage: "\n -r IP Request this IP address" 916 //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" 917 //usage: "\n Examples of string, numeric, and hex byte opts:" 918 //usage: "\n -x hostname:bbox - option 12" 919 //usage: "\n -x lease:3600 - option 51 (lease time)" 920 //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" 921 //usage: "\n -F NAME Ask server to update DNS mapping for NAME" 922 //usage: "\n -H,-h NAME Send NAME as client hostname (default none)" 923 //usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" 924 //usage: "\n -C Don't send MAC as client identifier" 925 //usage: IF_UDHCP_VERBOSE( 926 //usage: "\n -v Verbose" 927 //usage: ) 928 //usage: ) 929 930 int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 931 int udhcpc_main(int argc UNUSED_PARAM, char **argv) 145 932 { 146 933 uint8_t *temp, *message; 147 char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t; 934 const char *str_V, *str_h, *str_F, *str_r; 935 IF_FEATURE_UDHCP_PORT(char *str_P;) 936 void *clientid_mac_ptr; 937 llist_t *list_O = NULL; 938 llist_t *list_x = NULL; 939 int tryagain_timeout = 20; 940 int discover_timeout = 3; 941 int discover_retries = 3; 942 uint32_t server_addr = server_addr; /* for compiler */ 943 uint32_t requested_ip = 0; 148 944 uint32_t xid = 0; 149 uint32_t lease = 0; /* can be given as 32-bit quantity */150 unsigned t1 = 0, t2 = 0; /* what a wonderful names */151 unsigned start = 0;152 unsigned now;945 uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */ 946 int packet_num; 947 int timeout; /* must be signed */ 948 unsigned already_waited_sec; 153 949 unsigned opt; 154 950 int max_fd; 155 951 int retval; 156 int len;157 952 struct timeval tv; 158 struct in_addr temp_addr; 159 struct dhcpMessage packet; 953 struct dhcp_packet packet; 160 954 fd_set rfds; 161 955 162 enum { 163 OPT_c = 1 << 0, 164 OPT_C = 1 << 1, 165 OPT_V = 1 << 2, 166 OPT_f = 1 << 3, 167 OPT_b = 1 << 4, 168 OPT_H = 1 << 5, 169 OPT_h = 1 << 6, 170 OPT_F = 1 << 7, 171 OPT_i = 1 << 8, 172 OPT_n = 1 << 9, 173 OPT_p = 1 << 10, 174 OPT_q = 1 << 11, 175 OPT_R = 1 << 12, 176 OPT_r = 1 << 13, 177 OPT_s = 1 << 14, 178 OPT_T = 1 << 15, 179 OPT_t = 1 << 16, 180 OPT_v = 1 << 17, 181 OPT_S = 1 << 18, 182 }; 183 #if ENABLE_GETOPT_LONG 956 #if ENABLE_LONG_OPTS 184 957 static const char udhcpc_longopts[] ALIGN1 = 185 "clientid\0" Required_argument "c" 186 "clientid-none\0" No_argument "C" 187 "vendorclass\0" Required_argument "V" 188 "foreground\0" No_argument "f" 189 "background\0" No_argument "b" 190 "hostname\0" Required_argument "H" 191 "hostname\0" Required_argument "h" 192 "fqdn\0" Required_argument "F" 193 "interface\0" Required_argument "i" 194 "now\0" No_argument "n" 195 "pidfile\0" Required_argument "p" 196 "quit\0" No_argument "q" 197 "release\0" No_argument "R" 198 "request\0" Required_argument "r" 199 "script\0" Required_argument "s" 200 "timeout\0" Required_argument "T" 201 "version\0" No_argument "v" 202 "retries\0" Required_argument "t" 203 "syslog\0" No_argument "S" 958 "clientid-none\0" No_argument "C" 959 "vendorclass\0" Required_argument "V" 960 "hostname\0" Required_argument "H" 961 "fqdn\0" Required_argument "F" 962 "interface\0" Required_argument "i" 963 "now\0" No_argument "n" 964 "pidfile\0" Required_argument "p" 965 "quit\0" No_argument "q" 966 "release\0" No_argument "R" 967 "request\0" Required_argument "r" 968 "script\0" Required_argument "s" 969 "timeout\0" Required_argument "T" 970 "version\0" No_argument "v" 971 "retries\0" Required_argument "t" 972 "tryagain\0" Required_argument "A" 973 "syslog\0" No_argument "S" 974 "request-option\0" Required_argument "O" 975 "no-default-options\0" No_argument "o" 976 "foreground\0" No_argument "f" 977 "background\0" No_argument "b" 978 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") 979 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") 204 980 ; 205 981 #endif 206 /* Default options. */ 982 enum { 983 OPT_C = 1 << 0, 984 OPT_V = 1 << 1, 985 OPT_H = 1 << 2, 986 OPT_h = 1 << 3, 987 OPT_F = 1 << 4, 988 OPT_i = 1 << 5, 989 OPT_n = 1 << 6, 990 OPT_p = 1 << 7, 991 OPT_q = 1 << 8, 992 OPT_R = 1 << 9, 993 OPT_r = 1 << 10, 994 OPT_s = 1 << 11, 995 OPT_T = 1 << 12, 996 OPT_t = 1 << 13, 997 OPT_S = 1 << 14, 998 OPT_A = 1 << 15, 999 OPT_O = 1 << 16, 1000 OPT_o = 1 << 17, 1001 OPT_x = 1 << 18, 1002 OPT_f = 1 << 19, 1003 /* The rest has variable bit positions, need to be clever */ 1004 OPTBIT_f = 19, 1005 USE_FOR_MMU( OPTBIT_b,) 1006 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) 1007 IF_FEATURE_UDHCP_PORT( OPTBIT_P,) 1008 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) 1009 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) 1010 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) 1011 }; 1012 1013 /* Default options */ 1014 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) 1015 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) 207 1016 client_config.interface = "eth0"; 208 client_config.script = DEFAULT_SCRIPT; 209 client_config.retries = 3; 210 client_config.timeout = 3; 1017 client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; 1018 str_V = "udhcp "BB_VER; 211 1019 212 1020 /* Parse command line */ 213 opt_complementary = "c--C:C--c" // mutually exclusive214 ":hH:Hh"; // -h and -H are the same215 #if ENABLE_GETOPT_LONG216 applet_long_options = udhcpc_longopts;1021 /* O,x: list; -T,-t,-A take numeric param */ 1022 opt_complementary = "O::x::T+:t+:A+" 1023 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1024 ":vv" 217 1025 #endif 218 opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vS", 219 &str_c, &str_V, &str_h, &str_h, &str_F, 220 &client_config.interface, &client_config.pidfile, &str_r, 221 &client_config.script, &str_T, &str_t 1026 ; 1027 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1028 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f" 1029 USE_FOR_MMU("b") 1030 IF_FEATURE_UDHCPC_ARPING("a") 1031 IF_FEATURE_UDHCP_PORT("P:") 1032 "v" 1033 , &str_V, &str_h, &str_h, &str_F 1034 , &client_config.interface, &client_config.pidfile, &str_r /* i,p */ 1035 , &client_config.script /* s */ 1036 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ 1037 , &list_O 1038 , &list_x 1039 IF_FEATURE_UDHCP_PORT(, &str_P) 1040 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1041 , &dhcp_verbose 1042 #endif 222 1043 ); 223 224 if (opt & OPT_c) 225 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0); 226 //if (opt & OPT_C) 227 if (opt & OPT_V) 228 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); 229 if (opt & OPT_f) 230 client_config.foreground = 1; 231 if (opt & OPT_b) 232 client_config.background_if_no_lease = 1; 233 if (opt & OPT_h) 1044 if (opt & (OPT_h|OPT_H)) 234 1045 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); 235 1046 if (opt & OPT_F) { 1047 /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ 236 1048 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<4>com<0> not "host.domain.com" 241 N: 1 => Client requests Server to not update DNS 242 */ 1049 /* Flag bits: 0000NEOS 1050 * S: 1 = Client requests server to update A RR in DNS as well as PTR 1051 * O: 1 = Server indicates to client that DNS has been updated regardless 1052 * E: 1 = Name is in DNS format, i.e. <4>host<6>domain<3>com<0>, 1053 * not "host.domain.com". Format 0 is obsolete. 1054 * N: 1 = Client requests server to not update DNS (S must be 0 then) 1055 * Two [0] bytes which follow are deprecated and must be 0. 1056 */ 243 1057 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_i) client_config.interface = ... 248 if (opt & OPT_n) 249 client_config.abort_if_no_lease = 1; 250 // if (opt & OPT_p) client_config.pidfile = ... 251 if (opt & OPT_q) 252 client_config.quit_after_lease = 1; 253 if (opt & OPT_R) 254 client_config.release_on_quit = 1; 1058 /*client_config.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */ 1059 /*client_config.fqdn[OPT_DATA + 2] = 0; */ 1060 } 255 1061 if (opt & OPT_r) 256 1062 requested_ip = inet_addr(str_r); 257 // if (opt & OPT_s) client_config.script = ... 258 if (opt & OPT_T) 259 client_config.timeout = xatoi_u(str_T); 260 if (opt & OPT_t) 261 client_config.retries = xatoi_u(str_t); 262 if (opt & OPT_v) { 263 printf("version %s\n", BB_VER); 264 return 0; 265 } 266 1063 #if ENABLE_FEATURE_UDHCP_PORT 1064 if (opt & OPT_P) { 1065 CLIENT_PORT = xatou16(str_P); 1066 SERVER_PORT = CLIENT_PORT - 1; 1067 } 1068 #endif 1069 if (opt & OPT_o) 1070 client_config.no_default_options = 1; 1071 while (list_O) { 1072 char *optstr = llist_pop(&list_O); 1073 unsigned n = udhcp_option_idx(optstr); 1074 n = dhcp_optflags[n].code; 1075 client_config.opt_mask[n >> 3] |= 1 << (n & 7); 1076 } 1077 while (list_x) { 1078 char *optstr = llist_pop(&list_x); 1079 char *colon = strchr(optstr, ':'); 1080 if (colon) 1081 *colon = ' '; 1082 /* now it looks similar to udhcpd's config file line: 1083 * "optname optval", using the common routine: */ 1084 udhcp_str2optset(optstr, &client_config.options); 1085 } 1086 1087 if (udhcp_read_interface(client_config.interface, 1088 &client_config.ifindex, 1089 NULL, 1090 client_config.client_mac) 1091 ) { 1092 return 1; 1093 } 1094 1095 clientid_mac_ptr = NULL; 1096 if (!(opt & OPT_C) && !udhcp_find_option(client_config.options, DHCP_CLIENT_ID)) { 1097 /* not suppressed and not set, set the default client ID */ 1098 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); 1099 client_config.clientid[OPT_DATA] = 1; /* type: ethernet */ 1100 clientid_mac_ptr = client_config.clientid + OPT_DATA+1; 1101 memcpy(clientid_mac_ptr, client_config.client_mac, 6); 1102 } 1103 if (str_V[0] != '\0') 1104 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); 1105 #if !BB_MMU 1106 /* on NOMMU reexec (i.e., background) early */ 1107 if (!(opt & OPT_f)) { 1108 bb_daemonize_or_rexec(0 /* flags */, argv); 1109 logmode = LOGMODE_NONE; 1110 } 1111 #endif 267 1112 if (opt & OPT_S) { 268 openlog(applet_name, LOG_PID, LOG_ LOCAL0);1113 openlog(applet_name, LOG_PID, LOG_DAEMON); 269 1114 logmode |= LOGMODE_SYSLOG; 270 1115 } 271 272 if (read_interface(client_config.interface, &client_config.ifindex,273 NULL, client_config.arp))274 return 1;275 1116 276 1117 /* Make sure fd 0,1,2 are open */ … … 278 1119 /* Equivalent of doing a fflush after every \n */ 279 1120 setlinebuf(stdout); 280 281 1121 /* Create pidfile */ 282 1122 write_pidfile(client_config.pidfile); 283 /* if (!..) bb_perror_msg("cannot create pidfile %s", pidfile); */ 284 285 /* Goes to stdout and possibly syslog */ 286 bb_info_msg("%s (v%s) started", applet_name, BB_VER); 287 288 /* if not set, and not suppressed, setup the default client ID */ 289 if (!client_config.clientid && !(opt & OPT_C)) { 290 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); 291 client_config.clientid[OPT_DATA] = 1; 292 memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6); 293 } 294 295 if (!client_config.vendorclass) 296 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0); 297 298 /* setup the signal pipe */ 1123 /* Goes to stdout (unless NOMMU) and possibly syslog */ 1124 bb_info_msg("%s (v"BB_VER") started", applet_name); 1125 /* Set up the signal pipe */ 299 1126 udhcp_sp_setup(); 1127 /* We want random_xid to be random... */ 1128 srand(monotonic_us()); 300 1129 301 1130 state = INIT_SELECTING; 302 1131 udhcp_run_script(NULL, "deconfig"); 303 change_mode(LISTEN_RAW); 304 tv.tv_sec = 0; 305 goto jump_in; 306 1132 change_listen_mode(LISTEN_RAW); 1133 packet_num = 0; 1134 timeout = 0; 1135 already_waited_sec = 0; 1136 1137 /* Main event loop. select() waits on signal pipe and possibly 1138 * on sockfd. 1139 * "continue" statements in code below jump to the top of the loop. 1140 */ 307 1141 for (;;) { 308 tv.tv_sec = timeout - monotonic_sec(); 309 jump_in: 1142 /* silence "uninitialized!" warning */ 1143 unsigned timestamp_before_wait = timestamp_before_wait; 1144 1145 //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); 1146 1147 /* Was opening raw or udp socket here 1148 * if (listen_mode != LISTEN_NONE && sockfd < 0), 1149 * but on fast network renew responses return faster 1150 * than we open sockets. Thus this code is moved 1151 * to change_listen_mode(). Thus we open listen socket 1152 * BEFORE we send renew request (see "case BOUND:"). */ 1153 1154 max_fd = udhcp_sp_fd_set(&rfds, sockfd); 1155 1156 tv.tv_sec = timeout - already_waited_sec; 310 1157 tv.tv_usec = 0; 311 312 if (listen_mode != LISTEN_NONE && sockfd < 0) { 313 if (listen_mode == LISTEN_KERNEL) 314 sockfd = listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface); 315 else 316 sockfd = raw_socket(client_config.ifindex); 317 } 318 max_fd = udhcp_sp_fd_set(&rfds, sockfd); 319 320 retval = 0; /* If we already timed out, fall through, else... */ 321 if (tv.tv_sec > 0) { 322 DEBUG("Waiting on select..."); 1158 retval = 0; 1159 /* If we already timed out, fall through with retval = 0, else... */ 1160 if ((int)tv.tv_sec > 0) { 1161 timestamp_before_wait = (unsigned)monotonic_sec(); 1162 log1("Waiting on select..."); 323 1163 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 324 }325 326 now = monotonic_sec();327 if (retval < 0) {328 /* EINTR? signal was caught, don't panic */329 if (errno != EINTR) {1164 if (retval < 0) { 1165 /* EINTR? A signal was caught, don't panic */ 1166 if (errno == EINTR) { 1167 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1168 continue; 1169 } 330 1170 /* Else: an error occured, panic! */ 331 1171 bb_perror_msg_and_die("select"); 332 1172 } 333 } else if (retval == 0) { 334 /* timeout dropped to zero */ 1173 } 1174 1175 /* If timeout dropped to zero, time to become active: 1176 * resend discover/renew/whatever 1177 */ 1178 if (retval == 0) { 1179 /* When running on a bridge, the ifindex may have changed 1180 * (e.g. if member interfaces were added/removed 1181 * or if the status of the bridge changed). 1182 * Refresh ifindex and client_mac: 1183 */ 1184 if (udhcp_read_interface(client_config.interface, 1185 &client_config.ifindex, 1186 NULL, 1187 client_config.client_mac) 1188 ) { 1189 return 1; /* iface is gone? */ 1190 } 1191 if (clientid_mac_ptr) 1192 memcpy(clientid_mac_ptr, client_config.client_mac, 6); 1193 1194 /* We will restart the wait in any case */ 1195 already_waited_sec = 0; 1196 335 1197 switch (state) { 336 1198 case INIT_SELECTING: 337 if (packet_num < client_config.retries) {1199 if (packet_num < discover_retries) { 338 1200 if (packet_num == 0) 339 1201 xid = random_xid(); 340 341 /* send discover packet */ 342 send_discover(xid, requested_ip); /* broadcast */ 343 344 timeout = now + client_config.timeout; 1202 /* broadcast */ 1203 send_discover(xid, requested_ip); 1204 timeout = discover_timeout; 345 1205 packet_num++; 1206 continue; 1207 } 1208 leasefail: 1209 udhcp_run_script(NULL, "leasefail"); 1210 #if BB_MMU /* -b is not supported on NOMMU */ 1211 if (opt & OPT_b) { /* background if no lease */ 1212 bb_info_msg("No lease, forking to background"); 1213 client_background(); 1214 /* do not background again! */ 1215 opt = ((opt & ~OPT_b) | OPT_f); 1216 } else 1217 #endif 1218 if (opt & OPT_n) { /* abort if no lease */ 1219 bb_info_msg("No lease, failing"); 1220 retval = 1; 1221 goto ret; 1222 } 1223 /* wait before trying again */ 1224 timeout = tryagain_timeout; 1225 packet_num = 0; 1226 continue; 1227 case REQUESTING: 1228 if (packet_num < discover_retries) { 1229 /* send broadcast select packet */ 1230 send_select(xid, server_addr, requested_ip); 1231 timeout = discover_timeout; 1232 packet_num++; 1233 continue; 1234 } 1235 /* Timed out, go back to init state. 1236 * "discover...select...discover..." loops 1237 * were seen in the wild. Treat them similarly 1238 * to "no response to discover" case */ 1239 change_listen_mode(LISTEN_RAW); 1240 state = INIT_SELECTING; 1241 goto leasefail; 1242 case BOUND: 1243 /* 1/2 lease passed, enter renewing state */ 1244 state = RENEWING; 1245 change_listen_mode(LISTEN_KERNEL); 1246 log1("Entering renew state"); 1247 /* fall right through */ 1248 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1249 case_RENEW_REQUESTED: 1250 case RENEWING: 1251 if (timeout > 60) { 1252 /* send an unicast renew request */ 1253 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind 1254 * a new UDP socket for sending inside send_renew. 1255 * I hazard to guess existing listening socket 1256 * is somehow conflicting with it, but why is it 1257 * not deterministic then?! Strange. 1258 * Anyway, it does recover by eventually failing through 1259 * into INIT_SELECTING state. 1260 */ 1261 send_renew(xid, server_addr, requested_ip); 1262 timeout >>= 1; 1263 continue; 1264 } 1265 /* Timed out, enter rebinding state */ 1266 log1("Entering rebinding state"); 1267 state = REBINDING; 1268 /* fall right through */ 1269 case REBINDING: 1270 /* Switch to bcast receive */ 1271 change_listen_mode(LISTEN_RAW); 1272 /* Lease is *really* about to run out, 1273 * try to find DHCP server using broadcast */ 1274 if (timeout > 0) { 1275 /* send a broadcast renew request */ 1276 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); 1277 timeout >>= 1; 1278 continue; 1279 } 1280 /* Timed out, enter init state */ 1281 bb_info_msg("Lease lost, entering init state"); 1282 udhcp_run_script(NULL, "deconfig"); 1283 state = INIT_SELECTING; 1284 /*timeout = 0; - already is */ 1285 packet_num = 0; 1286 continue; 1287 /* case RELEASED: */ 1288 } 1289 /* yah, I know, *you* say it would never happen */ 1290 timeout = INT_MAX; 1291 continue; /* back to main loop */ 1292 } /* if select timed out */ 1293 1294 /* select() didn't timeout, something happened */ 1295 1296 /* Is it a signal? */ 1297 /* note: udhcp_sp_read checks FD_ISSET before reading */ 1298 switch (udhcp_sp_read(&rfds)) { 1299 case SIGUSR1: 1300 perform_renew(); 1301 if (state == RENEW_REQUESTED) 1302 goto case_RENEW_REQUESTED; 1303 /* Start things over */ 1304 packet_num = 0; 1305 /* Kill any timeouts, user wants this to hurry along */ 1306 timeout = 0; 1307 continue; 1308 case SIGUSR2: 1309 perform_release(requested_ip, server_addr); 1310 timeout = INT_MAX; 1311 continue; 1312 case SIGTERM: 1313 bb_info_msg("Received SIGTERM"); 1314 if (opt & OPT_R) /* release on quit */ 1315 perform_release(requested_ip, server_addr); 1316 goto ret0; 1317 } 1318 1319 /* Is it a packet? */ 1320 if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds)) 1321 continue; /* no */ 1322 1323 { 1324 int len; 1325 1326 /* A packet is ready, read it */ 1327 if (listen_mode == LISTEN_KERNEL) 1328 len = udhcp_recv_kernel_packet(&packet, sockfd); 1329 else 1330 len = udhcp_recv_raw_packet(&packet, sockfd); 1331 if (len == -1) { 1332 /* Error is severe, reopen socket */ 1333 bb_info_msg("Read error: %s, reopening socket", strerror(errno)); 1334 sleep(discover_timeout); /* 3 seconds by default */ 1335 change_listen_mode(listen_mode); /* just close and reopen */ 1336 } 1337 /* If this packet will turn out to be unrelated/bogus, 1338 * we will go back and wait for next one. 1339 * Be sure timeout is properly decreased. */ 1340 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1341 if (len < 0) 1342 continue; 1343 } 1344 1345 if (packet.xid != xid) { 1346 log1("xid %x (our is %x), ignoring packet", 1347 (unsigned)packet.xid, (unsigned)xid); 1348 continue; 1349 } 1350 1351 /* Ignore packets that aren't for us */ 1352 if (packet.hlen != 6 1353 || memcmp(packet.chaddr, client_config.client_mac, 6) != 0 1354 ) { 1355 //FIXME: need to also check that last 10 bytes are zero 1356 log1("chaddr does not match, ignoring packet"); // log2? 1357 continue; 1358 } 1359 1360 message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); 1361 if (message == NULL) { 1362 bb_error_msg("no message type option, ignoring packet"); 1363 continue; 1364 } 1365 1366 switch (state) { 1367 case INIT_SELECTING: 1368 /* Must be a DHCPOFFER to one of our xid's */ 1369 if (*message == DHCPOFFER) { 1370 /* TODO: why we don't just fetch server's IP from IP header? */ 1371 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1372 if (!temp) { 1373 bb_error_msg("no server ID, ignoring packet"); 1374 continue; 1375 /* still selecting - this server looks bad */ 1376 } 1377 /* it IS unaligned sometimes, don't "optimize" */ 1378 move_from_unaligned32(server_addr, temp); 1379 /*xid = packet.xid; - already is */ 1380 requested_ip = packet.yiaddr; 1381 1382 /* enter requesting state */ 1383 state = REQUESTING; 1384 timeout = 0; 1385 packet_num = 0; 1386 already_waited_sec = 0; 1387 } 1388 continue; 1389 case REQUESTING: 1390 case RENEWING: 1391 case RENEW_REQUESTED: 1392 case REBINDING: 1393 if (*message == DHCPACK) { 1394 temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); 1395 if (!temp) { 1396 bb_error_msg("no lease time with ACK, using 1 hour lease"); 1397 lease_seconds = 60 * 60; 346 1398 } else { 347 udhcp_run_script(NULL, "leasefail"); 348 if (client_config.background_if_no_lease) { 349 bb_info_msg("No lease, forking to background"); 350 client_background(); 351 } else if (client_config.abort_if_no_lease) { 352 bb_info_msg("No lease, failing"); 353 retval = 1; 354 goto ret; 355 } 356 /* wait to try again */ 357 packet_num = 0; 358 timeout = now + 60; 1399 /* it IS unaligned sometimes, don't "optimize" */ 1400 move_from_unaligned32(lease_seconds, temp); 1401 lease_seconds = ntohl(lease_seconds); 1402 lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */ 1403 if (lease_seconds < 10) /* and not too small */ 1404 lease_seconds = 10; 359 1405 } 360 break; 361 case RENEW_REQUESTED: 362 case REQUESTING: 363 if (packet_num < client_config.retries) { 364 /* send request packet */ 365 if (state == RENEW_REQUESTED) 366 send_renew(xid, server_addr, requested_ip); /* unicast */ 367 else send_selecting(xid, server_addr, requested_ip); /* broadcast */ 368 369 timeout = now + ((packet_num == 2) ? 10 : 2); 370 packet_num++; 371 } else { 372 /* timed out, go back to init state */ 373 if (state == RENEW_REQUESTED) 374 udhcp_run_script(NULL, "deconfig"); 375 state = INIT_SELECTING; 376 timeout = now; 377 packet_num = 0; 378 change_mode(LISTEN_RAW); 379 } 380 break; 381 case BOUND: 382 /* Lease is starting to run out, time to enter renewing state */ 383 state = RENEWING; 384 change_mode(LISTEN_KERNEL); 385 DEBUG("Entering renew state"); 386 /* fall right through */ 387 case RENEWING: 388 /* Either set a new T1, or enter REBINDING state */ 389 if ((t2 - t1) <= (lease / 14400 + 1)) { 390 /* timed out, enter rebinding state */ 391 state = REBINDING; 392 timeout = now + (t2 - t1); 393 DEBUG("Entering rebinding state"); 394 } else { 395 /* send a request packet */ 396 send_renew(xid, server_addr, requested_ip); /* unicast */ 397 t1 = (t2 - t1) / 2 + t1; 398 timeout = start + t1; 399 } 400 break; 401 case REBINDING: 402 /* Either set a new T2, or enter INIT state */ 403 if ((lease - t2) <= (lease / 14400 + 1)) { 404 /* timed out, enter init state */ 405 state = INIT_SELECTING; 406 bb_info_msg("Lease lost, entering init state"); 407 udhcp_run_script(NULL, "deconfig"); 408 timeout = now; 409 packet_num = 0; 410 change_mode(LISTEN_RAW); 411 } else { 412 /* send a request packet */ 413 send_renew(xid, 0, requested_ip); /* broadcast */ 414 t2 = (lease - t2) / 2 + t2; 415 timeout = start + t2; 416 } 417 break; 418 case RELEASED: 419 /* yah, I know, *you* say it would never happen */ 420 timeout = INT_MAX; 421 break; 422 } 423 } else if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) { 424 /* a packet is ready, read it */ 425 426 if (listen_mode == LISTEN_KERNEL) 427 len = udhcp_get_packet(&packet, sockfd); 428 else len = get_raw_packet(&packet, sockfd); 429 430 if (len == -1 && errno != EINTR) { 431 DEBUG("error on read, %s, reopening socket", strerror(errno)); 432 change_mode(listen_mode); /* just close and reopen */ 433 } 434 if (len < 0) continue; 435 436 if (packet.xid != xid) { 437 DEBUG("Ignoring XID %x (our xid is %x)", 438 (unsigned)packet.xid, (unsigned)xid); 439 continue; 440 } 441 442 /* Ignore packets that aren't for us */ 443 if (memcmp(packet.chaddr, client_config.arp, 6)) { 444 DEBUG("Packet does not have our chaddr - ignoring"); 445 continue; 446 } 447 448 message = get_option(&packet, DHCP_MESSAGE_TYPE); 449 if (message == NULL) { 450 bb_error_msg("cannot get option from packet - ignoring"); 451 continue; 452 } 453 454 switch (state) { 455 case INIT_SELECTING: 456 /* Must be a DHCPOFFER to one of our xid's */ 457 if (*message == DHCPOFFER) { 458 temp = get_option(&packet, DHCP_SERVER_ID); 459 if (temp) { 460 /* can be misaligned, thus memcpy */ 461 memcpy(&server_addr, temp, 4); 462 xid = packet.xid; 463 requested_ip = packet.yiaddr; 464 465 /* enter requesting state */ 466 state = REQUESTING; 467 timeout = now; 1406 #if ENABLE_FEATURE_UDHCPC_ARPING 1407 if (opt & OPT_a) { 1408 /* RFC 2131 3.1 paragraph 5: 1409 * "The client receives the DHCPACK message with configuration 1410 * parameters. The client SHOULD perform a final check on the 1411 * parameters (e.g., ARP for allocated network address), and notes 1412 * the duration of the lease specified in the DHCPACK message. At this 1413 * point, the client is configured. If the client detects that the 1414 * address is already in use (e.g., through the use of ARP), 1415 * the client MUST send a DHCPDECLINE message to the server and restarts 1416 * the configuration process..." */ 1417 if (!arpping(packet.yiaddr, 1418 NULL, 1419 (uint32_t) 0, 1420 client_config.client_mac, 1421 client_config.interface) 1422 ) { 1423 bb_info_msg("Offered address is in use " 1424 "(got ARP reply), declining"); 1425 send_decline(xid, server_addr, packet.yiaddr); 1426 1427 if (state != REQUESTING) 1428 udhcp_run_script(NULL, "deconfig"); 1429 change_listen_mode(LISTEN_RAW); 1430 state = INIT_SELECTING; 1431 requested_ip = 0; 1432 timeout = tryagain_timeout; 468 1433 packet_num = 0; 469 } else {470 bb_error_msg("no server ID in message");1434 already_waited_sec = 0; 1435 continue; /* back to main loop */ 471 1436 } 472 1437 } 473 break; 474 case RENEW_REQUESTED: 475 case REQUESTING: 476 case RENEWING: 477 case REBINDING: 478 if (*message == DHCPACK) { 479 temp = get_option(&packet, DHCP_LEASE_TIME); 480 if (!temp) { 481 bb_error_msg("no lease time with ACK, using 1 hour lease"); 482 lease = 60 * 60; 483 } else { 484 /* can be misaligned, thus memcpy */ 485 memcpy(&lease, temp, 4); 486 lease = ntohl(lease); 487 } 488 489 /* enter bound state */ 490 t1 = lease / 2; 491 492 /* little fixed point for n * .875 */ 493 t2 = (lease * 7) >> 3; 1438 #endif 1439 /* enter bound state */ 1440 timeout = lease_seconds / 2; 1441 { 1442 struct in_addr temp_addr; 494 1443 temp_addr.s_addr = packet.yiaddr; 495 1444 bb_info_msg("Lease of %s obtained, lease time %u", 496 inet_ntoa(temp_addr), (unsigned)lease); 497 start = now; 498 timeout = start + t1; 499 requested_ip = packet.yiaddr; 500 udhcp_run_script(&packet, 501 ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); 502 503 state = BOUND; 504 change_mode(LISTEN_NONE); 505 if (client_config.quit_after_lease) { 506 if (client_config.release_on_quit) 507 perform_release(); 508 goto ret0; 509 } 510 if (!client_config.foreground) 511 client_background(); 512 513 } else if (*message == DHCPNAK) { 514 /* return to init state */ 515 bb_info_msg("Received DHCP NAK"); 516 udhcp_run_script(&packet, "nak"); 517 if (state != REQUESTING) 518 udhcp_run_script(NULL, "deconfig"); 519 state = INIT_SELECTING; 520 timeout = now; 521 requested_ip = 0; 522 packet_num = 0; 523 change_mode(LISTEN_RAW); 524 sleep(3); /* avoid excessive network traffic */ 1445 inet_ntoa(temp_addr), (unsigned)lease_seconds); 525 1446 } 526 break; 527 /* case BOUND, RELEASED: - ignore all packets */ 1447 requested_ip = packet.yiaddr; 1448 udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); 1449 1450 state = BOUND; 1451 change_listen_mode(LISTEN_NONE); 1452 if (opt & OPT_q) { /* quit after lease */ 1453 if (opt & OPT_R) /* release on quit */ 1454 perform_release(requested_ip, server_addr); 1455 goto ret0; 1456 } 1457 /* future renew failures should not exit (JM) */ 1458 opt &= ~OPT_n; 1459 #if BB_MMU /* NOMMU case backgrounded earlier */ 1460 if (!(opt & OPT_f)) { 1461 client_background(); 1462 /* do not background again! */ 1463 opt = ((opt & ~OPT_b) | OPT_f); 1464 } 1465 #endif 1466 already_waited_sec = 0; 1467 continue; /* back to main loop */ 528 1468 } 529 } else { 530 int signo = udhcp_sp_read(&rfds); 531 switch (signo) { 532 case SIGUSR1: 533 perform_renew(); 534 break; 535 case SIGUSR2: 536 perform_release(); 537 break; 538 case SIGTERM: 539 bb_info_msg("Received SIGTERM"); 540 if (client_config.release_on_quit) 541 perform_release(); 542 goto ret0; 1469 if (*message == DHCPNAK) { 1470 /* return to init state */ 1471 bb_info_msg("Received DHCP NAK"); 1472 udhcp_run_script(&packet, "nak"); 1473 if (state != REQUESTING) 1474 udhcp_run_script(NULL, "deconfig"); 1475 change_listen_mode(LISTEN_RAW); 1476 sleep(3); /* avoid excessive network traffic */ 1477 state = INIT_SELECTING; 1478 requested_ip = 0; 1479 timeout = 0; 1480 packet_num = 0; 1481 already_waited_sec = 0; 543 1482 } 1483 continue; 1484 /* case BOUND: - ignore all packets */ 1485 /* case RELEASED: - ignore all packets */ 544 1486 } 545 } /* for (;;) */ 1487 /* back to main loop */ 1488 } /* for (;;) - main loop ends */ 1489 546 1490 ret0: 547 1491 retval = 0; 548 1492 ret: 549 /*if (client_config.pidfile) - remove_pidfile has it 's own check */1493 /*if (client_config.pidfile) - remove_pidfile has its own check */ 550 1494 remove_pidfile(client_config.pidfile); 551 1495 return retval;
Note:
See TracChangeset
for help on using the changeset viewer.