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