1/* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2012 Roy Marples <roy@marples.name> 4 * All rights reserved 5 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <ctype.h> 29#include <errno.h> 30#include <fcntl.h> 31#include <stdlib.h> 32#include <string.h> 33#include <syslog.h> 34#include <unistd.h> 35 36#include "config.h" 37#include "common.h" 38#include "dhcp.h" 39 40#define REQUEST (1 << 0) 41#define UINT8 (1 << 1) 42#define UINT16 (1 << 2) 43#define SINT16 (1 << 3) 44#define UINT32 (1 << 4) 45#define SINT32 (1 << 5) 46#define IPV4 (1 << 6) 47#define STRING (1 << 7) 48#define PAIR (1 << 8) 49#define ARRAY (1 << 9) 50#define RFC3361 (1 << 10) 51#define RFC3397 (1 << 11) 52#define RFC3442 (1 << 12) 53#define RFC5969 (1 << 13) 54 55#define IPV4R IPV4 | REQUEST 56 57#define DAD "Duplicate address detected" 58 59/* Our aggregate option buffer. 60 * We ONLY use this when options are split, which for most purposes is 61 * practically never. See RFC3396 for details. */ 62static uint8_t *opt_buffer; 63 64struct dhcp_opt { 65 uint8_t option; 66 int type; 67 const char *var; 68}; 69 70static const struct dhcp_opt const dhcp_opts[] = { 71 { 1, IPV4 | REQUEST, "subnet_mask" }, 72 /* RFC 3442 states that the CSR has to come before all other 73 * routes. For completeness, we also specify static routes, 74 * then routers. */ 75 { 121, RFC3442, "classless_static_routes" }, 76 { 249, RFC3442, "ms_classless_static_routes" }, 77 { 33, IPV4 | ARRAY | REQUEST, "static_routes" }, 78 { 3, IPV4 | ARRAY | REQUEST, "routers" }, 79 { 2, UINT32, "time_offset" }, 80 { 4, IPV4 | ARRAY, "time_servers" }, 81 { 5, IPV4 | ARRAY, "ien116_name_servers" }, 82 { 6, IPV4 | ARRAY, "domain_name_servers" }, 83 { 7, IPV4 | ARRAY, "log_servers" }, 84 { 8, IPV4 | ARRAY, "cookie_servers" }, 85 { 9, IPV4 | ARRAY, "lpr_servers" }, 86 { 10, IPV4 | ARRAY, "impress_servers" }, 87 { 11, IPV4 | ARRAY, "resource_location_servers" }, 88 { 12, STRING, "host_name" }, 89 { 13, UINT16, "boot_size" }, 90 { 14, STRING, "merit_dump" }, 91 { 15, STRING, "domain_name" }, 92 { 16, IPV4, "swap_server" }, 93 { 17, STRING, "root_path" }, 94 { 18, STRING, "extensions_path" }, 95 { 19, UINT8, "ip_forwarding" }, 96 { 20, UINT8, "non_local_source_routing" }, 97 { 21, IPV4 | ARRAY, "policy_filter" }, 98 { 22, SINT16, "max_dgram_reassembly" }, 99 { 23, UINT16, "default_ip_ttl" }, 100 { 24, UINT32, "path_mtu_aging_timeout" }, 101 { 25, UINT16 | ARRAY, "path_mtu_plateau_table" }, 102 { 26, UINT16, "interface_mtu" }, 103 { 27, UINT8, "all_subnets_local" }, 104 { 28, IPV4 | REQUEST, "broadcast_address" }, 105 { 29, UINT8, "perform_mask_discovery" }, 106 { 30, UINT8, "mask_supplier" }, 107 { 31, UINT8, "router_discovery" }, 108 { 32, IPV4, "router_solicitation_address" }, 109 { 34, UINT8, "trailer_encapsulation" }, 110 { 35, UINT32, "arp_cache_timeout" }, 111 { 36, UINT16, "ieee802_3_encapsulation" }, 112 { 37, UINT8, "default_tcp_ttl" }, 113 { 38, UINT32, "tcp_keepalive_interval" }, 114 { 39, UINT8, "tcp_keepalive_garbage" }, 115 { 40, STRING, "nis_domain" }, 116 { 41, IPV4 | ARRAY, "nis_servers" }, 117 { 42, IPV4 | ARRAY, "ntp_servers" }, 118 { 43, STRING, "vendor_encapsulated_options" }, 119 { 44, IPV4 | ARRAY, "netbios_name_servers" }, 120 { 45, IPV4, "netbios_dd_server" }, 121 { 46, UINT8, "netbios_node_type" }, 122 { 47, STRING, "netbios_scope" }, 123 { 48, IPV4 | ARRAY, "font_servers" }, 124 { 49, IPV4 | ARRAY, "x_display_manager" }, 125 { 50, IPV4, "dhcp_requested_address" }, 126 { 51, UINT32 | REQUEST, "dhcp_lease_time" }, 127 { 52, UINT8, "dhcp_option_overload" }, 128 { 53, UINT8, "dhcp_message_type" }, 129 { 54, IPV4, "dhcp_server_identifier" }, 130 { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" }, 131 { 56, STRING, "dhcp_message" }, 132 { 57, UINT16, "dhcp_max_message_size" }, 133 { 58, UINT32 | REQUEST, "dhcp_renewal_time" }, 134 { 59, UINT32 | REQUEST, "dhcp_rebinding_time" }, 135 { 64, STRING, "nisplus_domain" }, 136 { 65, IPV4 | ARRAY, "nisplus_servers" }, 137 { 66, STRING, "tftp_server_name" }, 138 { 67, STRING, "bootfile_name" }, 139 { 68, IPV4 | ARRAY, "mobile_ip_home_agent" }, 140 { 69, IPV4 | ARRAY, "smtp_server" }, 141 { 70, IPV4 | ARRAY, "pop_server" }, 142 { 71, IPV4 | ARRAY, "nntp_server" }, 143 { 72, IPV4 | ARRAY, "www_server" }, 144 { 73, IPV4 | ARRAY, "finger_server" }, 145 { 74, IPV4 | ARRAY, "irc_server" }, 146 { 75, IPV4 | ARRAY, "streettalk_server" }, 147 { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" }, 148 { 77, STRING, "user_class" }, 149 { 81, STRING | RFC3397, "fqdn_name" }, 150 { 85, IPV4 | ARRAY, "nds_servers" }, 151 { 86, STRING, "nds_tree_name" }, 152 { 87, STRING, "nds_context" }, 153 { 88, STRING | RFC3397, "bcms_controller_names" }, 154 { 89, IPV4 | ARRAY, "bcms_controller_address" }, 155 { 91, UINT32, "client_last_transaction_time" }, 156 { 92, IPV4 | ARRAY, "associated_ip" }, 157 { 98, STRING, "uap_servers" }, 158 { 112, IPV4 | ARRAY, "netinfo_server_address" }, 159 { 113, STRING, "netinfo_server_tag" }, 160 { 114, STRING, "default_url" }, 161 { 118, IPV4, "subnet_selection" }, 162 { 119, STRING | RFC3397, "domain_search" }, 163 { 120, STRING | RFC3361, "sip_server" }, 164 { 212, RFC5969, "sixrd" }, 165 { 0, 0, NULL } 166}; 167 168static const char *if_params[] = { 169 "interface", 170 "reason", 171 "pid", 172 "ifmetric", 173 "ifwireless", 174 "ifflags", 175 "profile", 176 "interface_order", 177 NULL 178}; 179 180static const char *dhcp_params[] = { 181 "ip_address", 182 "subnet_cidr", 183 "network_number", 184 "ssid", 185 "filename", 186 "server_name", 187 NULL 188}; 189 190void 191print_options(void) 192{ 193 const struct dhcp_opt *opt; 194 const char **p; 195 196 for (p = if_params; *p; p++) 197 printf(" - %s\n", *p); 198 199 for (p = dhcp_params; *p; p++) 200 printf(" %s\n", *p); 201 202 for (opt = dhcp_opts; opt->option; opt++) 203 if (opt->var) 204 printf("%03d %s\n", opt->option, opt->var); 205} 206 207int make_option_mask(uint8_t *mask, const char *opts, int add) 208{ 209 char *token, *o, *p, *t; 210 const struct dhcp_opt *opt; 211 int match, n; 212 213 o = p = xstrdup(opts); 214 while ((token = strsep(&p, ", "))) { 215 if (*token == '\0') 216 continue; 217 for (opt = dhcp_opts; opt->option; opt++) { 218 if (!opt->var) 219 continue; 220 match = 0; 221 if (strcmp(opt->var, token) == 0) 222 match = 1; 223 else { 224 errno = 0; 225 n = strtol(token, &t, 0); 226 if (errno == 0 && !*t) 227 if (opt->option == n) 228 match = 1; 229 } 230 if (match) { 231 if (add == 2 && !(opt->type & IPV4)) { 232 free(o); 233 errno = EINVAL; 234 return -1; 235 } 236 if (add == 1 || add == 2) 237 add_option_mask(mask, 238 opt->option); 239 else 240 del_option_mask(mask, 241 opt->option); 242 break; 243 } 244 } 245 if (!opt->option) { 246 free(o); 247 errno = ENOENT; 248 return -1; 249 } 250 } 251 free(o); 252 return 0; 253} 254 255static int 256valid_length(uint8_t option, int dl, int *type) 257{ 258 const struct dhcp_opt *opt; 259 ssize_t sz; 260 261 if (dl == 0) 262 return -1; 263 264 for (opt = dhcp_opts; opt->option; opt++) { 265 if (opt->option != option) 266 continue; 267 268 if (type) 269 *type = opt->type; 270 271 if (opt->type == 0 || 272 opt->type & (STRING | RFC3442 | RFC5969)) 273 return 0; 274 275 if (opt->type & IPV4 && opt->type & ARRAY) 276 return (dl % sizeof(uint32_t) == 0 ? 0 : -1); 277 278 sz = 0; 279 if (opt->type & (UINT32 | IPV4)) 280 sz = sizeof(uint32_t); 281 if (opt->type & UINT16) 282 sz = sizeof(uint16_t); 283 if (opt->type & UINT8) 284 sz = sizeof(uint8_t); 285 /* If we don't know the size, assume it's valid */ 286 return (sz == 0 || dl == sz ? 0 : -1); 287 } 288 289 /* unknown option, so let it pass */ 290 return 0; 291} 292 293#ifdef DEBUG_MEMORY 294static void 295free_option_buffer(void) 296{ 297 free(opt_buffer); 298} 299#endif 300 301#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL) 302static const uint8_t * 303get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type) 304{ 305 const uint8_t *p = dhcp->options; 306 const uint8_t *e = p + sizeof(dhcp->options); 307 uint8_t l, ol = 0; 308 uint8_t o = 0; 309 uint8_t overl = 0; 310 uint8_t *bp = NULL; 311 const uint8_t *op = NULL; 312 int bl = 0; 313 314 while (p < e) { 315 o = *p++; 316 if (o == opt) { 317 if (op) { 318 if (!opt_buffer) { 319 opt_buffer = xmalloc(sizeof(*dhcp)); 320#ifdef DEBUG_MEMORY 321 atexit(free_option_buffer); 322#endif 323 } 324 if (!bp) 325 bp = opt_buffer; 326 memcpy(bp, op, ol); 327 bp += ol; 328 } 329 ol = *p; 330 op = p + 1; 331 bl += ol; 332 } 333 switch (o) { 334 case DHO_PAD: 335 continue; 336 case DHO_END: 337 if (overl & 1) { 338 /* bit 1 set means parse boot file */ 339 overl &= ~1; 340 p = dhcp->bootfile; 341 e = p + sizeof(dhcp->bootfile); 342 } else if (overl & 2) { 343 /* bit 2 set means parse server name */ 344 overl &= ~2; 345 p = dhcp->servername; 346 e = p + sizeof(dhcp->servername); 347 } else 348 goto exit; 349 break; 350 case DHO_OPTIONSOVERLOADED: 351 /* Ensure we only get this option once */ 352 if (!overl) 353 overl = p[1]; 354 break; 355 } 356 l = *p++; 357 p += l; 358 } 359 360exit: 361 if (valid_length(opt, bl, type) == -1) { 362 errno = EINVAL; 363 return NULL; 364 } 365 if (len) 366 *len = bl; 367 if (bp) { 368 memcpy(bp, op, ol); 369 return (const uint8_t *)opt_buffer; 370 } 371 if (op) 372 return op; 373 errno = ENOENT; 374 return NULL; 375} 376 377int 378get_option_addr(struct in_addr *a, const struct dhcp_message *dhcp, 379 uint8_t option) 380{ 381 const uint8_t *p = get_option_raw(dhcp, option); 382 383 if (!p) 384 return -1; 385 memcpy(&a->s_addr, p, sizeof(a->s_addr)); 386 return 0; 387} 388 389int 390get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) 391{ 392 const uint8_t *p = get_option_raw(dhcp, option); 393 uint32_t d; 394 395 if (!p) 396 return -1; 397 memcpy(&d, p, sizeof(d)); 398 *i = ntohl(d); 399 return 0; 400} 401 402int 403get_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option) 404{ 405 const uint8_t *p = get_option_raw(dhcp, option); 406 uint16_t d; 407 408 if (!p) 409 return -1; 410 memcpy(&d, p, sizeof(d)); 411 *i = ntohs(d); 412 return 0; 413} 414 415int 416get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option) 417{ 418 const uint8_t *p = get_option_raw(dhcp, option); 419 420 if (!p) 421 return -1; 422 if (i) 423 *i = *(p); 424 return 0; 425} 426 427/* Decode an RFC3397 DNS search order option into a space 428 * separated string. Returns length of string (including 429 * terminating zero) or zero on error. out may be NULL 430 * to just determine output length. */ 431ssize_t 432decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p) 433{ 434 const uint8_t *r, *q = p; 435 int count = 0, l, hops; 436 uint8_t ltype; 437 438 while (q - p < pl) { 439 r = NULL; 440 hops = 0; 441 /* We check we are inside our length again incase 442 * the data is NOT terminated correctly. */ 443 while ((l = *q++) && q - p < pl) { 444 ltype = l & 0xc0; 445 if (ltype == 0x80 || ltype == 0x40) 446 return 0; 447 else if (ltype == 0xc0) { /* pointer */ 448 l = (l & 0x3f) << 8; 449 l |= *q++; 450 /* save source of first jump. */ 451 if (!r) 452 r = q; 453 hops++; 454 if (hops > 255) 455 return 0; 456 q = p + l; 457 if (q - p >= pl) 458 return 0; 459 } else { 460 /* straightforward name segment, add with '.' */ 461 count += l + 1; 462 if (out) { 463 if ((ssize_t)l + 1 > len) { 464 errno = ENOBUFS; 465 return -1; 466 } 467 memcpy(out, q, l); 468 out += l; 469 *out++ = '.'; 470 len -= l; 471 len--; 472 } 473 q += l; 474 } 475 } 476 /* change last dot to space */ 477 if (out) 478 *(out - 1) = ' '; 479 if (r) 480 q = r; 481 } 482 483 /* change last space to zero terminator */ 484 if (out) 485 *(out - 1) = 0; 486 487 return count; 488} 489 490static ssize_t 491decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p) 492{ 493 const uint8_t *e; 494 ssize_t b, bytes = 0, ocets; 495 uint8_t cidr; 496 struct in_addr addr; 497 char *o = out; 498 499 /* Minimum is 5 -first is CIDR and a router length of 4 */ 500 if (pl < 5) { 501 errno = EINVAL; 502 return -1; 503 } 504 505 e = p + pl; 506 while (p < e) { 507 cidr = *p++; 508 if (cidr > 32) { 509 errno = EINVAL; 510 return -1; 511 } 512 ocets = (cidr + 7) / 8; 513 if (!out) { 514 p += 4 + ocets; 515 bytes += ((4 * 4) * 2) + 4; 516 continue; 517 } 518 if ((((4 * 4) * 2) + 4) > len) { 519 errno = ENOBUFS; 520 return -1; 521 } 522 if (o != out) { 523 *o++ = ' '; 524 len--; 525 } 526 /* If we have ocets then we have a destination and netmask */ 527 if (ocets > 0) { 528 addr.s_addr = 0; 529 memcpy(&addr.s_addr, p, ocets); 530 b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr); 531 p += ocets; 532 } else 533 b = snprintf(o, len, "0.0.0.0/0"); 534 o += b; 535 len -= b; 536 537 /* Finally, snag the router */ 538 memcpy(&addr.s_addr, p, 4); 539 p += 4; 540 b = snprintf(o, len, " %s", inet_ntoa(addr)); 541 o += b; 542 len -= b; 543 } 544 545 if (out) 546 return o - out; 547 return bytes; 548} 549 550static struct rt * 551decode_rfc3442_rt(int dl, const uint8_t *data) 552{ 553 const uint8_t *p = data; 554 const uint8_t *e; 555 uint8_t cidr; 556 size_t ocets; 557 struct rt *routes = NULL; 558 struct rt *rt = NULL; 559 560 /* Minimum is 5 -first is CIDR and a router length of 4 */ 561 if (dl < 5) 562 return NULL; 563 564 e = p + dl; 565 while (p < e) { 566 cidr = *p++; 567 if (cidr > 32) { 568 free_routes(routes); 569 errno = EINVAL; 570 return NULL; 571 } 572 573 if (rt) { 574 rt->next = xzalloc(sizeof(*rt)); 575 rt = rt->next; 576 } else { 577 routes = rt = xzalloc(sizeof(*routes)); 578 } 579 rt->next = NULL; 580 581 ocets = (cidr + 7) / 8; 582 /* If we have ocets then we have a destination and netmask */ 583 if (ocets > 0) { 584 memcpy(&rt->dest.s_addr, p, ocets); 585 p += ocets; 586 rt->net.s_addr = htonl(~0U << (32 - cidr)); 587 } 588 589 /* Finally, snag the router */ 590 memcpy(&rt->gate.s_addr, p, 4); 591 p += 4; 592 } 593 return routes; 594} 595 596static char * 597decode_rfc3361(int dl, const uint8_t *data) 598{ 599 uint8_t enc; 600 unsigned int l; 601 char *sip = NULL; 602 struct in_addr addr; 603 char *p; 604 605 if (dl < 2) { 606 errno = EINVAL; 607 return 0; 608 } 609 610 enc = *data++; 611 dl--; 612 switch (enc) { 613 case 0: 614 if ((l = decode_rfc3397(NULL, 0, dl, data)) > 0) { 615 sip = xmalloc(l); 616 decode_rfc3397(sip, l, dl, data); 617 } 618 break; 619 case 1: 620 if (dl == 0 || dl % 4 != 0) { 621 errno = EINVAL; 622 break; 623 } 624 addr.s_addr = INADDR_BROADCAST; 625 l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1; 626 sip = p = xmalloc(l); 627 while (dl != 0) { 628 memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 629 data += sizeof(addr.s_addr); 630 p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr)); 631 dl -= sizeof(addr.s_addr); 632 } 633 *--p = '\0'; 634 break; 635 default: 636 errno = EINVAL; 637 return 0; 638 } 639 640 return sip; 641} 642 643/* Decode an RFC5969 6rd order option into a space 644 * separated string. Returns length of string (including 645 * terminating zero) or zero on error. */ 646static ssize_t 647decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p) 648{ 649 uint8_t ipv4masklen, ipv6prefixlen; 650 uint8_t ipv6prefix[16]; 651 uint8_t br[4]; 652 int i; 653 ssize_t b, bytes = 0; 654 655 if (pl < 22) { 656 errno = EINVAL; 657 return 0; 658 } 659 660 ipv4masklen = *p++; 661 pl--; 662 ipv6prefixlen = *p++; 663 pl--; 664 665 for (i = 0; i < 16; i++) { 666 ipv6prefix[i] = *p++; 667 pl--; 668 } 669 if (out) { 670 b= snprintf(out, len, 671 "%d %d " 672 "%02x%02x:%02x%02x:" 673 "%02x%02x:%02x%02x:" 674 "%02x%02x:%02x%02x:" 675 "%02x%02x:%02x%02x", 676 ipv4masklen, ipv6prefixlen, 677 ipv6prefix[0], ipv6prefix[1], ipv6prefix[2], ipv6prefix[3], 678 ipv6prefix[4], ipv6prefix[5], ipv6prefix[6], ipv6prefix[7], 679 ipv6prefix[8], ipv6prefix[9], ipv6prefix[10],ipv6prefix[11], 680 ipv6prefix[12],ipv6prefix[13],ipv6prefix[14], ipv6prefix[15] 681 ); 682 683 len -= b; 684 out += b; 685 bytes += b; 686 } else { 687 bytes += 16 * 2 + 8 + 2 + 1 + 2; 688 } 689 690 while (pl >= 4) { 691 br[0] = *p++; 692 br[1] = *p++; 693 br[2] = *p++; 694 br[3] = *p++; 695 pl -= 4; 696 697 if (out) { 698 b= snprintf(out, len, " %d.%d.%d.%d", 699 br[0], br[1], br[2], br[3]); 700 len -= b; 701 out += b; 702 bytes += b; 703 } else { 704 bytes += (4 * 4); 705 } 706 } 707 708 return bytes; 709} 710 711char * 712get_option_string(const struct dhcp_message *dhcp, uint8_t option) 713{ 714 int type = 0; 715 int len; 716 const uint8_t *p; 717 char *s; 718 719 p = get_option(dhcp, option, &len, &type); 720 if (!p || *p == '\0') 721 return NULL; 722 723 if (type & RFC3397) { 724 type = decode_rfc3397(NULL, 0, len, p); 725 if (!type) { 726 errno = EINVAL; 727 return NULL; 728 } 729 s = xmalloc(sizeof(char) * type); 730 decode_rfc3397(s, type, len, p); 731 return s; 732 } 733 734 if (type & RFC3361) 735 return decode_rfc3361(len, p); 736 737 s = xmalloc(sizeof(char) * (len + 1)); 738 memcpy(s, p, len); 739 s[len] = '\0'; 740 return s; 741} 742 743/* This calculates the netmask that we should use for static routes. 744 * This IS different from the calculation used to calculate the netmask 745 * for an interface address. */ 746static uint32_t 747route_netmask(uint32_t ip_in) 748{ 749 /* used to be unsigned long - check if error */ 750 uint32_t p = ntohl(ip_in); 751 uint32_t t; 752 753 if (IN_CLASSA(p)) 754 t = ~IN_CLASSA_NET; 755 else { 756 if (IN_CLASSB(p)) 757 t = ~IN_CLASSB_NET; 758 else { 759 if (IN_CLASSC(p)) 760 t = ~IN_CLASSC_NET; 761 else 762 t = 0; 763 } 764 } 765 766 while (t & p) 767 t >>= 1; 768 769 return (htonl(~t)); 770} 771 772/* We need to obey routing options. 773 * If we have a CSR then we only use that. 774 * Otherwise we add static routes and then routers. */ 775struct rt * 776get_option_routes(const struct dhcp_message *dhcp, 777 const char *ifname, unsigned long long *opts) 778{ 779 const uint8_t *p; 780 const uint8_t *e; 781 struct rt *routes = NULL; 782 struct rt *route = NULL; 783 int len; 784 785 /* If we have CSR's then we MUST use these only */ 786 p = get_option(dhcp, DHO_CSR, &len, NULL); 787 /* Check for crappy MS option */ 788 if (!p) 789 p = get_option(dhcp, DHO_MSCSR, &len, NULL); 790 if (p) { 791 routes = decode_rfc3442_rt(len, p); 792 if (routes) { 793 if (!(*opts & DHCPCD_CSR_WARNED)) { 794 syslog(LOG_DEBUG, 795 "%s: using Classless Static Routes", 796 ifname); 797 *opts |= DHCPCD_CSR_WARNED; 798 } 799 return routes; 800 } 801 } 802 803 /* OK, get our static routes first. */ 804 p = get_option(dhcp, DHO_STATICROUTE, &len, NULL); 805 if (p) { 806 e = p + len; 807 while (p < e) { 808 if (route) { 809 route->next = xmalloc(sizeof(*route)); 810 route = route->next; 811 } else 812 routes = route = xmalloc(sizeof(*routes)); 813 route->next = NULL; 814 memcpy(&route->dest.s_addr, p, 4); 815 p += 4; 816 memcpy(&route->gate.s_addr, p, 4); 817 p += 4; 818 route->net.s_addr = route_netmask(route->dest.s_addr); 819 } 820 } 821 822 /* Now grab our routers */ 823 p = get_option(dhcp, DHO_ROUTER, &len, NULL); 824 if (p) { 825 e = p + len; 826 while (p < e) { 827 if (route) { 828 route->next = xzalloc(sizeof(*route)); 829 route = route->next; 830 } else 831 routes = route = xzalloc(sizeof(*route)); 832 memcpy(&route->gate.s_addr, p, 4); 833 p += 4; 834 } 835 } 836 837 return routes; 838} 839 840static size_t 841encode_rfc1035(const char *src, uint8_t *dst) 842{ 843 uint8_t *p = dst; 844 uint8_t *lp = p++; 845 846 if (*src == '\0') 847 return 0; 848 for (; *src; src++) { 849 if (*src == '\0') 850 break; 851 if (*src == '.') { 852 /* Skip the trailing . */ 853 if (src[1] == '\0') 854 break; 855 *lp = p - lp - 1; 856 if (*lp == '\0') 857 return p - dst; 858 lp = p++; 859 } else 860 *p++ = (uint8_t)*src; 861 } 862 *lp = p - lp - 1; 863 *p++ = '\0'; 864 return p - dst; 865} 866 867#define PUTADDR(_type, _val) \ 868 { \ 869 *p++ = _type; \ 870 *p++ = 4; \ 871 memcpy(p, &_val.s_addr, 4); \ 872 p += 4; \ 873 } 874 875int 876dhcp_message_add_addr(struct dhcp_message *dhcp, 877 uint8_t type, struct in_addr addr) 878{ 879 uint8_t *p; 880 size_t len; 881 882 p = dhcp->options; 883 while (*p != DHO_END) { 884 p++; 885 p += *p + 1; 886 } 887 888 len = p - (uint8_t *)dhcp; 889 if (len + 6 > sizeof(*dhcp)) { 890 errno = ENOMEM; 891 return -1; 892 } 893 894 PUTADDR(type, addr); 895 *p = DHO_END; 896 return 0; 897} 898 899ssize_t 900make_message(struct dhcp_message **message, 901 const struct interface *iface, 902 uint8_t type) 903{ 904 struct dhcp_message *dhcp; 905 uint8_t *m, *lp, *p; 906 uint8_t *n_params = NULL; 907 time_t up = uptime() - iface->start_uptime; 908 uint32_t ul; 909 uint16_t sz; 910 size_t len; 911 const char *hp; 912 const struct dhcp_opt *opt; 913 const struct if_options *ifo = iface->state->options; 914 const struct dhcp_lease *lease = &iface->state->lease; 915 916 dhcp = xzalloc(sizeof (*dhcp)); 917 m = (uint8_t *)dhcp; 918 p = dhcp->options; 919 920 if ((type == DHCP_INFORM || type == DHCP_RELEASE || 921 (type == DHCP_REQUEST && 922 iface->net.s_addr == lease->net.s_addr && 923 (iface->state->new == NULL || 924 iface->state->new->cookie == htonl(MAGIC_COOKIE))))) 925 { 926 dhcp->ciaddr = iface->addr.s_addr; 927 /* In-case we haven't actually configured the address yet */ 928 if (type == DHCP_INFORM && iface->addr.s_addr == 0) 929 dhcp->ciaddr = lease->addr.s_addr; 930 } 931 932 dhcp->op = DHCP_BOOTREQUEST; 933 dhcp->hwtype = iface->family; 934 switch (iface->family) { 935 case ARPHRD_ETHER: 936 case ARPHRD_IEEE802: 937 dhcp->hwlen = iface->hwlen; 938 memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen); 939 break; 940 } 941 942 if (ifo->options & DHCPCD_BROADCAST && 943 dhcp->ciaddr == 0 && 944 type != DHCP_DECLINE && 945 type != DHCP_RELEASE) 946 dhcp->flags = htons(BROADCAST_FLAG); 947 948 if (type != DHCP_DECLINE && type != DHCP_RELEASE) { 949 if (up < 0 || up > (time_t)UINT16_MAX) 950 dhcp->secs = htons((uint16_t)UINT16_MAX); 951 else 952 dhcp->secs = htons(up); 953 } 954 dhcp->xid = iface->state->xid; 955 dhcp->cookie = htonl(MAGIC_COOKIE); 956 957 *p++ = DHO_MESSAGETYPE; 958 *p++ = 1; 959 *p++ = type; 960 961 if (iface->clientid) { 962 *p++ = DHO_CLIENTID; 963 memcpy(p, iface->clientid, iface->clientid[0] + 1); 964 p += iface->clientid[0] + 1; 965 } 966 967 if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) { 968 if (type == DHCP_DECLINE || 969 (type == DHCP_REQUEST && 970 lease->addr.s_addr != iface->addr.s_addr)) 971 { 972 PUTADDR(DHO_IPADDRESS, lease->addr); 973 if (lease->server.s_addr) 974 PUTADDR(DHO_SERVERID, lease->server); 975 } 976 977 if (type == DHCP_RELEASE) { 978 if (lease->server.s_addr) 979 PUTADDR(DHO_SERVERID, lease->server); 980 } 981 } 982 983 if (type == DHCP_DECLINE) { 984 *p++ = DHO_MESSAGE; 985 len = strlen(DAD); 986 *p++ = len; 987 memcpy(p, DAD, len); 988 p += len; 989 } 990 991 if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST) 992 PUTADDR(DHO_IPADDRESS, ifo->req_addr); 993 994 if (type == DHCP_DISCOVER || 995 type == DHCP_INFORM || 996 type == DHCP_REQUEST) 997 { 998 *p++ = DHO_MAXMESSAGESIZE; 999 *p++ = 2; 1000 sz = get_mtu(iface->name); 1001 if (sz < MTU_MIN) { 1002 if (set_mtu(iface->name, MTU_MIN) == 0) 1003 sz = MTU_MIN; 1004 } else if (sz > MTU_MAX) { 1005 /* Even though our MTU could be greater than 1006 * MTU_MAX (1500) dhcpcd does not presently 1007 * handle DHCP packets any bigger. */ 1008 sz = MTU_MAX; 1009 } 1010 sz = htons(sz); 1011 memcpy(p, &sz, 2); 1012 p += 2; 1013 1014 if (ifo->userclass[0]) { 1015 *p++ = DHO_USERCLASS; 1016 memcpy(p, ifo->userclass, ifo->userclass[0] + 1); 1017 p += ifo->userclass[0] + 1; 1018 } 1019 1020 if (ifo->vendorclassid[0]) { 1021 *p++ = DHO_VENDORCLASSID; 1022 memcpy(p, ifo->vendorclassid, 1023 ifo->vendorclassid[0] + 1); 1024 p += ifo->vendorclassid[0] + 1; 1025 } 1026 1027 1028 if (type != DHCP_INFORM) { 1029 if (ifo->leasetime != 0) { 1030 *p++ = DHO_LEASETIME; 1031 *p++ = 4; 1032 ul = htonl(ifo->leasetime); 1033 memcpy(p, &ul, 4); 1034 p += 4; 1035 } 1036 } 1037 1038 /* Regardless of RFC2132, we should always send a hostname 1039 * upto the first dot (the short hostname) as otherwise 1040 * confuses some DHCP servers when updating DNS. 1041 * The FQDN option should be used if a FQDN is required. */ 1042 if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) { 1043 *p++ = DHO_HOSTNAME; 1044 hp = strchr(ifo->hostname, '.'); 1045 if (hp) 1046 len = hp - ifo->hostname; 1047 else 1048 len = strlen(ifo->hostname); 1049 *p++ = len; 1050 memcpy(p, ifo->hostname, len); 1051 p += len; 1052 } 1053 if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) { 1054 /* IETF DHC-FQDN option (81), RFC4702 */ 1055 *p++ = DHO_FQDN; 1056 lp = p; 1057 *p++ = 3; 1058 /* 1059 * Flags: 0000NEOS 1060 * S: 1 => Client requests Server to update 1061 * a RR in DNS as well as PTR 1062 * O: 1 => Server indicates to client that 1063 * DNS has been updated 1064 * E: 1 => Name data is DNS format 1065 * N: 1 => Client requests Server to not 1066 * update DNS 1067 */ 1068 *p++ = (ifo->fqdn & 0x09) | 0x04; 1069 *p++ = 0; /* from server for PTR RR */ 1070 *p++ = 0; /* from server for A RR if S=1 */ 1071 ul = encode_rfc1035(ifo->hostname, p); 1072 *lp += ul; 1073 p += ul; 1074 } 1075 1076 /* vendor is already encoded correctly, so just add it */ 1077 if (ifo->vendor[0]) { 1078 *p++ = DHO_VENDOR; 1079 memcpy(p, ifo->vendor, ifo->vendor[0] + 1); 1080 p += ifo->vendor[0] + 1; 1081 } 1082 1083 *p++ = DHO_PARAMETERREQUESTLIST; 1084 n_params = p; 1085 *p++ = 0; 1086 for (opt = dhcp_opts; opt->option; opt++) { 1087 if (!(opt->type & REQUEST || 1088 has_option_mask(ifo->requestmask, opt->option))) 1089 continue; 1090 if (type == DHCP_INFORM && 1091 (opt->option == DHO_RENEWALTIME || 1092 opt->option == DHO_REBINDTIME)) 1093 continue; 1094 *p++ = opt->option; 1095 } 1096 *n_params = p - n_params - 1; 1097 } 1098 *p++ = DHO_END; 1099 1100#ifdef BOOTP_MESSAGE_LENTH_MIN 1101 /* Some crappy DHCP servers think they have to obey the BOOTP minimum 1102 * message length. 1103 * They are wrong, but we should still cater for them. */ 1104 while (p - m < BOOTP_MESSAGE_LENTH_MIN) 1105 *p++ = DHO_PAD; 1106#endif 1107 1108 *message = dhcp; 1109 return p - m; 1110} 1111 1112ssize_t 1113write_lease(const struct interface *iface, const struct dhcp_message *dhcp) 1114{ 1115 int fd; 1116 ssize_t bytes = sizeof(*dhcp); 1117 const uint8_t *p = dhcp->options; 1118 const uint8_t *e = p + sizeof(dhcp->options); 1119 uint8_t l; 1120 uint8_t o = 0; 1121 1122 /* We don't write BOOTP leases */ 1123 if (is_bootp(dhcp)) { 1124 unlink(iface->leasefile); 1125 return 0; 1126 } 1127 1128 syslog(LOG_DEBUG, "%s: writing lease `%s'", 1129 iface->name, iface->leasefile); 1130 1131 fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444); 1132 if (fd == -1) 1133 return -1; 1134 1135 /* Only write as much as we need */ 1136 while (p < e) { 1137 o = *p; 1138 if (o == DHO_END) { 1139 bytes = p - (const uint8_t *)dhcp; 1140 break; 1141 } 1142 p++; 1143 if (o != DHO_PAD) { 1144 l = *p++; 1145 p += l; 1146 } 1147 } 1148 bytes = write(fd, dhcp, bytes); 1149 close(fd); 1150 return bytes; 1151} 1152 1153struct dhcp_message * 1154read_lease(const struct interface *iface) 1155{ 1156 int fd; 1157 struct dhcp_message *dhcp; 1158 ssize_t bytes; 1159 1160 fd = open(iface->leasefile, O_RDONLY); 1161 if (fd == -1) { 1162 if (errno != ENOENT) 1163 syslog(LOG_ERR, "%s: open `%s': %m", 1164 iface->name, iface->leasefile); 1165 return NULL; 1166 } 1167 syslog(LOG_DEBUG, "%s: reading lease `%s'", 1168 iface->name, iface->leasefile); 1169 dhcp = xmalloc(sizeof(*dhcp)); 1170 memset(dhcp, 0, sizeof(*dhcp)); 1171 bytes = read(fd, dhcp, sizeof(*dhcp)); 1172 close(fd); 1173 if (bytes < 0) { 1174 free(dhcp); 1175 dhcp = NULL; 1176 } 1177 return dhcp; 1178} 1179 1180static ssize_t 1181print_string(char *s, ssize_t len, int dl, const uint8_t *data) 1182{ 1183 uint8_t c; 1184 const uint8_t *e, *p; 1185 ssize_t bytes = 0; 1186 ssize_t r; 1187 1188 e = data + dl; 1189 while (data < e) { 1190 c = *data++; 1191 if (c == '\0') { 1192 /* If rest is all NULL, skip it. */ 1193 for (p = data; p < e; p++) 1194 if (*p != '\0') 1195 break; 1196 if (p == e) 1197 break; 1198 } 1199 if (!isascii(c) || !isprint(c)) { 1200 if (s) { 1201 if (len < 5) { 1202 errno = ENOBUFS; 1203 return -1; 1204 } 1205 r = snprintf(s, len, "\\%03o", c); 1206 len -= r; 1207 bytes += r; 1208 s += r; 1209 } else 1210 bytes += 4; 1211 continue; 1212 } 1213 switch (c) { 1214 case '"': /* FALLTHROUGH */ 1215 case '\'': /* FALLTHROUGH */ 1216 case '$': /* FALLTHROUGH */ 1217 case '`': /* FALLTHROUGH */ 1218 case '\\': /* FALLTHROUGH */ 1219 case '|': /* FALLTHROUGH */ 1220 case '&': 1221 if (s) { 1222 if (len < 3) { 1223 errno = ENOBUFS; 1224 return -1; 1225 } 1226 *s++ = '\\'; 1227 len--; 1228 } 1229 bytes++; 1230 break; 1231 } 1232 if (s) { 1233 *s++ = c; 1234 len--; 1235 } 1236 bytes++; 1237 } 1238 1239 /* NULL */ 1240 if (s) 1241 *s = '\0'; 1242 bytes++; 1243 return bytes; 1244} 1245 1246static ssize_t 1247print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data) 1248{ 1249 const uint8_t *e, *t; 1250 uint16_t u16; 1251 int16_t s16; 1252 uint32_t u32; 1253 int32_t s32; 1254 struct in_addr addr; 1255 ssize_t bytes = 0; 1256 ssize_t l; 1257 char *tmp; 1258 1259 if (type & RFC3397) { 1260 l = decode_rfc3397(NULL, 0, dl, data); 1261 if (l < 1) 1262 return l; 1263 tmp = xmalloc(l); 1264 decode_rfc3397(tmp, l, dl, data); 1265 l = print_string(s, len, l - 1, (uint8_t *)tmp); 1266 free(tmp); 1267 return l; 1268 } 1269 1270 if (type & RFC3361) { 1271 if ((tmp = decode_rfc3361(dl, data)) == NULL) 1272 return -1; 1273 l = strlen(tmp); 1274 l = print_string(s, len, l - 1, (uint8_t *)tmp); 1275 free(tmp); 1276 return l; 1277 } 1278 1279 if (type & RFC3442) 1280 return decode_rfc3442(s, len, dl, data); 1281 1282 if (type & RFC5969) 1283 return decode_rfc5969(s, len, dl, data); 1284 1285 if (type & STRING) { 1286 /* Some DHCP servers return NULL strings */ 1287 if (*data == '\0') 1288 return 0; 1289 return print_string(s, len, dl, data); 1290 } 1291 1292 if (!s) { 1293 if (type & UINT8) 1294 l = 3; 1295 else if (type & UINT16) { 1296 l = 5; 1297 dl /= 2; 1298 } else if (type & SINT16) { 1299 l = 6; 1300 dl /= 2; 1301 } else if (type & UINT32) { 1302 l = 10; 1303 dl /= 4; 1304 } else if (type & SINT32) { 1305 l = 11; 1306 dl /= 4; 1307 } else if (type & IPV4) { 1308 l = 16; 1309 dl /= 4; 1310 } else { 1311 errno = EINVAL; 1312 return -1; 1313 } 1314 return (l + 1) * dl; 1315 } 1316 1317 t = data; 1318 e = data + dl; 1319 while (data < e) { 1320 if (data != t) { 1321 *s++ = ' '; 1322 bytes++; 1323 len--; 1324 } 1325 if (type & UINT8) { 1326 l = snprintf(s, len, "%d", *data); 1327 data++; 1328 } else if (type & UINT16) { 1329 memcpy(&u16, data, sizeof(u16)); 1330 u16 = ntohs(u16); 1331 l = snprintf(s, len, "%d", u16); 1332 data += sizeof(u16); 1333 } else if (type & SINT16) { 1334 memcpy(&s16, data, sizeof(s16)); 1335 s16 = ntohs(s16); 1336 l = snprintf(s, len, "%d", s16); 1337 data += sizeof(s16); 1338 } else if (type & UINT32) { 1339 memcpy(&u32, data, sizeof(u32)); 1340 u32 = ntohl(u32); 1341 l = snprintf(s, len, "%d", u32); 1342 data += sizeof(u32); 1343 } else if (type & SINT32) { 1344 memcpy(&s32, data, sizeof(s32)); 1345 s32 = ntohl(s32); 1346 l = snprintf(s, len, "%d", s32); 1347 data += sizeof(s32); 1348 } else if (type & IPV4) { 1349 memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 1350 l = snprintf(s, len, "%s", inet_ntoa(addr)); 1351 data += sizeof(addr.s_addr); 1352 } else 1353 l = 0; 1354 len -= l; 1355 bytes += l; 1356 s += l; 1357 } 1358 1359 return bytes; 1360} 1361 1362ssize_t 1363configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp, 1364 const struct if_options *ifo) 1365{ 1366 const uint8_t *p; 1367 int pl; 1368 struct in_addr addr; 1369 struct in_addr net; 1370 struct in_addr brd; 1371 char *val, *v; 1372 const struct dhcp_opt *opt; 1373 ssize_t len, e = 0; 1374 char **ep; 1375 char cidr[4]; 1376 uint8_t overl = 0; 1377 1378 get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED); 1379 1380 if (!env) { 1381 for (opt = dhcp_opts; opt->option; opt++) { 1382 if (!opt->var) 1383 continue; 1384 if (has_option_mask(ifo->nomask, opt->option)) 1385 continue; 1386 if (get_option_raw(dhcp, opt->option)) 1387 e++; 1388 } 1389 if (dhcp->yiaddr || dhcp->ciaddr) 1390 e += 5; 1391 if (*dhcp->bootfile && !(overl & 1)) 1392 e++; 1393 if (*dhcp->servername && !(overl & 2)) 1394 e++; 1395 return e; 1396 } 1397 1398 ep = env; 1399 if (dhcp->yiaddr || dhcp->ciaddr) { 1400 /* Set some useful variables that we derive from the DHCP 1401 * message but are not necessarily in the options */ 1402 addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr; 1403 setvar(&ep, prefix, "ip_address", inet_ntoa(addr)); 1404 if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) { 1405 net.s_addr = get_netmask(addr.s_addr); 1406 setvar(&ep, prefix, "subnet_mask", inet_ntoa(net)); 1407 } 1408 snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net)); 1409 setvar(&ep, prefix, "subnet_cidr", cidr); 1410 if (get_option_addr(&brd, dhcp, DHO_BROADCAST) == -1) { 1411 brd.s_addr = addr.s_addr | ~net.s_addr; 1412 setvar(&ep, prefix, "broadcast_address", inet_ntoa(brd)); 1413 } 1414 addr.s_addr = dhcp->yiaddr & net.s_addr; 1415 setvar(&ep, prefix, "network_number", inet_ntoa(addr)); 1416 } 1417 1418 if (*dhcp->bootfile && !(overl & 1)) 1419 setvar(&ep, prefix, "filename", (const char *)dhcp->bootfile); 1420 if (*dhcp->servername && !(overl & 2)) 1421 setvar(&ep, prefix, "server_name", (const char *)dhcp->servername); 1422 1423 for (opt = dhcp_opts; opt->option; opt++) { 1424 if (!opt->var) 1425 continue; 1426 if (has_option_mask(ifo->nomask, opt->option)) 1427 continue; 1428 val = NULL; 1429 p = get_option(dhcp, opt->option, &pl, NULL); 1430 if (!p) 1431 continue; 1432 /* We only want the FQDN name */ 1433 if (opt->option == DHO_FQDN) { 1434 p += 3; 1435 pl -= 3; 1436 } 1437 len = print_option(NULL, 0, opt->type, pl, p); 1438 if (len < 0) 1439 return -1; 1440 e = strlen(prefix) + strlen(opt->var) + len + 4; 1441 v = val = *ep++ = xmalloc(e); 1442 v += snprintf(val, e, "%s_%s=", prefix, opt->var); 1443 if (len != 0) 1444 print_option(v, len, opt->type, pl, p); 1445 } 1446 1447 return ep - env; 1448} 1449 1450void 1451get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp) 1452{ 1453 struct timeval now; 1454 1455 lease->cookie = dhcp->cookie; 1456 /* BOOTP does not set yiaddr for replies when ciaddr is set. */ 1457 if (dhcp->yiaddr) 1458 lease->addr.s_addr = dhcp->yiaddr; 1459 else 1460 lease->addr.s_addr = dhcp->ciaddr; 1461 if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1) 1462 lease->net.s_addr = get_netmask(lease->addr.s_addr); 1463 if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1) 1464 lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr; 1465 if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) { 1466 /* Ensure that we can use the lease */ 1467 get_monotonic(&now); 1468 if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec) 1469 lease->leasetime = ~0U; /* Infinite lease */ 1470 } else 1471 lease->leasetime = ~0U; /* Default to infinite lease */ 1472 if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) 1473 lease->renewaltime = 0; 1474 if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) 1475 lease->rebindtime = 0; 1476 if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0) 1477 lease->server.s_addr = INADDR_ANY; 1478} 1479