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