1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2018 Roy Marples <roy@marples.name> 4 * All rights reserved 5 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/stat.h> 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 <arpa/nameser.h> /* after normal includes for sunos */ 40 41 #include "config.h" 42 43 #include "common.h" 44 #include "dhcp-common.h" 45 #include "dhcp.h" 46 #include "if.h" 47 #include "ipv6.h" 48 #include "logerr.h" 49 50 /* Support very old arpa/nameser.h as found in OpenBSD */ 51 #ifndef NS_MAXDNAME 52 #define NS_MAXCDNAME MAXCDNAME 53 #define NS_MAXDNAME MAXDNAME 54 #define NS_MAXLABEL MAXLABEL 55 #endif 56 57 const char * 58 dhcp_get_hostname(char *buf, size_t buf_len, const struct if_options *ifo) 59 { 60 61 if (ifo->hostname[0] == '\0') { 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] == '.' || 70 strcmp(buf, "(none)") == 0 || 71 strcmp(buf, "localhost") == 0 || 72 strncmp(buf, "localhost.", strlen("localhost.")) == 0) 73 return NULL; 74 75 /* Shorten the hostname if required */ 76 if (ifo->options & DHCPCD_HOSTNAME_SHORT) { 77 char *hp; 78 79 hp = strchr(buf, '.'); 80 if (hp != NULL) 81 *hp = '\0'; 82 } 83 84 return buf; 85 } 86 87 void 88 dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols) 89 { 90 91 while (cols < 40) { 92 putchar(' '); 93 cols++; 94 } 95 putchar('\t'); 96 if (opt->type & OT_EMBED) 97 printf(" embed"); 98 if (opt->type & OT_ENCAP) 99 printf(" encap"); 100 if (opt->type & OT_INDEX) 101 printf(" index"); 102 if (opt->type & OT_ARRAY) 103 printf(" array"); 104 if (opt->type & OT_UINT8) 105 printf(" uint8"); 106 else if (opt->type & OT_INT8) 107 printf(" int8"); 108 else if (opt->type & OT_UINT16) 109 printf(" uint16"); 110 else if (opt->type & OT_INT16) 111 printf(" int16"); 112 else if (opt->type & OT_UINT32) 113 printf(" uint32"); 114 else if (opt->type & OT_INT32) 115 printf(" int32"); 116 else if (opt->type & OT_ADDRIPV4) 117 printf(" ipaddress"); 118 else if (opt->type & OT_ADDRIPV6) 119 printf(" ip6address"); 120 else if (opt->type & OT_FLAG) 121 printf(" flag"); 122 else if (opt->type & OT_BITFLAG) 123 printf(" bitflags"); 124 else if (opt->type & OT_RFC1035) 125 printf(" domain"); 126 else if (opt->type & OT_DOMAIN) 127 printf(" dname"); 128 else if (opt->type & OT_ASCII) 129 printf(" ascii"); 130 else if (opt->type & OT_RAW) 131 printf(" raw"); 132 else if (opt->type & OT_BINHEX) 133 printf(" binhex"); 134 else if (opt->type & OT_STRING) 135 printf(" string"); 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 putchar('\n'); 145 } 146 147 struct dhcp_opt * 148 vivso_find(uint32_t iana_en, const void *arg) 149 { 150 const struct interface *ifp; 151 size_t i; 152 struct dhcp_opt *opt; 153 154 ifp = arg; 155 for (i = 0, opt = ifp->options->vivso_override; 156 i < ifp->options->vivso_override_len; 157 i++, opt++) 158 if (opt->option == iana_en) 159 return opt; 160 for (i = 0, opt = ifp->ctx->vivso; 161 i < ifp->ctx->vivso_len; 162 i++, opt++) 163 if (opt->option == iana_en) 164 return opt; 165 return NULL; 166 } 167 168 ssize_t 169 dhcp_vendor(char *str, size_t len) 170 { 171 struct utsname utn; 172 char *p; 173 int l; 174 175 if (uname(&utn) == -1) 176 return (ssize_t)snprintf(str, len, "%s-%s", 177 PACKAGE, VERSION); 178 p = str; 179 l = snprintf(p, len, 180 "%s-%s:%s-%s:%s", PACKAGE, VERSION, 181 utn.sysname, utn.release, utn.machine); 182 if (l == -1 || (size_t)(l + 1) > len) 183 return -1; 184 p += l; 185 len -= (size_t)l; 186 l = if_machinearch(p, len); 187 if (l == -1 || (size_t)(l + 1) > len) 188 return -1; 189 p += l; 190 return p - str; 191 } 192 193 int 194 make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len, 195 const struct dhcp_opt *odopts, size_t odopts_len, 196 uint8_t *mask, const char *opts, int add) 197 { 198 char *token, *o, *p; 199 const struct dhcp_opt *opt; 200 int match, e; 201 unsigned int n; 202 size_t i; 203 204 if (opts == NULL) 205 return -1; 206 o = p = strdup(opts); 207 while ((token = strsep(&p, ", "))) { 208 if (*token == '\0') 209 continue; 210 match = 0; 211 for (i = 0, opt = odopts; i < odopts_len; i++, opt++) { 212 if (opt->var == NULL || opt->option == 0) 213 continue; /* buggy dhcpcd-definitions.conf */ 214 if (strcmp(opt->var, token) == 0) 215 match = 1; 216 else { 217 n = (unsigned int)strtou(token, NULL, 0, 218 0, UINT_MAX, &e); 219 if (e == 0 && opt->option == n) 220 match = 1; 221 } 222 if (match) 223 break; 224 } 225 if (match == 0) { 226 for (i = 0, opt = dopts; i < dopts_len; i++, opt++) { 227 if (strcmp(opt->var, token) == 0) 228 match = 1; 229 else { 230 n = (unsigned int)strtou(token, NULL, 0, 231 0, UINT_MAX, &e); 232 if (e == 0 && opt->option == n) 233 match = 1; 234 } 235 if (match) 236 break; 237 } 238 } 239 if (!match || !opt->option) { 240 free(o); 241 errno = ENOENT; 242 return -1; 243 } 244 if (add == 2 && !(opt->type & OT_ADDRIPV4)) { 245 free(o); 246 errno = EINVAL; 247 return -1; 248 } 249 if (add == 1 || add == 2) 250 add_option_mask(mask, opt->option); 251 else 252 del_option_mask(mask, opt->option); 253 } 254 free(o); 255 return 0; 256 } 257 258 size_t 259 encode_rfc1035(const char *src, uint8_t *dst) 260 { 261 uint8_t *p; 262 uint8_t *lp; 263 size_t len; 264 uint8_t has_dot; 265 266 if (src == NULL || *src == '\0') 267 return 0; 268 269 if (dst) { 270 p = dst; 271 lp = p++; 272 } 273 /* Silence bogus GCC warnings */ 274 else 275 p = lp = NULL; 276 277 len = 1; 278 has_dot = 0; 279 for (; *src; src++) { 280 if (*src == '\0') 281 break; 282 if (*src == '.') { 283 /* Skip the trailing . */ 284 if (src[1] == '\0') 285 break; 286 has_dot = 1; 287 if (dst) { 288 *lp = (uint8_t)(p - lp - 1); 289 if (*lp == '\0') 290 return len; 291 lp = p++; 292 } 293 } else if (dst) 294 *p++ = (uint8_t)*src; 295 len++; 296 } 297 298 if (dst) { 299 *lp = (uint8_t)(p - lp - 1); 300 if (has_dot) 301 *p++ = '\0'; 302 } 303 304 if (has_dot) 305 len++; 306 307 return len; 308 } 309 310 /* Decode an RFC1035 DNS search order option into a space 311 * separated string. Returns length of string (including 312 * terminating zero) or zero on error. out may be NULL 313 * to just determine output length. */ 314 ssize_t 315 decode_rfc1035(char *out, size_t len, const uint8_t *p, size_t pl) 316 { 317 const char *start; 318 size_t start_len, l, d_len, o_len; 319 const uint8_t *r, *q = p, *e; 320 int hops; 321 uint8_t ltype; 322 323 o_len = 0; 324 start = out; 325 start_len = len; 326 q = p; 327 e = p + pl; 328 while (q < e) { 329 r = NULL; 330 d_len = 0; 331 hops = 0; 332 /* Check we are inside our length again in-case 333 * the name isn't fully qualified (ie, not terminated) */ 334 while (q < e && (l = (size_t)*q++)) { 335 ltype = l & 0xc0; 336 if (ltype == 0x80 || ltype == 0x40) { 337 /* Currently reserved for future use as noted 338 * in RFC1035 4.1.4 as the 10 and 01 339 * combinations. */ 340 errno = ENOTSUP; 341 return -1; 342 } 343 else if (ltype == 0xc0) { /* pointer */ 344 if (q == e) { 345 errno = ERANGE; 346 return -1; 347 } 348 l = (l & 0x3f) << 8; 349 l |= *q++; 350 /* save source of first jump. */ 351 if (!r) 352 r = q; 353 hops++; 354 if (hops > 255) { 355 errno = ERANGE; 356 return -1; 357 } 358 q = p + l; 359 if (q >= e) { 360 errno = ERANGE; 361 return -1; 362 } 363 } else { 364 /* straightforward name segment, add with '.' */ 365 if (q + l > e) { 366 errno = ERANGE; 367 return -1; 368 } 369 if (l > NS_MAXLABEL) { 370 errno = EINVAL; 371 return -1; 372 } 373 d_len += l + 1; 374 if (out) { 375 if (l + 1 > len) { 376 errno = ENOBUFS; 377 return -1; 378 } 379 memcpy(out, q, l); 380 out += l; 381 *out++ = '.'; 382 len -= l; 383 len--; 384 } 385 q += l; 386 } 387 } 388 389 /* Don't count the trailing NUL */ 390 if (d_len > NS_MAXDNAME + 1) { 391 errno = E2BIG; 392 return -1; 393 } 394 o_len += d_len; 395 396 /* change last dot to space */ 397 if (out && out != start) 398 *(out - 1) = ' '; 399 if (r) 400 q = r; 401 } 402 403 /* change last space to zero terminator */ 404 if (out) { 405 if (out != start) 406 *(out - 1) = '\0'; 407 else if (start_len > 0) 408 *out = '\0'; 409 } 410 411 /* Remove the trailing NUL */ 412 if (o_len != 0) 413 o_len--; 414 415 return (ssize_t)o_len; 416 } 417 418 /* Check for a valid name as per RFC952 and RFC1123 section 2.1 */ 419 static int 420 valid_domainname(char *lbl, int type) 421 { 422 char *slbl, *lst; 423 unsigned char c; 424 int start, len, errset; 425 426 if (lbl == NULL || *lbl == '\0') { 427 errno = EINVAL; 428 return 0; 429 } 430 431 slbl = lbl; 432 lst = NULL; 433 start = 1; 434 len = errset = 0; 435 for (;;) { 436 c = (unsigned char)*lbl++; 437 if (c == '\0') 438 return 1; 439 if (c == ' ') { 440 if (lbl - 1 == slbl) /* No space at start */ 441 break; 442 if (!(type & OT_ARRAY)) 443 break; 444 /* Skip to the next label */ 445 if (!start) { 446 start = 1; 447 lst = lbl - 1; 448 } 449 if (len) 450 len = 0; 451 continue; 452 } 453 if (c == '.') { 454 if (*lbl == '.') 455 break; 456 len = 0; 457 continue; 458 } 459 if (((c == '-' || c == '_') && 460 !start && *lbl != ' ' && *lbl != '\0') || 461 isalnum(c)) 462 { 463 if (++len > NS_MAXLABEL) { 464 errno = ERANGE; 465 errset = 1; 466 break; 467 } 468 } else 469 break; 470 if (start) 471 start = 0; 472 } 473 474 if (!errset) 475 errno = EINVAL; 476 if (lst) { 477 /* At least one valid domain, return it */ 478 *lst = '\0'; 479 return 1; 480 } 481 return 0; 482 } 483 484 /* 485 * Prints a chunk of data to a string. 486 * PS_SHELL goes as it is these days, it's upto the target to validate it. 487 * PS_SAFE has all non ascii and non printables changes to escaped octal. 488 */ 489 static const char hexchrs[] = "0123456789abcdef"; 490 ssize_t 491 print_string(char *dst, size_t len, int type, const uint8_t *data, size_t dl) 492 { 493 char *odst; 494 uint8_t c; 495 const uint8_t *e; 496 size_t bytes; 497 498 odst = dst; 499 bytes = 0; 500 e = data + dl; 501 502 while (data < e) { 503 c = *data++; 504 if (type & OT_BINHEX) { 505 if (dst) { 506 if (len == 0 || len == 1) { 507 errno = ENOBUFS; 508 return -1; 509 } 510 *dst++ = hexchrs[(c & 0xF0) >> 4]; 511 *dst++ = hexchrs[(c & 0x0F)]; 512 len -= 2; 513 } 514 bytes += 2; 515 continue; 516 } 517 if (type & OT_ASCII && (!isascii(c))) { 518 errno = EINVAL; 519 break; 520 } 521 if (!(type & (OT_ASCII | OT_RAW | OT_ESCSTRING | OT_ESCFILE)) && 522 (!isascii(c) && !isprint(c))) 523 { 524 errno = EINVAL; 525 break; 526 } 527 if ((type & (OT_ESCSTRING | OT_ESCFILE) && 528 (c == '\\' || !isascii(c) || !isprint(c))) || 529 (type & OT_ESCFILE && (c == '/' || c == ' '))) 530 { 531 errno = EINVAL; 532 if (c == '\\') { 533 if (dst) { 534 if (len == 0 || len == 1) { 535 errno = ENOBUFS; 536 return -1; 537 } 538 *dst++ = '\\'; *dst++ = '\\'; 539 len -= 2; 540 } 541 bytes += 2; 542 continue; 543 } 544 if (dst) { 545 if (len < 5) { 546 errno = ENOBUFS; 547 return -1; 548 } 549 *dst++ = '\\'; 550 *dst++ = (char)(((c >> 6) & 03) + '0'); 551 *dst++ = (char)(((c >> 3) & 07) + '0'); 552 *dst++ = (char)(( c & 07) + '0'); 553 len -= 4; 554 } 555 bytes += 4; 556 } else { 557 if (dst) { 558 if (len == 0) { 559 errno = ENOBUFS; 560 return -1; 561 } 562 *dst++ = (char)c; 563 len--; 564 } 565 bytes++; 566 } 567 } 568 569 /* NULL */ 570 if (dst) { 571 if (len == 0) { 572 errno = ENOBUFS; 573 return -1; 574 } 575 *dst = '\0'; 576 577 /* Now we've printed it, validate the domain */ 578 if (type & OT_DOMAIN && !valid_domainname(odst, type)) { 579 *odst = '\0'; 580 return 1; 581 } 582 583 } 584 585 return (ssize_t)bytes; 586 } 587 588 #define ADDR6SZ 16 589 static ssize_t 590 dhcp_optlen(const struct dhcp_opt *opt, size_t dl) 591 { 592 size_t sz; 593 594 if (opt->type & OT_ADDRIPV6) 595 sz = ADDR6SZ; 596 else if (opt->type & (OT_INT32 | OT_UINT32 | OT_ADDRIPV4)) 597 sz = sizeof(uint32_t); 598 else if (opt->type & (OT_INT16 | OT_UINT16)) 599 sz = sizeof(uint16_t); 600 else if (opt->type & (OT_INT8 | OT_UINT8 | OT_BITFLAG)) 601 sz = sizeof(uint8_t); 602 else if (opt->type & OT_FLAG) 603 return 0; 604 else { 605 /* All other types are variable length */ 606 if (opt->len) { 607 if ((size_t)opt->len > dl) { 608 errno = EOVERFLOW; 609 return -1; 610 } 611 return (ssize_t)opt->len; 612 } 613 return (ssize_t)dl; 614 } 615 if (dl < sz) { 616 errno = EOVERFLOW; 617 return -1; 618 } 619 620 /* Trim any extra data. 621 * Maybe we need a settng to reject DHCP options with extra data? */ 622 if (opt->type & OT_ARRAY) 623 return (ssize_t)(dl - (dl % sz)); 624 return (ssize_t)sz; 625 } 626 627 /* It's possible for DHCPv4 to contain an IPv6 address */ 628 static ssize_t 629 ipv6_printaddr(char *s, size_t sl, const uint8_t *d, const char *ifname) 630 { 631 char buf[INET6_ADDRSTRLEN]; 632 const char *p; 633 size_t l; 634 635 p = inet_ntop(AF_INET6, d, buf, sizeof(buf)); 636 if (p == NULL) 637 return -1; 638 639 l = strlen(p); 640 if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80) 641 l += 1 + strlen(ifname); 642 643 if (s == NULL) 644 return (ssize_t)l; 645 646 if (sl < l) { 647 errno = ENOMEM; 648 return -1; 649 } 650 651 s += strlcpy(s, p, sl); 652 if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80) { 653 *s++ = '%'; 654 s += strlcpy(s, ifname, sl); 655 } 656 *s = '\0'; 657 return (ssize_t)l; 658 } 659 660 static ssize_t 661 print_option(char *s, size_t len, const struct dhcp_opt *opt, 662 const uint8_t *data, size_t dl, const char *ifname) 663 { 664 const uint8_t *e, *t; 665 uint16_t u16; 666 int16_t s16; 667 uint32_t u32; 668 int32_t s32; 669 struct in_addr addr; 670 ssize_t bytes = 0, sl; 671 size_t l; 672 #ifdef INET 673 char *tmp; 674 #endif 675 676 if (opt->type & OT_RFC1035) { 677 sl = decode_rfc1035(s, len, data, dl); 678 if (sl == 0 || sl == -1) 679 return sl; 680 if (s != NULL) { 681 if (valid_domainname(s, opt->type) == -1) 682 return -1; 683 } 684 return sl; 685 } 686 687 #ifdef INET 688 if (opt->type & OT_RFC3361) { 689 if ((tmp = decode_rfc3361(data, dl)) == NULL) 690 return -1; 691 l = strlen(tmp); 692 sl = print_string(s, len, opt->type, (uint8_t *)tmp, l); 693 free(tmp); 694 return sl; 695 } 696 697 if (opt->type & OT_RFC3442) 698 return decode_rfc3442(s, len, data, dl); 699 #endif 700 701 if (opt->type & OT_STRING) 702 return print_string(s, len, opt->type, data, dl); 703 704 if (opt->type & OT_FLAG) { 705 if (s) { 706 *s++ = '1'; 707 *s = '\0'; 708 } 709 return 1; 710 } 711 712 if (opt->type & OT_BITFLAG) { 713 /* bitflags are a string, MSB first, such as ABCDEFGH 714 * where A is 10000000, B is 01000000, etc. */ 715 bytes = 0; 716 for (l = 0, sl = sizeof(opt->bitflags) - 1; 717 l < sizeof(opt->bitflags); 718 l++, sl--) 719 { 720 /* Don't print NULL or 0 flags */ 721 if (opt->bitflags[l] != '\0' && 722 opt->bitflags[l] != '0' && 723 *data & (1 << sl)) 724 { 725 if (s) 726 *s++ = opt->bitflags[l]; 727 bytes++; 728 } 729 } 730 if (s) 731 *s = '\0'; 732 return bytes; 733 } 734 735 if (!s) { 736 if (opt->type & OT_UINT8) 737 l = 3; 738 else if (opt->type & OT_INT8) 739 l = 4; 740 else if (opt->type & OT_UINT16) { 741 l = 5; 742 dl /= 2; 743 } else if (opt->type & OT_INT16) { 744 l = 6; 745 dl /= 2; 746 } else if (opt->type & OT_UINT32) { 747 l = 10; 748 dl /= 4; 749 } else if (opt->type & OT_INT32) { 750 l = 11; 751 dl /= 4; 752 } else if (opt->type & OT_ADDRIPV4) { 753 l = 16; 754 dl /= 4; 755 } else if (opt->type & OT_ADDRIPV6) { 756 e = data + dl; 757 l = 0; 758 while (data < e) { 759 if (l) 760 l++; /* space */ 761 sl = ipv6_printaddr(NULL, 0, data, ifname); 762 if (sl == -1) 763 return l == 0 ? -1 : (ssize_t)l; 764 l += (size_t)sl; 765 data += 16; 766 } 767 return (ssize_t)l; 768 } else { 769 errno = EINVAL; 770 return -1; 771 } 772 return (ssize_t)(l * dl); 773 } 774 775 t = data; 776 e = data + dl; 777 while (data < e) { 778 if (data != t) { 779 *s++ = ' '; 780 bytes++; 781 len--; 782 } 783 if (opt->type & OT_UINT8) { 784 sl = snprintf(s, len, "%u", *data); 785 data++; 786 } else if (opt->type & OT_INT8) { 787 sl = snprintf(s, len, "%d", *data); 788 data++; 789 } else if (opt->type & OT_UINT16) { 790 memcpy(&u16, data, sizeof(u16)); 791 u16 = ntohs(u16); 792 sl = snprintf(s, len, "%u", u16); 793 data += sizeof(u16); 794 } else if (opt->type & OT_INT16) { 795 memcpy(&u16, data, sizeof(u16)); 796 s16 = (int16_t)ntohs(u16); 797 sl = snprintf(s, len, "%d", s16); 798 data += sizeof(u16); 799 } else if (opt->type & OT_UINT32) { 800 memcpy(&u32, data, sizeof(u32)); 801 u32 = ntohl(u32); 802 sl = snprintf(s, len, "%u", u32); 803 data += sizeof(u32); 804 } else if (opt->type & OT_INT32) { 805 memcpy(&u32, data, sizeof(u32)); 806 s32 = (int32_t)ntohl(u32); 807 sl = snprintf(s, len, "%d", s32); 808 data += sizeof(u32); 809 } else if (opt->type & OT_ADDRIPV4) { 810 memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 811 sl = snprintf(s, len, "%s", inet_ntoa(addr)); 812 data += sizeof(addr.s_addr); 813 } else if (opt->type & OT_ADDRIPV6) { 814 sl = ipv6_printaddr(s, len, data, ifname); 815 data += 16; 816 } else { 817 errno = EINVAL; 818 return -1; 819 } 820 if (sl == -1) 821 return bytes == 0 ? -1 : bytes; 822 len -= (size_t)sl; 823 bytes += sl; 824 s += sl; 825 } 826 827 return bytes; 828 } 829 830 int 831 dhcp_set_leasefile(char *leasefile, size_t len, int family, 832 const struct interface *ifp) 833 { 834 char ssid[1 + (IF_SSIDLEN * 4) + 1]; /* - prefix and NUL terminated. */ 835 836 if (ifp->name[0] == '\0') { 837 strlcpy(leasefile, ifp->ctx->pidfile, len); 838 return 0; 839 } 840 841 switch (family) { 842 case AF_INET: 843 case AF_INET6: 844 break; 845 default: 846 errno = EINVAL; 847 return -1; 848 } 849 850 if (ifp->wireless) { 851 ssid[0] = '-'; 852 print_string(ssid + 1, sizeof(ssid) - 1, 853 OT_ESCFILE, 854 (const uint8_t *)ifp->ssid, ifp->ssid_len); 855 } else 856 ssid[0] = '\0'; 857 return snprintf(leasefile, len, 858 family == AF_INET ? LEASEFILE : LEASEFILE6, 859 ifp->name, ssid); 860 } 861 862 static size_t 863 dhcp_envoption1(char **env, const char *prefix, 864 const struct dhcp_opt *opt, int vname, const uint8_t *od, size_t ol, 865 const char *ifname) 866 { 867 ssize_t len; 868 size_t e; 869 char *v, *val; 870 int r; 871 872 /* Ensure a valid length */ 873 ol = (size_t)dhcp_optlen(opt, ol); 874 if ((ssize_t)ol == -1) 875 return 0; 876 877 len = print_option(NULL, 0, opt, od, ol, ifname); 878 if (len < 0) 879 return 0; 880 if (vname) 881 e = strlen(opt->var) + 1; 882 else 883 e = 0; 884 if (prefix) 885 e += strlen(prefix); 886 e += (size_t)len + 2; 887 if (env == NULL) 888 return e; 889 v = val = *env = malloc(e); 890 if (v == NULL) 891 return 0; 892 if (vname) 893 r = snprintf(val, e, "%s_%s=", prefix, opt->var); 894 else 895 r = snprintf(val, e, "%s=", prefix); 896 if (r != -1 && len != 0) { 897 v += r; 898 if (print_option(v, (size_t)len + 1, opt, od, ol, ifname) == -1) 899 r = -1; 900 } 901 if (r == -1) { 902 free(val); 903 return 0; 904 } 905 return e; 906 } 907 908 size_t 909 dhcp_envoption(struct dhcpcd_ctx *ctx, char **env, const char *prefix, 910 const char *ifname, struct dhcp_opt *opt, 911 const uint8_t *(*dgetopt)(struct dhcpcd_ctx *, 912 size_t *, unsigned int *, size_t *, 913 const uint8_t *, size_t, struct dhcp_opt **), 914 const uint8_t *od, size_t ol) 915 { 916 size_t e, i, n, eos, eol; 917 ssize_t eo; 918 unsigned int eoc; 919 const uint8_t *eod; 920 int ov; 921 struct dhcp_opt *eopt, *oopt; 922 char *pfx; 923 924 /* If no embedded or encapsulated options, it's easy */ 925 if (opt->embopts_len == 0 && opt->encopts_len == 0) { 926 if (!(opt->type & OT_RESERVED)) { 927 if (dhcp_envoption1(env == NULL ? NULL : &env[0], 928 prefix, opt, 1, od, ol, ifname)) 929 return 1; 930 else 931 logerr("%s: %s %d", 932 ifname, __func__, opt->option); 933 } 934 return 0; 935 } 936 937 /* Create a new prefix based on the option */ 938 if (env) { 939 if (opt->type & OT_INDEX) { 940 if (opt->index > 999) { 941 errno = ENOBUFS; 942 logerr(__func__); 943 return 0; 944 } 945 } 946 e = strlen(prefix) + strlen(opt->var) + 2 + 947 (opt->type & OT_INDEX ? 3 : 0); 948 pfx = malloc(e); 949 if (pfx == NULL) { 950 logerr(__func__); 951 return 0; 952 } 953 if (opt->type & OT_INDEX) 954 snprintf(pfx, e, "%s_%s%d", prefix, 955 opt->var, ++opt->index); 956 else 957 snprintf(pfx, e, "%s_%s", prefix, opt->var); 958 } else 959 pfx = NULL; 960 961 /* Embedded options are always processed first as that 962 * is a fixed layout */ 963 n = 0; 964 for (i = 0, eopt = opt->embopts; i < opt->embopts_len; i++, eopt++) { 965 eo = dhcp_optlen(eopt, ol); 966 if (eo == -1) { 967 if (env == NULL) 968 logerrx("%s: %s %d.%d/%zu: " 969 "malformed embedded option", 970 ifname, __func__, opt->option, 971 eopt->option, i); 972 goto out; 973 } 974 if (eo == 0) { 975 /* An option was expected, but there is no data 976 * data for it. 977 * This may not be an error as some options like 978 * DHCP FQDN in RFC4702 have a string as the last 979 * option which is optional. */ 980 if (env == NULL && 981 (ol != 0 || !(eopt->type & OT_OPTIONAL))) 982 logerrx("%s: %s %d.%d/%zu: missing embedded option", 983 ifname, __func__, opt->option, 984 eopt->option, i); 985 goto out; 986 } 987 /* Use the option prefix if the embedded option 988 * name is different. 989 * This avoids new_fqdn_fqdn which would be silly. */ 990 if (!(eopt->type & OT_RESERVED)) { 991 ov = strcmp(opt->var, eopt->var); 992 if (dhcp_envoption1(env == NULL ? NULL : &env[n], 993 pfx, eopt, ov, od, (size_t)eo, ifname)) 994 n++; 995 else if (env == NULL) 996 logerr("%s: %s %d.%d/%zu", 997 ifname, __func__, 998 opt->option, eopt->option, i); 999 } 1000 od += (size_t)eo; 1001 ol -= (size_t)eo; 1002 } 1003 1004 /* Enumerate our encapsulated options */ 1005 if (opt->encopts_len && ol > 0) { 1006 /* Zero any option indexes 1007 * We assume that referenced encapsulated options are NEVER 1008 * recursive as the index order could break. */ 1009 for (i = 0, eopt = opt->encopts; 1010 i < opt->encopts_len; 1011 i++, eopt++) 1012 { 1013 eoc = opt->option; 1014 if (eopt->type & OT_OPTION) { 1015 dgetopt(ctx, NULL, &eoc, NULL, NULL, 0, &oopt); 1016 if (oopt) 1017 oopt->index = 0; 1018 } 1019 } 1020 1021 while ((eod = dgetopt(ctx, &eos, &eoc, &eol, od, ol, &oopt))) { 1022 for (i = 0, eopt = opt->encopts; 1023 i < opt->encopts_len; 1024 i++, eopt++) 1025 { 1026 if (eopt->option == eoc) { 1027 if (eopt->type & OT_OPTION) { 1028 if (oopt == NULL) 1029 /* Report error? */ 1030 continue; 1031 } 1032 n += dhcp_envoption(ctx, 1033 env == NULL ? NULL : &env[n], pfx, 1034 ifname, 1035 eopt->type & OT_OPTION ? oopt:eopt, 1036 dgetopt, eod, eol); 1037 break; 1038 } 1039 } 1040 od += eos + eol; 1041 ol -= eos + eol; 1042 } 1043 } 1044 1045 out: 1046 if (env) 1047 free(pfx); 1048 1049 /* Return number of options found */ 1050 return n; 1051 } 1052 1053 void 1054 dhcp_zero_index(struct dhcp_opt *opt) 1055 { 1056 size_t i; 1057 struct dhcp_opt *o; 1058 1059 opt->index = 0; 1060 for (i = 0, o = opt->embopts; i < opt->embopts_len; i++, o++) 1061 dhcp_zero_index(o); 1062 for (i = 0, o = opt->encopts; i < opt->encopts_len; i++, o++) 1063 dhcp_zero_index(o); 1064 } 1065 1066 size_t 1067 dhcp_read_lease_fd(int fd, void **lease) 1068 { 1069 struct stat st; 1070 size_t sz; 1071 void *buf; 1072 ssize_t len; 1073 1074 if (fstat(fd, &st) != 0) 1075 goto out; 1076 if (!S_ISREG(st.st_mode)) { 1077 errno = EINVAL; 1078 goto out; 1079 } 1080 if (st.st_size > UINT32_MAX) { 1081 errno = E2BIG; 1082 goto out; 1083 } 1084 1085 sz = (size_t)st.st_size; 1086 if ((buf = malloc(sz)) == NULL) 1087 goto out; 1088 if ((len = read(fd, buf, sz)) == -1) { 1089 free(buf); 1090 goto out; 1091 } 1092 *lease = buf; 1093 return (size_t)len; 1094 1095 out: 1096 *lease = NULL; 1097 return 0; 1098 } 1099