1 /* 2 * dhcpcd - DHCP client daemon 3 * SPDX-License-Identifier: BSD-2-Clause 4 * Copyright (c) 2006-2025 Roy Marples <roy (at) marples.name> 5 * All rights reserved 6 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/utsname.h> 30 31 #include <ctype.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <inttypes.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include "config.h" // IWYU pragma: keep 40 #include "common.h" 41 #include "dhcp-common.h" 42 #include "dhcp.h" 43 #include "if.h" 44 #include "ipv6.h" 45 #include "logerr.h" 46 #include "script.h" 47 48 const char * 49 dhcp_get_hostname(struct dhcpcd_ctx *ctx, char *buf, size_t buf_len, 50 const struct if_options *ifo) 51 { 52 #ifndef PRIVSEP_GETHOSTNAME 53 UNUSED(ctx); 54 #endif 55 if (ifo->hostname[0] == '\0') { 56 #ifdef PRIVSEP_GETHOSTNAME 57 if (IN_PRIVSEP(ctx)) { 58 if (ps_root_gethostname(ctx, buf, buf_len) == -1) 59 return NULL; 60 } else 61 #endif 62 if (gethostname(buf, buf_len) != 0) 63 return NULL; 64 buf[buf_len - 1] = '\0'; 65 } else 66 strlcpy(buf, ifo->hostname, buf_len); 67 68 /* Deny sending of these local hostnames */ 69 if (buf[0] == '\0' || buf[0] == '.' || strcmp(buf, "(none)") == 0 || 70 strcmp(buf, "localhost") == 0 || 71 strncmp(buf, "localhost.", strlen("localhost.")) == 0) 72 return NULL; 73 74 /* Shorten the hostname if required */ 75 if (ifo->options & DHCPCD_HOSTNAME_SHORT) { 76 char *hp; 77 78 hp = strchr(buf, '.'); 79 if (hp != NULL) 80 *hp = '\0'; 81 } 82 83 return buf; 84 } 85 86 void 87 dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols) 88 { 89 while (cols < 40) { 90 putchar(' '); 91 cols++; 92 } 93 putchar('\t'); 94 if (opt->type & OT_EMBED) 95 printf(" embed"); 96 if (opt->type & OT_ENCAP) 97 printf(" encap"); 98 if (opt->type & OT_INDEX) 99 printf(" index"); 100 if (opt->type & OT_ARRAY) 101 printf(" array"); 102 if (opt->type & OT_UINT8) 103 printf(" uint8"); 104 else if (opt->type & OT_INT8) 105 printf(" int8"); 106 else if (opt->type & OT_UINT16) 107 printf(" uint16"); 108 else if (opt->type & OT_INT16) 109 printf(" int16"); 110 else if (opt->type & OT_UINT32) 111 printf(" uint32"); 112 else if (opt->type & OT_INT32) 113 printf(" int32"); 114 else if (opt->type & OT_ADDRIPV4) 115 printf(" ipaddress"); 116 else if (opt->type & OT_ADDRIPV6) 117 printf(" ip6address"); 118 else if (opt->type & OT_FLAG) 119 printf(" flag"); 120 else if (opt->type & OT_BITFLAG) 121 printf(" bitflags"); 122 else if (opt->type & OT_RFC1035) 123 printf(" domain"); 124 else if (opt->type & OT_DOMAIN) 125 printf(" dname"); 126 else if (opt->type & OT_ASCII) 127 printf(" ascii"); 128 else if (opt->type & OT_RAW) 129 printf(" raw"); 130 else if (opt->type & OT_BINHEX) 131 printf(" binhex"); 132 else if (opt->type & OT_STRING) 133 printf(" string"); 134 else if (opt->type & OT_URI) 135 printf(" uri"); 136 if (opt->type & OT_RFC3361) 137 printf(" rfc3361"); 138 if (opt->type & OT_RFC3442) 139 printf(" rfc3442"); 140 if (opt->type & OT_REQUEST) 141 printf(" request"); 142 if (opt->type & OT_NOREQ) 143 printf(" norequest"); 144 if (opt->type & OT_TRUNCATED) 145 printf(" truncated"); 146 putchar('\n'); 147 fflush(stdout); 148 } 149 150 static char dhcp_option_string_buf[16]; 151 const char * 152 dhcp_option_string(const struct dhcp_opt *opts, size_t nopts, uint32_t option) 153 { 154 size_t n; 155 156 for (n = 0; n < nopts; n++, opts++) { 157 if (opts->option == option) 158 return opts->var; 159 } 160 161 if (snprintf(dhcp_option_string_buf, sizeof(dhcp_option_string_buf), 162 "%u", option) == -1) 163 return NULL; 164 return dhcp_option_string_buf; 165 } 166 167 struct dhcp_opt * 168 vivso_find(uint32_t iana_en, const void *arg) 169 { 170 const struct interface *ifp; 171 size_t i; 172 struct dhcp_opt *opt; 173 174 ifp = arg; 175 for (i = 0, opt = ifp->options->vivso_override; 176 i < ifp->options->vivso_override_len; i++, opt++) 177 if (opt->option == iana_en) 178 return opt; 179 for (i = 0, opt = ifp->ctx->vivso; i < ifp->ctx->vivso_len; i++, opt++) 180 if (opt->option == iana_en) 181 return opt; 182 return NULL; 183 } 184 185 ssize_t 186 dhcp_vendor(char *str, size_t len) 187 { 188 struct utsname utn; 189 char *p; 190 int l; 191 192 if (uname(&utn) == -1) 193 return (ssize_t)snprintf(str, len, "%s-%s", PACKAGE, VERSION); 194 p = str; 195 l = snprintf(p, len, "%s-%s:%s-%s:%s", PACKAGE, VERSION, utn.sysname, 196 utn.release, utn.machine); 197 if (l == -1 || (size_t)(l + 1) > len) 198 return -1; 199 p += l; 200 len -= (size_t)l; 201 l = if_machinearch(p + 1, len - 1); 202 if (l == -1 || (size_t)(l + 1) > len) 203 return -1; 204 if (l != 0) { 205 *p = ':'; 206 p += l; 207 } 208 return p - str; 209 } 210 211 int 212 dho_policy_has(const struct dho_policy *policy, uint32_t option) 213 { 214 size_t i; 215 216 for (i = 0; i < policy->dhop_policy_len; i++) { 217 if (policy->dhop_policy[i] == option) 218 return 1; 219 } 220 221 return 0; 222 } 223 224 int 225 dho_policy_allowed(const struct dho_policy_group *pg, uint32_t option) 226 { 227 if (pg->dhop_allow.dhop_policy_len == 0) { 228 /* No allowed policy has been set, so be permissive. */ 229 return dho_policy_has(&pg->dhop_remove, option) ? 0 : 1; 230 } 231 232 if (dho_policy_has(&pg->dhop_allow, option) || 233 dho_policy_has(&pg->dhop_request, option)) 234 return 1; 235 return 0; 236 } 237 238 int 239 dho_policy_requested(const struct dho_policy_group *pg, uint32_t option) 240 { 241 if (!dho_policy_has(&pg->dhop_request, option)) 242 return 0; 243 if (dho_policy_has(&pg->dhop_allow, option)) 244 return 1; 245 if (dho_policy_has(&pg->dhop_remove, option)) 246 return 0; 247 return 1; 248 } 249 250 int 251 dho_policy_opt_requested(const struct dho_policy_group *pg, 252 const struct dhcp_opt *dho) 253 { 254 if (dho->type & OT_NOREQ) 255 return 0; 256 if (!(dho->type & OT_REQUEST) && 257 !dho_policy_has(&pg->dhop_request, dho->option)) 258 return 0; 259 if (dho_policy_has(&pg->dhop_allow, dho->option)) 260 return 1; 261 if (dho_policy_has(&pg->dhop_remove, dho->option)) 262 return 0; 263 return 1; 264 } 265 266 static uint32_t * 267 dho_policy_find(struct dho_policy *policy, uint32_t option, 268 uint32_t **free_option) 269 { 270 size_t i; 271 272 for (i = 0; i < policy->dhop_policy_len; i++) { 273 if (policy->dhop_policy[i] == option) 274 return &policy->dhop_policy[i]; 275 if (policy->dhop_policy[i] == 0 && free_option != NULL && 276 *free_option == NULL) 277 *free_option = &policy->dhop_policy[i]; 278 } 279 280 return 0; 281 } 282 283 int 284 dho_policy_add(struct dho_policy *policy, uint32_t option) 285 { 286 uint32_t *np, *free_option = NULL; 287 288 if (dho_policy_find(policy, option, &free_option) != NULL) 289 return 0; 290 291 if (free_option != NULL) { 292 *free_option = option; 293 return 1; 294 } 295 296 np = reallocarray(policy->dhop_policy, policy->dhop_policy_len + 1, 297 sizeof(*policy->dhop_policy)); 298 if (np == NULL) 299 return -1; 300 301 np[policy->dhop_policy_len] = option; 302 policy->dhop_policy = np; 303 policy->dhop_policy_len++; 304 return 1; 305 } 306 307 int 308 dho_policy_del(struct dho_policy *policy, uint32_t option) 309 { 310 uint32_t *o; 311 312 o = dho_policy_find(policy, option, NULL); 313 if (o == NULL) 314 return 0; 315 316 *o = 0; 317 return 1; 318 } 319 320 int 321 dho_policy_set(const struct dho_policy_ctx *pctx, struct dho_policy *policy, 322 const char *opts, int add) 323 { 324 char *token, *o, *p; 325 const struct dhcp_opt *opt; 326 int match, e, err = -1; 327 unsigned int n, max = UINT16_MAX; 328 size_t i; 329 330 if (opts == NULL) 331 return -1; 332 o = p = strdup(opts); 333 while ((token = strsep(&p, ", "))) { 334 if (*token == '\0') 335 continue; 336 if (strncmp(token, "dhcp6_", 6) == 0) 337 token += 6; 338 else if (strncmp(token, "nd_", 3) == 0) 339 token += 3; 340 else 341 max = UINT8_MAX; 342 n = (unsigned int)strtou(token, NULL, 0, 1, max, &e); 343 match = 0; 344 for (i = 0, opt = pctx->odopts; i < pctx->odopts_len; 345 i++, opt++) { 346 if (opt->var == NULL || opt->option == 0) 347 continue; /* buggy dhcpcd-definitions.conf */ 348 if (strcmp(opt->var, token) == 0) 349 match = 1; 350 else if (e == 0 && opt->option == n) 351 match = 1; 352 if (match) 353 break; 354 } 355 if (match == 0) { 356 for (i = 0, opt = pctx->dopts; i < pctx->dopts_len; 357 i++, opt++) { 358 if (strcmp(opt->var, token) == 0) 359 match = 1; 360 else if (e == 0 && opt->option == n) 361 match = 1; 362 if (match) 363 break; 364 } 365 } 366 if ((!match || !opt->option) && e != 0) { 367 errno = ENOENT; 368 goto out; 369 } 370 if (match && add == 2 && !(opt->type & OT_ADDRIPV4)) { 371 errno = EINVAL; 372 goto out; 373 } 374 if (match) 375 n = opt->option; 376 if (add == 1 || add == 2) 377 dho_policy_add(policy, n); 378 else 379 dho_policy_del(policy, n); 380 } 381 382 err = 0; 383 384 out: 385 free(o); 386 return err; 387 } 388 389 /* Pass by value because we don't free the holder */ 390 void 391 dho_policy_free(struct dho_policy policy) 392 { 393 free(policy.dhop_policy); 394 } 395 396 void 397 dho_policy_group_free(struct dho_policy_group pg) 398 { 399 dho_policy_free(pg.dhop_request); 400 dho_policy_free(pg.dhop_require); 401 dho_policy_free(pg.dhop_allow); 402 dho_policy_free(pg.dhop_remove); 403 dho_policy_free(pg.dhop_reject); 404 } 405 406 int 407 dho_policy_check(const struct dho_policy *policy, 408 int (*check)(uint32_t, void *), void *check_ctx) 409 { 410 size_t i; 411 int result; 412 413 for (i = 0; i < policy->dhop_policy_len; i++) { 414 if (policy->dhop_policy[i] == 0) 415 continue; 416 result = check(policy->dhop_policy[i], check_ctx); 417 if (result != 0) 418 return result; 419 } 420 421 return 0; 422 } 423 424 size_t 425 encode_rfc1035(const char *src, uint8_t *dst) 426 { 427 uint8_t *p; 428 uint8_t *lp; 429 size_t len; 430 uint8_t has_dot; 431 432 if (src == NULL || *src == '\0') 433 return 0; 434 435 if (dst) { 436 p = dst; 437 lp = p++; 438 } 439 /* Silence bogus GCC warnings */ 440 else 441 p = lp = NULL; 442 443 len = 1; 444 has_dot = 0; 445 for (; *src; src++) { 446 if (*src == '\0') 447 break; 448 if (*src == '.') { 449 /* Skip the trailing . */ 450 if (src[1] == '\0') 451 break; 452 has_dot = 1; 453 if (dst) { 454 *lp = (uint8_t)(p - lp - 1); 455 if (*lp == '\0') 456 return len; 457 lp = p++; 458 } 459 } else if (dst) 460 *p++ = (uint8_t)*src; 461 len++; 462 } 463 464 if (dst) { 465 *lp = (uint8_t)(p - lp - 1); 466 if (has_dot) 467 *p++ = '\0'; 468 } 469 470 if (has_dot) 471 len++; 472 473 return len; 474 } 475 476 /* Decode an RFC1035 DNS search order option into a space 477 * separated string. Returns length of string (including 478 * terminating zero) or zero on error. out may be NULL 479 * to just determine output length. */ 480 ssize_t 481 decode_rfc1035(char *out, size_t len, const uint8_t *p, size_t pl) 482 { 483 const char *start; 484 size_t start_len, l, d_len, o_len; 485 const uint8_t *r, *q = p, *e; 486 int hops; 487 uint8_t ltype; 488 489 o_len = 0; 490 start = out; 491 start_len = len; 492 q = p; 493 e = p + pl; 494 while (q < e) { 495 r = NULL; 496 d_len = 0; 497 hops = 0; 498 /* Check we are inside our length again in-case 499 * the name isn't fully qualified (ie, not terminated) */ 500 while (q < e && (l = (size_t)*q++)) { 501 ltype = l & 0xc0; 502 if (ltype == 0x80 || ltype == 0x40) { 503 /* Currently reserved for future use as noted 504 * in RFC1035 4.1.4 as the 10 and 01 505 * combinations. */ 506 errno = ENOTSUP; 507 return -1; 508 } else if (ltype == 0xc0) { /* pointer */ 509 if (q == e) { 510 errno = ERANGE; 511 return -1; 512 } 513 l = (l & 0x3f) << 8; 514 l |= *q++; 515 /* save source of first jump. */ 516 if (!r) 517 r = q; 518 hops++; 519 if (hops > 255) { 520 errno = ERANGE; 521 return -1; 522 } 523 q = p + l; 524 if (q >= e) { 525 errno = ERANGE; 526 return -1; 527 } 528 } else { 529 /* straightforward name segment, add with '.' */ 530 if (q + l > e) { 531 errno = ERANGE; 532 return -1; 533 } 534 if (l > NS_MAXLABEL) { 535 errno = EINVAL; 536 return -1; 537 } 538 d_len += l + 1; 539 if (out) { 540 if (l + 1 > len) { 541 errno = ENOBUFS; 542 return -1; 543 } 544 memcpy(out, q, l); 545 out += l; 546 *out++ = '.'; 547 len -= l; 548 len--; 549 } 550 q += l; 551 } 552 } 553 554 /* Don't count the trailing NUL */ 555 if (d_len > NS_MAXDNAME + 1) { 556 errno = E2BIG; 557 return -1; 558 } 559 o_len += d_len; 560 561 /* change last dot to space */ 562 if (out && out != start) 563 *(out - 1) = ' '; 564 if (r) 565 q = r; 566 } 567 568 /* change last space to zero terminator */ 569 if (out) { 570 if (out != start) 571 *(out - 1) = '\0'; 572 else if (start_len > 0) 573 *out = '\0'; 574 } 575 576 /* Remove the trailing NUL */ 577 if (o_len != 0) 578 o_len--; 579 580 return (ssize_t)o_len; 581 } 582 583 /* Check for a valid name as per RFC952 and RFC1123 section 2.1 */ 584 static ssize_t 585 valid_domainname(char *lbl, int type) 586 { 587 char *slbl = lbl, *lst = NULL; 588 unsigned char c; 589 int len = 0; 590 bool start = true, errset = false; 591 592 if (lbl == NULL || *lbl == '\0') { 593 errno = EINVAL; 594 return 0; 595 } 596 597 for (;;) { 598 c = (unsigned char)*lbl++; 599 if (c == '\0') 600 return lbl - slbl - 1; 601 if (c == ' ') { 602 if (lbl - 1 == slbl) /* No space at start */ 603 break; 604 if (!(type & OT_ARRAY)) 605 break; 606 /* Skip to the next label */ 607 if (!start) { 608 start = true; 609 lst = lbl - 1; 610 } 611 if (len) 612 len = 0; 613 continue; 614 } 615 if (c == '.') { 616 if (*lbl == '.') 617 break; 618 len = 0; 619 continue; 620 } 621 if (((c == '-' || c == '_') && !start && *lbl != ' ' && 622 *lbl != '\0') || 623 isalnum(c)) { 624 if (++len > NS_MAXLABEL) { 625 errno = ERANGE; 626 errset = true; 627 break; 628 } 629 } else 630 break; 631 if (start) 632 start = false; 633 } 634 635 if (!errset) 636 errno = EINVAL; 637 if (lst) { 638 /* At least one valid domain, return it */ 639 *lst = '\0'; 640 return lst - slbl; 641 } 642 return 0; 643 } 644 645 /* 646 * Prints a chunk of data to a string. 647 * PS_SHELL goes as it is these days, it's upto the target to validate it. 648 * PS_SAFE has all non ascii and non printables changes to escaped octal. 649 */ 650 static const char hexchrs[] = "0123456789abcdef"; 651 ssize_t 652 print_string(char *dst, size_t len, int type, const void *data, size_t dl) 653 { 654 const uint8_t *d = (const uint8_t *)data; 655 char *odst; 656 uint8_t c; 657 const uint8_t *e; 658 size_t bytes; 659 660 odst = dst; 661 bytes = 0; 662 e = d + dl; 663 664 while (d < e) { 665 c = *d++; 666 if (type & OT_BINHEX) { 667 if (dst) { 668 if (len == 0 || len == 1) { 669 errno = ENOBUFS; 670 return -1; 671 } 672 *dst++ = hexchrs[(c & 0xF0) >> 4]; 673 *dst++ = hexchrs[(c & 0x0F)]; 674 len -= 2; 675 } 676 bytes += 2; 677 continue; 678 } 679 if (type & OT_ASCII && (!isascii(c))) { 680 errno = EINVAL; 681 break; 682 } 683 if (!(type & (OT_ASCII | OT_RAW | OT_ESCSTRING | OT_ESCFILE)) && 684 (!isascii(c) && !isprint(c))) { 685 errno = EINVAL; 686 break; 687 } 688 if (type & OT_URI && isspace(c)) { 689 errno = EINVAL; 690 break; 691 } 692 if ((type & (OT_ESCSTRING | OT_ESCFILE) && 693 (c == '\\' || !isascii(c) || !isprint(c))) || 694 (type & OT_ESCFILE && (c == '/' || c == ' '))) { 695 errno = EINVAL; 696 if (c == '\\') { 697 if (dst) { 698 if (len == 0 || len == 1) { 699 errno = ENOBUFS; 700 return -1; 701 } 702 *dst++ = '\\'; 703 *dst++ = '\\'; 704 len -= 2; 705 } 706 bytes += 2; 707 continue; 708 } 709 if (dst) { 710 if (len < 5) { 711 errno = ENOBUFS; 712 return -1; 713 } 714 *dst++ = '\\'; 715 *dst++ = (char)(((c >> 6) & 03) + '0'); 716 *dst++ = (char)(((c >> 3) & 07) + '0'); 717 *dst++ = (char)((c & 07) + '0'); 718 len -= 4; 719 } 720 bytes += 4; 721 } else { 722 if (dst) { 723 if (len == 0) { 724 errno = ENOBUFS; 725 return -1; 726 } 727 *dst++ = (char)c; 728 len--; 729 } 730 bytes++; 731 } 732 } 733 734 /* NULL */ 735 if (dst) { 736 if (len == 0) { 737 errno = ENOBUFS; 738 return -1; 739 } 740 *dst = '\0'; 741 742 /* Now we've printed it, validate the domain */ 743 if (type & OT_DOMAIN && !valid_domainname(odst, type)) { 744 *odst = '\0'; 745 return 1; 746 } 747 } 748 749 return (ssize_t)bytes; 750 } 751 752 #define ADDR6SZ 16 753 static ssize_t 754 dhcp_optlen(const struct dhcp_opt *opt, size_t dl) 755 { 756 size_t sz; 757 758 if (opt->type & OT_ADDRIPV6) 759 sz = ADDR6SZ; 760 else if (opt->type & (OT_INT32 | OT_UINT32 | OT_ADDRIPV4)) 761 sz = sizeof(uint32_t); 762 else if (opt->type & (OT_INT16 | OT_UINT16)) 763 sz = sizeof(uint16_t); 764 else if (opt->type & (OT_INT8 | OT_UINT8 | OT_BITFLAG)) 765 sz = sizeof(uint8_t); 766 else if (opt->type & OT_FLAG) 767 return 0; 768 else { 769 /* All other types are variable length */ 770 if (opt->len) { 771 if ((size_t)opt->len > dl) { 772 errno = EOVERFLOW; 773 return -1; 774 } 775 return (ssize_t)opt->len; 776 } 777 return (ssize_t)dl; 778 } 779 if (dl < sz) { 780 if (opt->type & OT_TRUNCATED) 781 return (ssize_t)dl; 782 errno = EOVERFLOW; 783 return -1; 784 } 785 786 /* Trim any extra data. 787 * Maybe we need a setting to reject DHCP options with extra data? */ 788 if (opt->type & OT_ARRAY) 789 return (ssize_t)(dl - (dl % sz)); 790 return (ssize_t)sz; 791 } 792 793 static ssize_t 794 print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt, 795 int vname, const uint8_t *data, size_t dl, const char *ifname) 796 { 797 fpos_t fp_pos; 798 const uint8_t *e, *t; 799 uint16_t u16; 800 int16_t s16; 801 uint32_t u32; 802 int32_t s32; 803 struct in_addr addr; 804 ssize_t sl; 805 size_t l; 806 807 /* Ensure a valid length */ 808 dl = (size_t)dhcp_optlen(opt, dl); 809 if ((ssize_t)dl == -1) 810 return 0; 811 812 if (fgetpos(fp, &fp_pos) == -1) 813 return -1; 814 if (fprintf(fp, "%s", prefix) == -1) 815 goto err; 816 817 /* We printed something, so always goto err from now-on 818 * to terminate the string. */ 819 if (vname) { 820 if (fprintf(fp, "_%s", opt->var) == -1) 821 goto err; 822 } 823 if (fputc('=', fp) == EOF) 824 goto err; 825 if (dl == 0) 826 goto done; 827 828 if (opt->type & OT_RFC1035) { 829 char domain[NS_MAXDNAME]; 830 831 sl = decode_rfc1035(domain, sizeof(domain), data, dl); 832 if (sl == -1) 833 goto err; 834 if (sl == 0) 835 goto done; 836 if (!valid_domainname(domain, opt->type)) 837 goto err; 838 return efprintf(fp, "%s", domain); 839 } 840 841 #ifdef INET 842 if (opt->type & OT_RFC3361) 843 return print_rfc3361(fp, data, dl); 844 845 if (opt->type & OT_RFC3442) 846 return print_rfc3442(fp, data, dl); 847 #endif 848 849 /* Produces a space separated list of URIs. 850 * This is valid as a URI cannot contain a space. */ 851 if ((opt->type & (OT_ARRAY | OT_URI)) == (OT_ARRAY | OT_URI)) { 852 #ifdef SMALL 853 errno = ENOTSUP; 854 return -1; 855 #else 856 char buf[UINT16_MAX + 1]; 857 uint16_t sz; 858 bool first = true; 859 860 while (dl) { 861 if (dl < 2) { 862 errno = EINVAL; 863 goto err; 864 } 865 866 memcpy(&u16, data, sizeof(u16)); 867 sz = ntohs(u16); 868 data += sizeof(u16); 869 dl -= sizeof(u16); 870 871 if (sz == 0) 872 continue; 873 if (sz > dl) { 874 errno = EINVAL; 875 goto err; 876 } 877 878 if (print_string(buf, sizeof(buf), opt->type, data, 879 sz) == -1) 880 goto err; 881 882 if (first) 883 first = false; 884 else if (fputc(' ', fp) == EOF) 885 goto err; 886 887 if (fprintf(fp, "%s", buf) == -1) 888 goto err; 889 890 data += sz; 891 dl -= sz; 892 } 893 894 if (fputc('\0', fp) == EOF) 895 goto err; 896 return 0; 897 #endif 898 } 899 900 if (opt->type & (OT_STRING | OT_URI)) { 901 char buf[1024]; 902 903 if (print_string(buf, sizeof(buf), opt->type, data, dl) == -1) 904 goto err; 905 return efprintf(fp, "%s", buf); 906 } 907 908 if (opt->type & OT_FLAG) 909 return efprintf(fp, "1"); 910 911 if (opt->type & OT_BITFLAG) { 912 /* bitflags are a string, MSB first, such as ABCDEFGH 913 * where A is 10000000, B is 01000000, etc. */ 914 for (l = 0, sl = sizeof(opt->bitflags) - 1; 915 l < sizeof(opt->bitflags); l++, sl--) { 916 if (opt->bitflags[l] == '1') { 917 if (fprintf(fp, "%d", *data & (1 << sl)) == -1) 918 goto err; 919 continue; 920 } 921 /* Don't print NULL or 0 flags */ 922 if (opt->bitflags[l] != '\0' && 923 opt->bitflags[l] != '0' && *data & (1 << sl)) { 924 if (fputc(opt->bitflags[l], fp) == EOF) 925 goto err; 926 } 927 } 928 goto done; 929 } 930 931 t = data; 932 e = data + dl; 933 while (data < e) { 934 if (data != t) { 935 if (fputc(' ', fp) == EOF) 936 goto err; 937 } 938 if (opt->type & OT_UINT8) { 939 if (fprintf(fp, "%u", *data) == -1) 940 goto err; 941 data++; 942 } else if (opt->type & OT_INT8) { 943 if (fprintf(fp, "%d", *data) == -1) 944 goto err; 945 data++; 946 } else if (opt->type & OT_UINT16) { 947 memcpy(&u16, data, sizeof(u16)); 948 u16 = ntohs(u16); 949 if (fprintf(fp, "%u", u16) == -1) 950 goto err; 951 data += sizeof(u16); 952 } else if (opt->type & OT_INT16) { 953 memcpy(&u16, data, sizeof(u16)); 954 s16 = (int16_t)ntohs(u16); 955 if (fprintf(fp, "%d", s16) == -1) 956 goto err; 957 data += sizeof(u16); 958 } else if (opt->type & OT_UINT32) { 959 memcpy(&u32, data, sizeof(u32)); 960 u32 = ntohl(u32); 961 if (fprintf(fp, "%u", u32) == -1) 962 goto err; 963 data += sizeof(u32); 964 } else if (opt->type & OT_INT32) { 965 memcpy(&u32, data, sizeof(u32)); 966 s32 = (int32_t)ntohl(u32); 967 if (fprintf(fp, "%d", s32) == -1) 968 goto err; 969 data += sizeof(u32); 970 } else if (opt->type & OT_ADDRIPV4) { 971 memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 972 if (fprintf(fp, "%s", inet_ntoa(addr)) == -1) 973 goto err; 974 data += sizeof(addr.s_addr); 975 } else if (opt->type & OT_ADDRIPV6) { 976 uint8_t databuf[sizeof(struct in6_addr)] = { 0 }; 977 size_t datalen = e - data >= 16 ? 16 : 978 (size_t)(e - data); 979 char buf[INET6_ADDRSTRLEN]; 980 981 /* avoid inet_ntop going beyond our option space by 982 * copying out into a temporary buffer. */ 983 memcpy(databuf, data, datalen); 984 if (inet_ntop(AF_INET6, databuf, buf, sizeof(buf)) == 985 NULL) 986 goto err; 987 if (fprintf(fp, "%s", buf) == -1) 988 goto err; 989 if (datalen >= 2 && data[0] == 0xfe && 990 (data[1] & 0xc0) == 0x80) { 991 if (fprintf(fp, "%%%s", ifname) == -1) 992 goto err; 993 } 994 data += 16; 995 } else { 996 errno = EINVAL; 997 goto err; 998 } 999 } 1000 1001 done: 1002 if (fputc('\0', fp) == EOF) 1003 return -1; 1004 return 1; 1005 1006 err: 1007 (void)fsetpos(fp, &fp_pos); 1008 return -1; 1009 } 1010 1011 int 1012 dhcp_set_leasefile(char *leasefile, size_t len, int family, 1013 const struct interface *ifp) 1014 { 1015 char ifname[(sizeof(ifp->name) * 4) + 1]; 1016 char ssid[1 + (IF_SSIDLEN * 4) + 1]; /* - prefix and NUL terminated. */ 1017 1018 if (ifp->name[0] == '\0') { 1019 strlcpy(leasefile, ifp->ctx->pidfile, len); 1020 return 0; 1021 } 1022 1023 switch (family) { 1024 case AF_INET: 1025 case AF_INET6: 1026 break; 1027 default: 1028 errno = EINVAL; 1029 return -1; 1030 } 1031 1032 if (print_string(ifname, sizeof(ifname), OT_ESCFILE, ifp->name, 1033 strlen(ifp->name)) == -1) 1034 return -1; 1035 1036 if (ifp->wireless) { 1037 ssid[0] = '-'; 1038 if (print_string(ssid + 1, sizeof(ssid) - 1, OT_ESCFILE, 1039 ifp->ssid, ifp->ssid_len) == -1) 1040 return -1; 1041 } else 1042 ssid[0] = '\0'; 1043 return snprintf(leasefile, len, 1044 family == AF_INET ? LEASEFILE : LEASEFILE6, ifname, ssid); 1045 } 1046 1047 void 1048 dhcp_envoption(struct dhcpcd_ctx *ctx, FILE *fp, const char *prefix, 1049 const char *ifname, struct dhcp_opt *opt, 1050 const uint8_t *(*dgetopt)(struct dhcpcd_ctx *, size_t *, unsigned int *, 1051 size_t *, const uint8_t *, size_t, struct dhcp_opt **), 1052 const uint8_t *od, size_t ol) 1053 { 1054 size_t i, eos, eol; 1055 ssize_t eo; 1056 unsigned int eoc; 1057 const uint8_t *eod; 1058 int ov; 1059 struct dhcp_opt *eopt, *oopt; 1060 char *pfx; 1061 1062 /* If no embedded or encapsulated options, it's easy */ 1063 if (opt->embopts_len == 0 && opt->encopts_len == 0) { 1064 if (opt->type & OT_RESERVED) 1065 return; 1066 if (print_option(fp, prefix, opt, 1, od, ol, ifname) == -1) 1067 logerr("%s: %s %d", ifname, __func__, opt->option); 1068 return; 1069 } 1070 1071 /* Create a new prefix based on the option */ 1072 if (opt->type & OT_INDEX) { 1073 if (asprintf(&pfx, "%s_%s%d", prefix, opt->var, ++opt->index) == 1074 -1) 1075 pfx = NULL; 1076 } else { 1077 if (asprintf(&pfx, "%s_%s", prefix, opt->var) == -1) 1078 pfx = NULL; 1079 } 1080 if (pfx == NULL) { 1081 logerr(__func__); 1082 return; 1083 } 1084 1085 /* Embedded options are always processed first as that 1086 * is a fixed layout */ 1087 for (i = 0, eopt = opt->embopts; i < opt->embopts_len; i++, eopt++) { 1088 eo = dhcp_optlen(eopt, ol); 1089 if (eo == -1) { 1090 logerrx("%s: %s %d.%d/%zu: " 1091 "malformed embedded option", 1092 ifname, __func__, opt->option, eopt->option, i); 1093 goto out; 1094 } 1095 if (eo == 0) { 1096 /* An option was expected, but there is no data 1097 * data for it. 1098 * This may not be an error as some options like 1099 * DHCP FQDN in RFC4702 have a string as the last 1100 * option which is optional. */ 1101 if (ol != 0 || !(eopt->type & OT_OPTIONAL)) 1102 logerrx("%s: %s %d.%d/%zu: " 1103 "missing embedded option", 1104 ifname, __func__, opt->option, eopt->option, 1105 i); 1106 goto out; 1107 } 1108 /* Use the option prefix if the embedded option 1109 * name is different. 1110 * This avoids new_fqdn_fqdn which would be silly. */ 1111 if (!(eopt->type & OT_RESERVED)) { 1112 ov = strcmp(opt->var, eopt->var); 1113 if (print_option(fp, pfx, eopt, ov, od, (size_t)eo, 1114 ifname) == -1) 1115 logerr("%s: %s %d.%d/%zu", ifname, __func__, 1116 opt->option, eopt->option, i); 1117 } 1118 od += (size_t)eo; 1119 ol -= (size_t)eo; 1120 } 1121 1122 /* Enumerate our encapsulated options */ 1123 if (opt->encopts_len && ol > 0) { 1124 /* Zero any option indexes 1125 * We assume that referenced encapsulated options are NEVER 1126 * recursive as the index order could break. */ 1127 for (i = 0, eopt = opt->encopts; i < opt->encopts_len; 1128 i++, eopt++) { 1129 eoc = opt->option; 1130 if (eopt->type & OT_OPTION) { 1131 dgetopt(ctx, NULL, &eoc, NULL, NULL, 0, &oopt); 1132 if (oopt) 1133 oopt->index = 0; 1134 } 1135 } 1136 1137 while ((eod = dgetopt(ctx, &eos, &eoc, &eol, od, ol, &oopt))) { 1138 for (i = 0, eopt = opt->encopts; i < opt->encopts_len; 1139 i++, eopt++) { 1140 if (eopt->option != eoc) 1141 continue; 1142 if (eopt->type & OT_OPTION) { 1143 if (oopt == NULL) 1144 /* Report error? */ 1145 continue; 1146 } 1147 dhcp_envoption(ctx, fp, pfx, ifname, 1148 eopt->type & OT_OPTION ? oopt : eopt, 1149 dgetopt, eod, eol); 1150 } 1151 od += eos + eol; 1152 ol -= eos + eol; 1153 } 1154 } 1155 1156 out: 1157 free(pfx); 1158 } 1159 1160 void 1161 dhcp_zero_index(struct dhcp_opt *opt) 1162 { 1163 size_t i; 1164 struct dhcp_opt *o; 1165 1166 opt->index = 0; 1167 for (i = 0, o = opt->embopts; i < opt->embopts_len; i++, o++) 1168 dhcp_zero_index(o); 1169 for (i = 0, o = opt->encopts; i < opt->encopts_len; i++, o++) 1170 dhcp_zero_index(o); 1171 } 1172 1173 ssize_t 1174 dhcp_readfile(struct dhcpcd_ctx *ctx, const char *file, void **data, 1175 size_t *len) 1176 { 1177 size_t rlen = 0; 1178 1179 if (len == NULL) 1180 len = &rlen; 1181 1182 if (file == NULL || *file == '\0') { 1183 uint8_t *p = *data; 1184 size_t needed = BUFSIZ, bytes = 0, left; 1185 ssize_t nread; 1186 1187 for (;;) { 1188 if (*len < needed) { 1189 void *nbuf = realloc(*data, needed); 1190 if (nbuf == NULL) 1191 return -1; 1192 p = *data = nbuf; 1193 p += bytes; 1194 *len = needed; 1195 } 1196 1197 left = *len - bytes; 1198 nread = read(fileno(stdin), p, left); 1199 if (nread == -1) 1200 return -1; 1201 bytes += (size_t)nread; 1202 if ((size_t)nread < left || nread == 0) 1203 return (ssize_t)bytes; 1204 1205 /* We need a bigger buffer */ 1206 needed += BUFSIZ; 1207 } 1208 } 1209 1210 #ifdef PRIVSEP 1211 if (file != NULL && ctx->options & DHCPCD_PRIVSEP && 1212 !(ctx->options & DHCPCD_PRIVSEPROOT)) 1213 return ps_root_readfile(ctx, file, data, len); 1214 #else 1215 UNUSED(ctx); 1216 #endif 1217 1218 return readfile(file, data, len); 1219 } 1220 1221 ssize_t 1222 dhcp_writefile(struct dhcpcd_ctx *ctx, const char *file, mode_t mode, 1223 const void *data, size_t len) 1224 { 1225 #ifdef PRIVSEP 1226 if (ctx->options & DHCPCD_PRIVSEP && 1227 !(ctx->options & DHCPCD_PRIVSEPROOT)) 1228 return ps_root_writefile(ctx, file, mode, data, len); 1229 #else 1230 UNUSED(ctx); 1231 #endif 1232 1233 return writefile(file, mode, data, len); 1234 } 1235 1236 int 1237 dhcp_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time) 1238 { 1239 #ifdef PRIVSEP 1240 if (ctx->options & DHCPCD_PRIVSEP && 1241 !(ctx->options & DHCPCD_PRIVSEPROOT)) 1242 return (int)ps_root_filemtime(ctx, file, time); 1243 #else 1244 UNUSED(ctx); 1245 #endif 1246 1247 return filemtime(file, time); 1248 } 1249 1250 int 1251 dhcp_unlink(struct dhcpcd_ctx *ctx, const char *file) 1252 { 1253 #ifdef PRIVSEP 1254 if (ctx->options & DHCPCD_PRIVSEP && 1255 !(ctx->options & DHCPCD_PRIVSEPROOT)) 1256 return (int)ps_root_unlink(ctx, file); 1257 #else 1258 UNUSED(ctx); 1259 #endif 1260 1261 return unlink(file); 1262 } 1263 1264 size_t 1265 dhcp_read_hwaddr_aton(struct dhcpcd_ctx *ctx, uint8_t **data, const char *file) 1266 { 1267 ssize_t bytes; 1268 size_t len; 1269 1270 bytes = dhcp_readfile(ctx, file, &ctx->io_buf, &ctx->io_buflen); 1271 if (bytes == -1) 1272 return 0; 1273 len = hwaddr_aton(NULL, ctx->io_buf); 1274 if (len == 0) 1275 return 0; 1276 *data = malloc(len); 1277 if (*data == NULL) 1278 return 0; 1279 hwaddr_aton(*data, ctx->io_buf); 1280 return len; 1281 } 1282