1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * dhcpcd - DHCP client daemon 4 * Copyright (c) 2006-2021 Roy Marples <roy@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/param.h> 30 #include <sys/types.h> 31 32 #include <arpa/inet.h> 33 34 #include <ctype.h> 35 #include <errno.h> 36 #include <getopt.h> 37 #include <grp.h> 38 #include <inttypes.h> 39 #include <limits.h> 40 #include <paths.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 #include <time.h> 46 47 #include "config.h" 48 #include "common.h" 49 #include "dhcp.h" 50 #include "dhcp6.h" 51 #include "dhcpcd-embedded.h" 52 #include "duid.h" 53 #include "if.h" 54 #include "if-options.h" 55 #include "ipv4.h" 56 #include "logerr.h" 57 #include "sa.h" 58 59 #define IN_CONFIG_BLOCK(ifo) ((ifo)->options & DHCPCD_FORKED) 60 #define SET_CONFIG_BLOCK(ifo) ((ifo)->options |= DHCPCD_FORKED) 61 #define CLEAR_CONFIG_BLOCK(ifo) ((ifo)->options &= ~DHCPCD_FORKED) 62 63 static unsigned long long default_options; 64 65 const struct option cf_options[] = { 66 {"background", no_argument, NULL, 'b'}, 67 {"script", required_argument, NULL, 'c'}, 68 {"debug", no_argument, NULL, 'd'}, 69 {"env", required_argument, NULL, 'e'}, 70 {"config", required_argument, NULL, 'f'}, 71 {"reconfigure", no_argument, NULL, 'g'}, 72 {"hostname", optional_argument, NULL, 'h'}, 73 {"vendorclassid", optional_argument, NULL, 'i'}, 74 {"logfile", required_argument, NULL, 'j'}, 75 {"release", no_argument, NULL, 'k'}, 76 {"leasetime", required_argument, NULL, 'l'}, 77 {"metric", required_argument, NULL, 'm'}, 78 {"rebind", no_argument, NULL, 'n'}, 79 {"option", required_argument, NULL, 'o'}, 80 {"persistent", no_argument, NULL, 'p'}, 81 {"quiet", no_argument, NULL, 'q'}, 82 {"request", optional_argument, NULL, 'r'}, 83 {"inform", optional_argument, NULL, 's'}, 84 {"inform6", optional_argument, NULL, O_INFORM6}, 85 {"timeout", required_argument, NULL, 't'}, 86 {"userclass", required_argument, NULL, 'u'}, 87 #ifndef SMALL 88 {"msuserclass", required_argument, NULL, O_MSUSERCLASS}, 89 #endif 90 {"vendor", required_argument, NULL, 'v'}, 91 {"waitip", optional_argument, NULL, 'w'}, 92 {"exit", no_argument, NULL, 'x'}, 93 {"allowinterfaces", required_argument, NULL, 'z'}, 94 {"reboot", required_argument, NULL, 'y'}, 95 {"noarp", no_argument, NULL, 'A'}, 96 {"nobackground", no_argument, NULL, 'B'}, 97 {"nohook", required_argument, NULL, 'C'}, 98 {"duid", optional_argument, NULL, 'D'}, 99 {"lastlease", no_argument, NULL, 'E'}, 100 {"fqdn", optional_argument, NULL, 'F'}, 101 {"nogateway", no_argument, NULL, 'G'}, 102 {"xidhwaddr", no_argument, NULL, 'H'}, 103 {"clientid", optional_argument, NULL, 'I'}, 104 {"broadcast", no_argument, NULL, 'J'}, 105 {"nolink", no_argument, NULL, 'K'}, 106 {"noipv4ll", no_argument, NULL, 'L'}, 107 {"manager", no_argument, NULL, 'M'}, 108 {"renew", no_argument, NULL, 'N'}, 109 {"nooption", required_argument, NULL, 'O'}, 110 {"printpidfile", no_argument, NULL, 'P'}, 111 {"require", required_argument, NULL, 'Q'}, 112 {"static", required_argument, NULL, 'S'}, 113 {"test", no_argument, NULL, 'T'}, 114 {"dumplease", no_argument, NULL, 'U'}, 115 {"variables", no_argument, NULL, 'V'}, 116 {"whitelist", required_argument, NULL, 'W'}, 117 {"blacklist", required_argument, NULL, 'X'}, 118 {"denyinterfaces", required_argument, NULL, 'Z'}, 119 {"oneshot", no_argument, NULL, '1'}, 120 {"ipv4only", no_argument, NULL, '4'}, 121 {"ipv6only", no_argument, NULL, '6'}, 122 {"anonymous", no_argument, NULL, O_ANONYMOUS}, 123 {"randomise_hwaddr",no_argument, NULL, O_RANDOMISE_HWADDR}, 124 {"arping", required_argument, NULL, O_ARPING}, 125 {"destination", required_argument, NULL, O_DESTINATION}, 126 {"fallback", required_argument, NULL, O_FALLBACK}, 127 {"ipv6rs", no_argument, NULL, O_IPV6RS}, 128 {"noipv6rs", no_argument, NULL, O_NOIPV6RS}, 129 {"ipv6ra_autoconf", no_argument, NULL, O_IPV6RA_AUTOCONF}, 130 {"ipv6ra_noautoconf", no_argument, NULL, O_IPV6RA_NOAUTOCONF}, 131 {"ipv6ra_fork", no_argument, NULL, O_IPV6RA_FORK}, 132 {"ipv4", no_argument, NULL, O_IPV4}, 133 {"noipv4", no_argument, NULL, O_NOIPV4}, 134 {"ipv6", no_argument, NULL, O_IPV6}, 135 {"noipv6", no_argument, NULL, O_NOIPV6}, 136 {"noalias", no_argument, NULL, O_NOALIAS}, 137 {"iaid", required_argument, NULL, O_IAID}, 138 {"ia_na", optional_argument, NULL, O_IA_NA}, 139 {"ia_ta", optional_argument, NULL, O_IA_TA}, 140 {"ia_pd", optional_argument, NULL, O_IA_PD}, 141 {"hostname_short", no_argument, NULL, O_HOSTNAME_SHORT}, 142 {"dev", required_argument, NULL, O_DEV}, 143 {"nodev", no_argument, NULL, O_NODEV}, 144 {"define", required_argument, NULL, O_DEFINE}, 145 {"definend", required_argument, NULL, O_DEFINEND}, 146 {"define6", required_argument, NULL, O_DEFINE6}, 147 {"embed", required_argument, NULL, O_EMBED}, 148 {"encap", required_argument, NULL, O_ENCAP}, 149 {"vendopt", required_argument, NULL, O_VENDOPT}, 150 {"vendclass", required_argument, NULL, O_VENDCLASS}, 151 {"authprotocol", required_argument, NULL, O_AUTHPROTOCOL}, 152 {"authtoken", required_argument, NULL, O_AUTHTOKEN}, 153 {"noauthrequired", no_argument, NULL, O_AUTHNOTREQUIRED}, 154 {"dhcp", no_argument, NULL, O_DHCP}, 155 {"nodhcp", no_argument, NULL, O_NODHCP}, 156 {"dhcp6", no_argument, NULL, O_DHCP6}, 157 {"nodhcp6", no_argument, NULL, O_NODHCP6}, 158 {"controlgroup", required_argument, NULL, O_CONTROLGRP}, 159 {"slaac", required_argument, NULL, O_SLAAC}, 160 {"gateway", no_argument, NULL, O_GATEWAY}, 161 {"reject", required_argument, NULL, O_REJECT}, 162 {"bootp", no_argument, NULL, O_BOOTP}, 163 {"nodelay", no_argument, NULL, O_NODELAY}, 164 {"noup", no_argument, NULL, O_NOUP}, 165 {"lastleaseextend", no_argument, NULL, O_LASTLEASE_EXTEND}, 166 {"inactive", no_argument, NULL, O_INACTIVE}, 167 {"mudurl", required_argument, NULL, O_MUDURL}, 168 {"link_rcvbuf", required_argument, NULL, O_LINK_RCVBUF}, 169 {"configure", no_argument, NULL, O_CONFIGURE}, 170 {"noconfigure", no_argument, NULL, O_NOCONFIGURE}, 171 {NULL, 0, NULL, '\0'} 172 }; 173 174 static char * 175 add_environ(char ***array, const char *value, int uniq) 176 { 177 char **newlist, **list = *array; 178 size_t i = 0, l, lv; 179 char *match = NULL, *p, *n; 180 181 match = strdup(value); 182 if (match == NULL) { 183 logerr(__func__); 184 return NULL; 185 } 186 p = strchr(match, '='); 187 if (p == NULL) { 188 logerrx("%s: no assignment: %s", __func__, value); 189 free(match); 190 return NULL; 191 } 192 *p++ = '\0'; 193 l = strlen(match); 194 195 while (list && list[i]) { 196 if (match && strncmp(list[i], match, l) == 0) { 197 if (uniq) { 198 n = strdup(value); 199 if (n == NULL) { 200 logerr(__func__); 201 free(match); 202 return NULL; 203 } 204 free(list[i]); 205 list[i] = n; 206 } else { 207 /* Append a space and the value to it */ 208 l = strlen(list[i]); 209 lv = strlen(p); 210 n = realloc(list[i], l + lv + 2); 211 if (n == NULL) { 212 logerr(__func__); 213 free(match); 214 return NULL; 215 } 216 list[i] = n; 217 list[i][l] = ' '; 218 memcpy(list[i] + l + 1, p, lv); 219 list[i][l + lv + 1] = '\0'; 220 } 221 free(match); 222 return list[i]; 223 } 224 i++; 225 } 226 227 free(match); 228 n = strdup(value); 229 if (n == NULL) { 230 logerr(__func__); 231 return NULL; 232 } 233 newlist = reallocarray(list, i + 2, sizeof(char *)); 234 if (newlist == NULL) { 235 logerr(__func__); 236 free(n); 237 return NULL; 238 } 239 newlist[i] = n; 240 newlist[i + 1] = NULL; 241 *array = newlist; 242 return newlist[i]; 243 } 244 245 #define PARSE_STRING 0 246 #define PARSE_STRING_NULL 1 247 #define PARSE_HWADDR 2 248 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING) 249 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL) 250 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR) 251 static ssize_t 252 parse_str(char *sbuf, size_t slen, const char *str, int flags) 253 { 254 size_t l; 255 const char *p, *end; 256 int i; 257 char c[4], cmd; 258 259 end = str + strlen(str); 260 /* If surrounded by quotes then it's a string */ 261 if (*str == '"') { 262 p = end - 1; 263 if (*p == '"') { 264 str++; 265 end = p; 266 } 267 } else { 268 l = (size_t)hwaddr_aton(NULL, str); 269 if ((ssize_t) l != -1 && l > 1) { 270 if (l > slen) { 271 errno = ENOBUFS; 272 return -1; 273 } 274 hwaddr_aton((uint8_t *)sbuf, str); 275 return (ssize_t)l; 276 } 277 } 278 279 /* Process escapes */ 280 l = 0; 281 /* If processing a string on the clientid, first byte should be 282 * 0 to indicate a non hardware type */ 283 if (flags == PARSE_HWADDR && *str) { 284 if (sbuf) 285 *sbuf++ = 0; 286 l++; 287 } 288 c[3] = '\0'; 289 while (str < end) { 290 if (++l > slen && sbuf) { 291 errno = ENOBUFS; 292 return -1; 293 } 294 if (*str == '\\') { 295 str++; 296 switch((cmd = *str++)) { 297 case '\0': 298 str--; 299 break; 300 case 'b': 301 if (sbuf) 302 *sbuf++ = '\b'; 303 break; 304 case 'n': 305 if (sbuf) 306 *sbuf++ = '\n'; 307 break; 308 case 'r': 309 if (sbuf) 310 *sbuf++ = '\r'; 311 break; 312 case 't': 313 if (sbuf) 314 *sbuf++ = '\t'; 315 break; 316 case 'x': 317 /* Grab a hex code */ 318 c[1] = '\0'; 319 for (i = 0; i < 2; i++) { 320 if (isxdigit((unsigned char)*str) == 0) 321 break; 322 c[i] = *str++; 323 } 324 if (c[1] != '\0') { 325 c[2] = '\0'; 326 if (sbuf) 327 *sbuf++ = (char)strtol(c, NULL, 16); 328 } else 329 l--; 330 break; 331 case '0': 332 /* Grab an octal code */ 333 c[2] = '\0'; 334 for (i = 0; i < 3; i++) { 335 if (*str < '0' || *str > '7') 336 break; 337 c[i] = *str++; 338 } 339 if (c[2] != '\0') { 340 i = (int)strtol(c, NULL, 8); 341 if (i > 255) 342 i = 255; 343 if (sbuf) 344 *sbuf++ = (char)i; 345 } else 346 l--; 347 break; 348 default: 349 if (sbuf) 350 *sbuf++ = cmd; 351 break; 352 } 353 } else { 354 if (sbuf) 355 *sbuf++ = *str; 356 str++; 357 } 358 } 359 if (flags == PARSE_STRING_NULL) { 360 l++; 361 if (sbuf != NULL) { 362 if (l > slen) { 363 errno = ENOBUFS; 364 return -1; 365 } 366 *sbuf = '\0'; 367 } 368 } 369 return (ssize_t)l; 370 } 371 372 static int 373 parse_iaid1(uint8_t *iaid, const char *arg, size_t len, int n) 374 { 375 int e; 376 uint32_t narg; 377 ssize_t s; 378 379 narg = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); 380 if (e == 0) { 381 if (n) 382 narg = htonl(narg); 383 memcpy(iaid, &narg, sizeof(narg)); 384 return 0; 385 } 386 387 if ((s = parse_string((char *)iaid, len, arg)) < 1) 388 return -1; 389 if (s < 4) 390 iaid[3] = '\0'; 391 if (s < 3) 392 iaid[2] = '\0'; 393 if (s < 2) 394 iaid[1] = '\0'; 395 return 0; 396 } 397 398 static int 399 parse_iaid(uint8_t *iaid, const char *arg, size_t len) 400 { 401 402 return parse_iaid1(iaid, arg, len, 1); 403 } 404 405 #ifdef AUTH 406 static int 407 parse_uint32(uint32_t *i, const char *arg) 408 { 409 410 return parse_iaid1((uint8_t *)i, arg, sizeof(uint32_t), 0); 411 } 412 #endif 413 414 static char ** 415 splitv(int *argc, char **argv, const char *arg) 416 { 417 char **n, **v = argv; 418 char *o = strdup(arg), *p, *t, *nt; 419 420 if (o == NULL) { 421 logerr(__func__); 422 return v; 423 } 424 p = o; 425 while ((t = strsep(&p, ", "))) { 426 nt = strdup(t); 427 if (nt == NULL) { 428 logerr(__func__); 429 free(o); 430 return v; 431 } 432 n = reallocarray(v, (size_t)(*argc) + 1, sizeof(char *)); 433 if (n == NULL) { 434 logerr(__func__); 435 free(o); 436 free(nt); 437 return v; 438 } 439 v = n; 440 v[(*argc)++] = nt; 441 } 442 free(o); 443 return v; 444 } 445 446 #ifdef INET 447 static int 448 parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg) 449 { 450 char *p; 451 452 if (arg == NULL || *arg == '\0') { 453 if (addr != NULL) 454 addr->s_addr = 0; 455 if (net != NULL) 456 net->s_addr = 0; 457 return 0; 458 } 459 if ((p = strchr(arg, '/')) != NULL) { 460 int e; 461 intmax_t i; 462 463 *p++ = '\0'; 464 i = strtoi(p, NULL, 10, 0, 32, &e); 465 if (e != 0 || 466 (net != NULL && inet_cidrtoaddr((int)i, net) != 0)) 467 { 468 logerrx("invalid CIDR: %s", p); 469 return -1; 470 } 471 } 472 473 if (addr != NULL && inet_aton(arg, addr) == 0) { 474 logerrx("invalid IP address: %s", arg); 475 return -1; 476 } 477 if (p != NULL) 478 *--p = '/'; 479 else if (net != NULL && addr != NULL) 480 net->s_addr = ipv4_getnetmask(addr->s_addr); 481 return 0; 482 } 483 #else 484 static int 485 parse_addr(__unused struct in_addr *addr, __unused struct in_addr *net, 486 __unused const char *arg) 487 { 488 489 logerrx("No IPv4 support"); 490 return -1; 491 } 492 #endif 493 494 static void 495 set_option_space(struct dhcpcd_ctx *ctx, 496 const char *arg, 497 const struct dhcp_opt **d, size_t *dl, 498 const struct dhcp_opt **od, size_t *odl, 499 struct if_options *ifo, 500 uint8_t *request[], uint8_t *require[], uint8_t *no[], uint8_t *reject[]) 501 { 502 503 #if !defined(INET) && !defined(INET6) 504 UNUSED(ctx); 505 #endif 506 507 #ifdef INET6 508 if (strncmp(arg, "nd_", strlen("nd_")) == 0) { 509 *d = ctx->nd_opts; 510 *dl = ctx->nd_opts_len; 511 *od = ifo->nd_override; 512 *odl = ifo->nd_override_len; 513 *request = ifo->requestmasknd; 514 *require = ifo->requiremasknd; 515 *no = ifo->nomasknd; 516 *reject = ifo->rejectmasknd; 517 return; 518 } 519 520 #ifdef DHCP6 521 if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) { 522 *d = ctx->dhcp6_opts; 523 *dl = ctx->dhcp6_opts_len; 524 *od = ifo->dhcp6_override; 525 *odl = ifo->dhcp6_override_len; 526 *request = ifo->requestmask6; 527 *require = ifo->requiremask6; 528 *no = ifo->nomask6; 529 *reject = ifo->rejectmask6; 530 return; 531 } 532 #endif 533 #else 534 UNUSED(arg); 535 #endif 536 537 #ifdef INET 538 *d = ctx->dhcp_opts; 539 *dl = ctx->dhcp_opts_len; 540 *od = ifo->dhcp_override; 541 *odl = ifo->dhcp_override_len; 542 #else 543 *d = NULL; 544 *dl = 0; 545 *od = NULL; 546 *odl = 0; 547 #endif 548 *request = ifo->requestmask; 549 *require = ifo->requiremask; 550 *no = ifo->nomask; 551 *reject = ifo->rejectmask; 552 } 553 554 void 555 free_dhcp_opt_embenc(struct dhcp_opt *opt) 556 { 557 size_t i; 558 struct dhcp_opt *o; 559 560 free(opt->var); 561 562 for (i = 0, o = opt->embopts; i < opt->embopts_len; i++, o++) 563 free_dhcp_opt_embenc(o); 564 free(opt->embopts); 565 opt->embopts_len = 0; 566 opt->embopts = NULL; 567 568 for (i = 0, o = opt->encopts; i < opt->encopts_len; i++, o++) 569 free_dhcp_opt_embenc(o); 570 free(opt->encopts); 571 opt->encopts_len = 0; 572 opt->encopts = NULL; 573 } 574 575 static char * 576 strwhite(const char *s) 577 { 578 579 if (s == NULL) 580 return NULL; 581 while (*s != ' ' && *s != '\t') { 582 if (*s == '\0') 583 return NULL; 584 s++; 585 } 586 return UNCONST(s); 587 } 588 589 static char * 590 strskipwhite(const char *s) 591 { 592 593 if (s == NULL || *s == '\0') 594 return NULL; 595 while (*s == ' ' || *s == '\t') { 596 s++; 597 if (*s == '\0') 598 return NULL; 599 } 600 return UNCONST(s); 601 } 602 603 #ifdef AUTH 604 /* Find the end pointer of a string. */ 605 static char * 606 strend(const char *s) 607 { 608 609 s = strskipwhite(s); 610 if (s == NULL) 611 return NULL; 612 if (*s != '"') 613 return strchr(s, ' '); 614 s++; 615 for (; *s != '"' ; s++) { 616 if (*s == '\0') 617 return NULL; 618 if (*s == '\\') { 619 if (*(++s) == '\0') 620 return NULL; 621 } 622 } 623 return UNCONST(++s); 624 } 625 #endif 626 627 static int 628 parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, 629 int opt, const char *arg, struct dhcp_opt **ldop, struct dhcp_opt **edop) 630 { 631 int e, i, t; 632 long l; 633 unsigned long u; 634 char *p = NULL, *bp, *fp, *np; 635 ssize_t s; 636 struct in_addr addr, addr2; 637 in_addr_t *naddr; 638 struct rt *rt; 639 const struct dhcp_opt *d, *od; 640 uint8_t *request, *require, *no, *reject; 641 struct dhcp_opt **dop, *ndop; 642 size_t *dop_len, dl, odl; 643 struct vivco *vivco; 644 struct group *grp; 645 #ifdef AUTH 646 struct token *token; 647 #endif 648 #ifdef _REENTRANT 649 struct group grpbuf; 650 #endif 651 #ifdef DHCP6 652 size_t sl; 653 struct if_ia *ia; 654 uint8_t iaid[4]; 655 #ifndef SMALL 656 struct if_sla *sla, *slap; 657 #endif 658 #endif 659 660 dop = NULL; 661 dop_len = NULL; 662 #ifdef INET6 663 i = 0; 664 #endif 665 666 /* Add a guard for static analysers. 667 * This should not be needed really because of the argument_required option 668 * in the options declaration above. */ 669 #define ARG_REQUIRED if (arg == NULL) goto arg_required 670 671 switch(opt) { 672 case 'f': /* FALLTHROUGH */ 673 case 'g': /* FALLTHROUGH */ 674 case 'n': /* FALLTHROUGH */ 675 case 'q': /* FALLTHROUGH */ 676 case 'x': /* FALLTHROUGH */ 677 case 'N': /* FALLTHROUGH */ 678 case 'P': /* FALLTHROUGH */ 679 case 'T': /* FALLTHROUGH */ 680 case 'U': /* FALLTHROUGH */ 681 case 'V': /* We need to handle non interface options */ 682 break; 683 case 'b': 684 ifo->options |= DHCPCD_BACKGROUND; 685 break; 686 case 'c': 687 ARG_REQUIRED; 688 if (IN_CONFIG_BLOCK(ifo)) { 689 logerrx("%s: per interface scripts" 690 " are no longer supported", 691 ifname); 692 return -1; 693 } 694 if (ctx->script != dhcpcd_default_script) 695 free(ctx->script); 696 s = parse_nstring(NULL, 0, arg); 697 if (s == 0) { 698 ctx->script = NULL; 699 break; 700 } 701 dl = (size_t)s; 702 if (s == -1 || (ctx->script = malloc(dl)) == NULL) { 703 ctx->script = NULL; 704 logerr(__func__); 705 return -1; 706 } 707 s = parse_nstring(ctx->script, dl, arg); 708 if (s == -1 || 709 ctx->script[0] == '\0' || 710 strcmp(ctx->script, "/dev/null") == 0) 711 { 712 free(ctx->script); 713 ctx->script = NULL; 714 } 715 break; 716 case 'd': 717 ifo->options |= DHCPCD_DEBUG; 718 break; 719 case 'e': 720 ARG_REQUIRED; 721 add_environ(&ifo->environ, arg, 1); 722 break; 723 case 'h': 724 if (!arg) { 725 ifo->options |= DHCPCD_HOSTNAME; 726 break; 727 } 728 s = parse_nstring(ifo->hostname, sizeof(ifo->hostname), arg); 729 if (s == -1) { 730 logerr("%s: hostname", __func__); 731 return -1; 732 } 733 if (s != 0 && ifo->hostname[0] == '.') { 734 logerrx("hostname cannot begin with ."); 735 return -1; 736 } 737 if (ifo->hostname[0] == '\0') 738 ifo->options &= ~DHCPCD_HOSTNAME; 739 else 740 ifo->options |= DHCPCD_HOSTNAME; 741 break; 742 case 'i': 743 if (arg) 744 s = parse_string((char *)ifo->vendorclassid + 1, 745 VENDORCLASSID_MAX_LEN, arg); 746 else 747 s = 0; 748 if (s == -1) { 749 logerr("vendorclassid"); 750 return -1; 751 } 752 *ifo->vendorclassid = (uint8_t)s; 753 break; 754 case 'j': 755 ARG_REQUIRED; 756 /* per interface logging is not supported 757 * don't want to overide the commandline */ 758 if (!IN_CONFIG_BLOCK(ifo) && ctx->logfile == NULL) { 759 logclose(); 760 ctx->logfile = strdup(arg); 761 logopen(ctx->logfile); 762 } 763 break; 764 case 'k': 765 ifo->options |= DHCPCD_RELEASE; 766 break; 767 case 'l': 768 ARG_REQUIRED; 769 if (strcmp(arg, "-1") == 0) { 770 ifo->leasetime = DHCP_INFINITE_LIFETIME; 771 break; 772 } 773 ifo->leasetime = (uint32_t)strtou(arg, NULL, 774 0, 0, UINT32_MAX, &e); 775 if (e) { 776 logerrx("failed to convert leasetime %s", arg); 777 return -1; 778 } 779 break; 780 case 'm': 781 ARG_REQUIRED; 782 ifo->metric = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e); 783 if (e) { 784 logerrx("failed to convert metric %s", arg); 785 return -1; 786 } 787 break; 788 case 'o': 789 ARG_REQUIRED; 790 if (ctx->options & DHCPCD_PRINT_PIDFILE) 791 break; 792 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, 793 &request, &require, &no, &reject); 794 if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 || 795 make_option_mask(d, dl, od, odl, no, arg, -1) != 0 || 796 make_option_mask(d, dl, od, odl, reject, arg, -1) != 0) 797 { 798 logerrx("unknown option: %s", arg); 799 return -1; 800 } 801 break; 802 case O_REJECT: 803 ARG_REQUIRED; 804 if (ctx->options & DHCPCD_PRINT_PIDFILE) 805 break; 806 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, 807 &request, &require, &no, &reject); 808 if (make_option_mask(d, dl, od, odl, reject, arg, 1) != 0 || 809 make_option_mask(d, dl, od, odl, request, arg, -1) != 0 || 810 make_option_mask(d, dl, od, odl, require, arg, -1) != 0) 811 { 812 logerrx("unknown option: %s", arg); 813 return -1; 814 } 815 break; 816 case 'p': 817 ifo->options |= DHCPCD_PERSISTENT; 818 break; 819 case 'r': 820 if (parse_addr(&ifo->req_addr, NULL, arg) != 0) 821 return -1; 822 ifo->options |= DHCPCD_REQUEST; 823 ifo->req_mask.s_addr = 0; 824 break; 825 case 's': 826 if (arg && *arg != '\0') { 827 /* Strip out a broadcast address */ 828 p = strchr(arg, '/'); 829 if (p != NULL) { 830 p = strchr(p + 1, '/'); 831 if (p != NULL) 832 *p = '\0'; 833 } 834 i = parse_addr(&ifo->req_addr, &ifo->req_mask, arg); 835 if (p != NULL) { 836 /* Ensure the original string is preserved */ 837 *p++ = '/'; 838 if (i == 0) 839 i = parse_addr(&ifo->req_brd, NULL, p); 840 } 841 if (i != 0) 842 return -1; 843 } else { 844 ifo->req_addr.s_addr = 0; 845 ifo->req_mask.s_addr = 0; 846 } 847 ifo->options |= DHCPCD_INFORM | DHCPCD_PERSISTENT; 848 ifo->options &= ~DHCPCD_STATIC; 849 break; 850 case O_INFORM6: 851 ifo->options |= DHCPCD_INFORM6; 852 break; 853 case 't': 854 ARG_REQUIRED; 855 ifo->timeout = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); 856 if (e) { 857 logerrx("failed to convert timeout %s", arg); 858 return -1; 859 } 860 break; 861 case 'u': 862 dl = sizeof(ifo->userclass) - ifo->userclass[0] - 1; 863 s = parse_string((char *)ifo->userclass + 864 ifo->userclass[0] + 2, dl, arg); 865 if (s == -1) { 866 logerr("userclass"); 867 return -1; 868 } 869 if (s != 0) { 870 ifo->userclass[ifo->userclass[0] + 1] = (uint8_t)s; 871 ifo->userclass[0] = (uint8_t)(ifo->userclass[0] + s +1); 872 } 873 break; 874 #ifndef SMALL 875 case O_MSUSERCLASS: 876 /* Some Microsoft DHCP servers expect userclass to be an 877 * opaque blob. This is not RFC 3004 compliant. */ 878 s = parse_string((char *)ifo->userclass + 1, 879 sizeof(ifo->userclass) - 1, arg); 880 if (s == -1) { 881 logerr("msuserclass"); 882 return -1; 883 } 884 ifo->userclass[0] = (uint8_t)s; 885 break; 886 #endif 887 case 'v': 888 ARG_REQUIRED; 889 p = strchr(arg, ','); 890 if (!p || !p[1]) { 891 logerrx("invalid vendor format: %s", arg); 892 return -1; 893 } 894 895 /* If vendor starts with , then it is not encapsulated */ 896 if (p == arg) { 897 arg++; 898 s = parse_string((char *)ifo->vendor + 1, 899 VENDOR_MAX_LEN, arg); 900 if (s == -1) { 901 logerr("vendor"); 902 return -1; 903 } 904 ifo->vendor[0] = (uint8_t)s; 905 ifo->options |= DHCPCD_VENDORRAW; 906 break; 907 } 908 909 /* Encapsulated vendor options */ 910 if (ifo->options & DHCPCD_VENDORRAW) { 911 ifo->options &= ~DHCPCD_VENDORRAW; 912 ifo->vendor[0] = 0; 913 } 914 915 /* Strip and preserve the comma */ 916 *p = '\0'; 917 i = (int)strtoi(arg, NULL, 0, 1, 254, &e); 918 *p = ','; 919 if (e) { 920 logerrx("vendor option should be between" 921 " 1 and 254 inclusive"); 922 return -1; 923 } 924 925 arg = p + 1; 926 s = VENDOR_MAX_LEN - ifo->vendor[0] - 2; 927 if (inet_aton(arg, &addr) == 1) { 928 if (s < 6) { 929 s = -1; 930 errno = ENOBUFS; 931 } else { 932 memcpy(ifo->vendor + ifo->vendor[0] + 3, 933 &addr.s_addr, sizeof(addr.s_addr)); 934 s = sizeof(addr.s_addr); 935 } 936 } else { 937 s = parse_string((char *)ifo->vendor + 938 ifo->vendor[0] + 3, (size_t)s, arg); 939 } 940 if (s == -1) { 941 logerr("vendor"); 942 return -1; 943 } 944 if (s != 0) { 945 ifo->vendor[ifo->vendor[0] + 1] = (uint8_t)i; 946 ifo->vendor[ifo->vendor[0] + 2] = (uint8_t)s; 947 ifo->vendor[0] = (uint8_t)(ifo->vendor[0] + s + 2); 948 } 949 break; 950 case 'w': 951 ifo->options |= DHCPCD_WAITIP; 952 if (arg != NULL && arg[0] != '\0') { 953 if (arg[0] == '4' || arg[1] == '4') 954 ifo->options |= DHCPCD_WAITIP4; 955 if (arg[0] == '6' || arg[1] == '6') 956 ifo->options |= DHCPCD_WAITIP6; 957 } 958 break; 959 case 'y': 960 ARG_REQUIRED; 961 ifo->reboot = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); 962 if (e) { 963 logerr("failed to convert reboot %s", arg); 964 return -1; 965 } 966 break; 967 case 'z': 968 ARG_REQUIRED; 969 if (!IN_CONFIG_BLOCK(ifo)) 970 ctx->ifav = splitv(&ctx->ifac, ctx->ifav, arg); 971 break; 972 case 'A': 973 ifo->options &= ~DHCPCD_ARP; 974 /* IPv4LL requires ARP */ 975 ifo->options &= ~DHCPCD_IPV4LL; 976 break; 977 case 'B': 978 ifo->options &= ~DHCPCD_DAEMONISE; 979 break; 980 case 'C': 981 ARG_REQUIRED; 982 /* Commas to spaces for shell */ 983 while ((p = strchr(arg, ','))) 984 *p = ' '; 985 dl = strlen("skip_hooks=") + strlen(arg) + 1; 986 p = malloc(sizeof(char) * dl); 987 if (p == NULL) { 988 logerr(__func__); 989 return -1; 990 } 991 snprintf(p, dl, "skip_hooks=%s", arg); 992 add_environ(&ifo->environ, p, 0); 993 free(p); 994 break; 995 case 'D': 996 ifo->options |= DHCPCD_CLIENTID | DHCPCD_DUID; 997 if (ifname != NULL) /* duid type only a global option */ 998 break; 999 if (arg == NULL) 1000 ctx->duid_type = DUID_DEFAULT; 1001 else if (strcmp(arg, "ll") == 0) 1002 ctx->duid_type = DUID_LL; 1003 else if (strcmp(arg, "llt") == 0) 1004 ctx->duid_type = DUID_LLT; 1005 else if (strcmp(arg, "uuid") == 0) 1006 ctx->duid_type = DUID_UUID; 1007 else { 1008 dl = hwaddr_aton(NULL, arg); 1009 if (dl != 0) { 1010 no = realloc(ctx->duid, dl); 1011 if (no == NULL) 1012 logerrx(__func__); 1013 else { 1014 ctx->duid = no; 1015 ctx->duid_len = hwaddr_aton(no, arg); 1016 } 1017 } 1018 } 1019 break; 1020 case 'E': 1021 ifo->options |= DHCPCD_LASTLEASE; 1022 break; 1023 case 'F': 1024 if (!arg) { 1025 ifo->fqdn = FQDN_BOTH; 1026 break; 1027 } 1028 if (strcmp(arg, "none") == 0) 1029 ifo->fqdn = FQDN_NONE; 1030 else if (strcmp(arg, "ptr") == 0) 1031 ifo->fqdn = FQDN_PTR; 1032 else if (strcmp(arg, "both") == 0) 1033 ifo->fqdn = FQDN_BOTH; 1034 else if (strcmp(arg, "disable") == 0) 1035 ifo->fqdn = FQDN_DISABLE; 1036 else { 1037 logerrx("invalid FQDN value: %s", arg); 1038 return -1; 1039 } 1040 break; 1041 case 'G': 1042 ifo->options &= ~DHCPCD_GATEWAY; 1043 break; 1044 case 'H': 1045 ifo->options |= DHCPCD_XID_HWADDR; 1046 break; 1047 case 'I': 1048 /* Strings have a type of 0 */; 1049 ifo->clientid[1] = 0; 1050 if (arg) 1051 s = parse_hwaddr((char *)ifo->clientid + 1, 1052 CLIENTID_MAX_LEN, arg); 1053 else 1054 s = 0; 1055 if (s == -1) { 1056 logerr("clientid"); 1057 return -1; 1058 } 1059 ifo->options |= DHCPCD_CLIENTID; 1060 ifo->clientid[0] = (uint8_t)s; 1061 ifo->options &= ~DHCPCD_DUID; 1062 break; 1063 case 'J': 1064 ifo->options |= DHCPCD_BROADCAST; 1065 break; 1066 case 'K': 1067 ifo->options &= ~DHCPCD_LINK; 1068 break; 1069 case 'L': 1070 ifo->options &= ~DHCPCD_IPV4LL; 1071 break; 1072 case 'M': 1073 ifo->options |= DHCPCD_MANAGER; 1074 break; 1075 case 'O': 1076 ARG_REQUIRED; 1077 if (ctx->options & DHCPCD_PRINT_PIDFILE) 1078 break; 1079 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, 1080 &request, &require, &no, &reject); 1081 if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 || 1082 make_option_mask(d, dl, od, odl, require, arg, -1) != 0 || 1083 make_option_mask(d, dl, od, odl, no, arg, 1) != 0) 1084 { 1085 logerrx("unknown option: %s", arg); 1086 return -1; 1087 } 1088 break; 1089 case 'Q': 1090 ARG_REQUIRED; 1091 if (ctx->options & DHCPCD_PRINT_PIDFILE) 1092 break; 1093 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, 1094 &request, &require, &no, &reject); 1095 if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 || 1096 make_option_mask(d, dl, od, odl, request, arg, 1) != 0 || 1097 make_option_mask(d, dl, od, odl, no, arg, -1) != 0 || 1098 make_option_mask(d, dl, od, odl, reject, arg, -1) != 0) 1099 { 1100 logerrx("unknown option: %s", arg); 1101 return -1; 1102 } 1103 break; 1104 case 'S': 1105 ARG_REQUIRED; 1106 p = strchr(arg, '='); 1107 if (p == NULL) { 1108 logerrx("static assignment required"); 1109 return -1; 1110 } 1111 p++; 1112 if (strncmp(arg, "ip_address=", strlen("ip_address=")) == 0) { 1113 if (parse_addr(&ifo->req_addr, 1114 ifo->req_mask.s_addr == 0 ? &ifo->req_mask : NULL, 1115 p) != 0) 1116 return -1; 1117 1118 ifo->options |= DHCPCD_STATIC; 1119 ifo->options &= ~DHCPCD_INFORM; 1120 } else if (strncmp(arg, "subnet_mask=", 1121 strlen("subnet_mask=")) == 0) 1122 { 1123 if (parse_addr(&ifo->req_mask, NULL, p) != 0) 1124 return -1; 1125 } else if (strncmp(arg, "broadcast_address=", 1126 strlen("broadcast_address=")) == 0) 1127 { 1128 if (parse_addr(&ifo->req_brd, NULL, p) != 0) 1129 return -1; 1130 } else if (strncmp(arg, "routes=", strlen("routes=")) == 0 || 1131 strncmp(arg, "static_routes=", 1132 strlen("static_routes=")) == 0 || 1133 strncmp(arg, "classless_static_routes=", 1134 strlen("classless_static_routes=")) == 0 || 1135 strncmp(arg, "ms_classless_static_routes=", 1136 strlen("ms_classless_static_routes=")) == 0) 1137 { 1138 struct in_addr addr3; 1139 1140 fp = np = strwhite(p); 1141 if (np == NULL) { 1142 logerrx("all routes need a gateway"); 1143 return -1; 1144 } 1145 *np++ = '\0'; 1146 np = strskipwhite(np); 1147 if (parse_addr(&addr, &addr2, p) == -1 || 1148 parse_addr(&addr3, NULL, np) == -1) 1149 { 1150 *fp = ' '; 1151 return -1; 1152 } 1153 *fp = ' '; 1154 if ((rt = rt_new0(ctx)) == NULL) 1155 return -1; 1156 sa_in_init(&rt->rt_dest, &addr); 1157 sa_in_init(&rt->rt_netmask, &addr2); 1158 sa_in_init(&rt->rt_gateway, &addr3); 1159 if (rt_proto_add_ctx(&ifo->routes, rt, ctx)) 1160 add_environ(&ifo->config, arg, 0); 1161 } else if (strncmp(arg, "routers=", strlen("routers=")) == 0) { 1162 if (parse_addr(&addr, NULL, p) == -1) 1163 return -1; 1164 if ((rt = rt_new0(ctx)) == NULL) 1165 return -1; 1166 addr2.s_addr = INADDR_ANY; 1167 sa_in_init(&rt->rt_dest, &addr2); 1168 sa_in_init(&rt->rt_netmask, &addr2); 1169 sa_in_init(&rt->rt_gateway, &addr); 1170 if (rt_proto_add_ctx(&ifo->routes, rt, ctx)) 1171 add_environ(&ifo->config, arg, 0); 1172 } else if (strncmp(arg, "interface_mtu=", 1173 strlen("interface_mtu=")) == 0 || 1174 strncmp(arg, "mtu=", strlen("mtu=")) == 0) 1175 { 1176 ifo->mtu = (unsigned int)strtou(p, NULL, 0, 1177 MTU_MIN, MTU_MAX, &e); 1178 if (e) { 1179 logerrx("invalid MTU %s", p); 1180 return -1; 1181 } 1182 } else if (strncmp(arg, "ip6_address=", strlen("ip6_address=")) == 0) { 1183 np = strchr(p, '/'); 1184 if (np) 1185 *np++ = '\0'; 1186 if ((i = inet_pton(AF_INET6, p, &ifo->req_addr6)) == 1) { 1187 if (np) { 1188 ifo->req_prefix_len = (uint8_t)strtou(np, 1189 NULL, 0, 0, 128, &e); 1190 if (e) { 1191 logerrx("%s: failed to " 1192 "convert prefix len", 1193 ifname); 1194 return -1; 1195 } 1196 } else 1197 ifo->req_prefix_len = 128; 1198 } 1199 if (np) 1200 *(--np) = '\0'; 1201 if (i != 1) { 1202 logerrx("invalid AF_INET6: %s", p); 1203 memset(&ifo->req_addr6, 0, 1204 sizeof(ifo->req_addr6)); 1205 return -1; 1206 } 1207 } else 1208 add_environ(&ifo->config, arg, 1); 1209 break; 1210 case 'W': 1211 if (parse_addr(&addr, &addr2, arg) != 0) 1212 return -1; 1213 if (strchr(arg, '/') == NULL) 1214 addr2.s_addr = INADDR_BROADCAST; 1215 naddr = reallocarray(ifo->whitelist, 1216 ifo->whitelist_len + 2, sizeof(in_addr_t)); 1217 if (naddr == NULL) { 1218 logerr(__func__); 1219 return -1; 1220 } 1221 ifo->whitelist = naddr; 1222 ifo->whitelist[ifo->whitelist_len++] = addr.s_addr; 1223 ifo->whitelist[ifo->whitelist_len++] = addr2.s_addr; 1224 break; 1225 case 'X': 1226 if (parse_addr(&addr, &addr2, arg) != 0) 1227 return -1; 1228 if (strchr(arg, '/') == NULL) 1229 addr2.s_addr = INADDR_BROADCAST; 1230 naddr = reallocarray(ifo->blacklist, 1231 ifo->blacklist_len + 2, sizeof(in_addr_t)); 1232 if (naddr == NULL) { 1233 logerr(__func__); 1234 return -1; 1235 } 1236 ifo->blacklist = naddr; 1237 ifo->blacklist[ifo->blacklist_len++] = addr.s_addr; 1238 ifo->blacklist[ifo->blacklist_len++] = addr2.s_addr; 1239 break; 1240 case 'Z': 1241 ARG_REQUIRED; 1242 if (!IN_CONFIG_BLOCK(ifo)) 1243 ctx->ifdv = splitv(&ctx->ifdc, ctx->ifdv, arg); 1244 break; 1245 case '1': 1246 ifo->options |= DHCPCD_ONESHOT; 1247 break; 1248 case '4': 1249 #ifdef INET 1250 ifo->options &= ~DHCPCD_IPV6; 1251 ifo->options |= DHCPCD_IPV4; 1252 break; 1253 #else 1254 logerrx("INET has been compiled out"); 1255 return -1; 1256 #endif 1257 case '6': 1258 #ifdef INET6 1259 ifo->options &= ~DHCPCD_IPV4; 1260 ifo->options |= DHCPCD_IPV6; 1261 break; 1262 #else 1263 logerrx("INET6 has been compiled out"); 1264 return -1; 1265 #endif 1266 case O_IPV4: 1267 ifo->options |= DHCPCD_IPV4; 1268 break; 1269 case O_NOIPV4: 1270 ifo->options &= ~DHCPCD_IPV4; 1271 break; 1272 case O_IPV6: 1273 ifo->options |= DHCPCD_IPV6; 1274 break; 1275 case O_NOIPV6: 1276 ifo->options &= ~DHCPCD_IPV6; 1277 break; 1278 case O_ANONYMOUS: 1279 ifo->options |= DHCPCD_ANONYMOUS; 1280 ifo->options &= ~DHCPCD_HOSTNAME; 1281 ifo->fqdn = FQDN_DISABLE; 1282 1283 /* Block everything */ 1284 memset(ifo->nomask, 0xff, sizeof(ifo->nomask)); 1285 memset(ifo->nomask6, 0xff, sizeof(ifo->nomask6)); 1286 1287 /* Allow the bare minimum through */ 1288 #ifdef INET 1289 del_option_mask(ifo->nomask, DHO_SUBNETMASK); 1290 del_option_mask(ifo->nomask, DHO_CSR); 1291 del_option_mask(ifo->nomask, DHO_ROUTER); 1292 del_option_mask(ifo->nomask, DHO_DNSSERVER); 1293 del_option_mask(ifo->nomask, DHO_DNSDOMAIN); 1294 del_option_mask(ifo->nomask, DHO_BROADCAST); 1295 del_option_mask(ifo->nomask, DHO_STATICROUTE); 1296 del_option_mask(ifo->nomask, DHO_SERVERID); 1297 del_option_mask(ifo->nomask, DHO_RENEWALTIME); 1298 del_option_mask(ifo->nomask, DHO_REBINDTIME); 1299 del_option_mask(ifo->nomask, DHO_DNSSEARCH); 1300 #endif 1301 1302 #ifdef DHCP6 1303 del_option_mask(ifo->nomask6, D6_OPTION_DNS_SERVERS); 1304 del_option_mask(ifo->nomask6, D6_OPTION_DOMAIN_LIST); 1305 del_option_mask(ifo->nomask6, D6_OPTION_SOL_MAX_RT); 1306 del_option_mask(ifo->nomask6, D6_OPTION_INF_MAX_RT); 1307 #endif 1308 1309 break; 1310 case O_RANDOMISE_HWADDR: 1311 ifo->randomise_hwaddr = true; 1312 break; 1313 #ifdef INET 1314 case O_ARPING: 1315 while (arg != NULL) { 1316 fp = strwhite(arg); 1317 if (fp) 1318 *fp++ = '\0'; 1319 if (parse_addr(&addr, NULL, arg) != 0) 1320 return -1; 1321 naddr = reallocarray(ifo->arping, 1322 (size_t)ifo->arping_len + 1, sizeof(in_addr_t)); 1323 if (naddr == NULL) { 1324 logerr(__func__); 1325 return -1; 1326 } 1327 ifo->arping = naddr; 1328 ifo->arping[ifo->arping_len++] = addr.s_addr; 1329 arg = strskipwhite(fp); 1330 } 1331 break; 1332 case O_DESTINATION: 1333 ARG_REQUIRED; 1334 if (ctx->options & DHCPCD_PRINT_PIDFILE) 1335 break; 1336 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, 1337 &request, &require, &no, &reject); 1338 if (make_option_mask(d, dl, od, odl, 1339 ifo->dstmask, arg, 2) != 0) 1340 { 1341 if (errno == EINVAL) 1342 logerrx("option does not take" 1343 " an IPv4 address: %s", arg); 1344 else 1345 logerrx("unknown option: %s", arg); 1346 return -1; 1347 } 1348 break; 1349 case O_FALLBACK: 1350 ARG_REQUIRED; 1351 free(ifo->fallback); 1352 ifo->fallback = strdup(arg); 1353 if (ifo->fallback == NULL) { 1354 logerrx(__func__); 1355 return -1; 1356 } 1357 break; 1358 #endif 1359 case O_IAID: 1360 ARG_REQUIRED; 1361 if (ctx->options & DHCPCD_MANAGER && !IN_CONFIG_BLOCK(ifo)) { 1362 logerrx("IAID must belong in an interface block"); 1363 return -1; 1364 } 1365 if (parse_iaid(ifo->iaid, arg, sizeof(ifo->iaid)) == -1) { 1366 logerrx("invalid IAID %s", arg); 1367 return -1; 1368 } 1369 ifo->options |= DHCPCD_IAID; 1370 break; 1371 case O_IPV6RS: 1372 ifo->options |= DHCPCD_IPV6RS; 1373 break; 1374 case O_NOIPV6RS: 1375 ifo->options &= ~DHCPCD_IPV6RS; 1376 break; 1377 case O_IPV6RA_FORK: 1378 ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS; 1379 break; 1380 case O_IPV6RA_AUTOCONF: 1381 ifo->options |= DHCPCD_IPV6RA_AUTOCONF; 1382 break; 1383 case O_IPV6RA_NOAUTOCONF: 1384 ifo->options &= ~DHCPCD_IPV6RA_AUTOCONF; 1385 break; 1386 case O_NOALIAS: 1387 ifo->options |= DHCPCD_NOALIAS; 1388 break; 1389 #ifdef DHCP6 1390 case O_IA_NA: 1391 i = D6_OPTION_IA_NA; 1392 /* FALLTHROUGH */ 1393 case O_IA_TA: 1394 if (i == 0) 1395 i = D6_OPTION_IA_TA; 1396 /* FALLTHROUGH */ 1397 case O_IA_PD: 1398 if (i == 0) { 1399 #ifdef SMALL 1400 logwarnx("%s: IA_PD not compiled in", ifname); 1401 return -1; 1402 #else 1403 if (ctx->options & DHCPCD_MANAGER && 1404 !IN_CONFIG_BLOCK(ifo)) 1405 { 1406 logerrx("IA PD must belong in an " 1407 "interface block"); 1408 return -1; 1409 } 1410 i = D6_OPTION_IA_PD; 1411 #endif 1412 } 1413 if (ctx->options & DHCPCD_MANAGER && 1414 !IN_CONFIG_BLOCK(ifo) && arg) 1415 { 1416 logerrx("IA with IAID must belong in an " 1417 "interface block"); 1418 return -1; 1419 } 1420 ifo->options |= DHCPCD_IA_FORCED; 1421 fp = strwhite(arg); 1422 if (fp) { 1423 *fp++ = '\0'; 1424 fp = strskipwhite(fp); 1425 } 1426 if (arg) { 1427 p = strchr(arg, '/'); 1428 if (p) 1429 *p++ = '\0'; 1430 if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) { 1431 logerr("invalid IAID: %s", arg); 1432 return -1; 1433 } 1434 } 1435 ia = NULL; 1436 for (sl = 0; sl < ifo->ia_len; sl++) { 1437 if ((arg == NULL && !ifo->ia[sl].iaid_set) || 1438 (arg != NULL && ifo->ia[sl].iaid_set && 1439 ifo->ia[sl].ia_type == (uint16_t)i && 1440 ifo->ia[sl].iaid[0] == iaid[0] && 1441 ifo->ia[sl].iaid[1] == iaid[1] && 1442 ifo->ia[sl].iaid[2] == iaid[2] && 1443 ifo->ia[sl].iaid[3] == iaid[3])) 1444 { 1445 ia = &ifo->ia[sl]; 1446 break; 1447 } 1448 } 1449 if (ia == NULL) { 1450 ia = reallocarray(ifo->ia, 1451 ifo->ia_len + 1, sizeof(*ifo->ia)); 1452 if (ia == NULL) { 1453 logerr(__func__); 1454 return -1; 1455 } 1456 ifo->ia = ia; 1457 ia = &ifo->ia[ifo->ia_len++]; 1458 ia->ia_type = (uint16_t)i; 1459 if (arg) { 1460 ia->iaid[0] = iaid[0]; 1461 ia->iaid[1] = iaid[1]; 1462 ia->iaid[2] = iaid[2]; 1463 ia->iaid[3] = iaid[3]; 1464 ia->iaid_set = 1; 1465 } else 1466 ia->iaid_set = 0; 1467 if (!ia->iaid_set || 1468 p == NULL || 1469 ia->ia_type == D6_OPTION_IA_TA) 1470 { 1471 memset(&ia->addr, 0, sizeof(ia->addr)); 1472 ia->prefix_len = 0; 1473 } else { 1474 arg = p; 1475 p = strchr(arg, '/'); 1476 if (p) 1477 *p++ = '\0'; 1478 if (inet_pton(AF_INET6, arg, &ia->addr) != 1) { 1479 logerrx("invalid AF_INET6: %s", arg); 1480 memset(&ia->addr, 0, sizeof(ia->addr)); 1481 } 1482 if (p && ia->ia_type == D6_OPTION_IA_PD) { 1483 ia->prefix_len = (uint8_t)strtou(p, 1484 NULL, 0, 8, 120, &e); 1485 if (e) { 1486 logerrx("%s: failed to convert" 1487 " prefix len", 1488 p); 1489 ia->prefix_len = 0; 1490 } 1491 } 1492 } 1493 #ifndef SMALL 1494 ia->sla_max = 0; 1495 ia->sla_len = 0; 1496 ia->sla = NULL; 1497 #endif 1498 } 1499 1500 #ifdef SMALL 1501 break; 1502 #else 1503 if (ia->ia_type != D6_OPTION_IA_PD) 1504 break; 1505 1506 for (p = fp; p; p = fp) { 1507 fp = strwhite(p); 1508 if (fp) { 1509 *fp++ = '\0'; 1510 fp = strskipwhite(fp); 1511 } 1512 sla = reallocarray(ia->sla, 1513 ia->sla_len + 1, sizeof(*ia->sla)); 1514 if (sla == NULL) { 1515 logerr(__func__); 1516 return -1; 1517 } 1518 ia->sla = sla; 1519 sla = &ia->sla[ia->sla_len++]; 1520 np = strchr(p, '/'); 1521 if (np) 1522 *np++ = '\0'; 1523 if (strlcpy(sla->ifname, p, 1524 sizeof(sla->ifname)) >= sizeof(sla->ifname)) 1525 { 1526 logerrx("%s: interface name too long", arg); 1527 goto err_sla; 1528 } 1529 sla->sla_set = false; 1530 sla->prefix_len = 0; 1531 sla->suffix = 1; 1532 p = np; 1533 if (p) { 1534 np = strchr(p, '/'); 1535 if (np) 1536 *np++ = '\0'; 1537 if (*p != '\0') { 1538 sla->sla = (uint32_t)strtou(p, NULL, 1539 0, 0, UINT32_MAX, &e); 1540 sla->sla_set = true; 1541 if (e) { 1542 logerrx("%s: failed to convert " 1543 "sla", 1544 ifname); 1545 goto err_sla; 1546 } 1547 } 1548 p = np; 1549 } 1550 if (p) { 1551 np = strchr(p, '/'); 1552 if (np) 1553 *np++ = '\0'; 1554 if (*p != '\0') { 1555 sla->prefix_len = (uint8_t)strtou(p, 1556 NULL, 0, 0, 120, &e); 1557 if (e) { 1558 logerrx("%s: failed to " 1559 "convert prefix len", 1560 ifname); 1561 goto err_sla; 1562 } 1563 } 1564 p = np; 1565 } 1566 if (p) { 1567 np = strchr(p, '/'); 1568 if (np) 1569 *np = '\0'; 1570 if (*p != '\0') { 1571 sla->suffix = (uint64_t)strtou(p, NULL, 1572 0, 0, UINT64_MAX, &e); 1573 if (e) { 1574 logerrx("%s: failed to " 1575 "convert suffix", 1576 ifname); 1577 goto err_sla; 1578 } 1579 } 1580 } 1581 /* Sanity check */ 1582 for (sl = 0; sl < ia->sla_len - 1; sl++) { 1583 slap = &ia->sla[sl]; 1584 if (slap->sla_set != sla->sla_set) { 1585 logerrx("%s: cannot mix automatic " 1586 "and fixed SLA", 1587 sla->ifname); 1588 goto err_sla; 1589 } 1590 if (ia->prefix_len && 1591 (sla->prefix_len == ia->prefix_len || 1592 slap->prefix_len == ia->prefix_len)) 1593 { 1594 logerrx("%s: cannot delegte the same" 1595 "prefix length more than once", 1596 sla->ifname); 1597 goto err_sla; 1598 } 1599 if (!sla->sla_set && 1600 strcmp(slap->ifname, sla->ifname) == 0) 1601 { 1602 logwarnx("%s: cannot specify the " 1603 "same interface twice with " 1604 "an automatic SLA", 1605 sla->ifname); 1606 goto err_sla; 1607 } 1608 if (slap->sla_set && sla->sla_set && 1609 slap->sla == sla->sla) 1610 { 1611 logerrx("%s: cannot" 1612 " assign the same SLA %u" 1613 " more than once", 1614 sla->ifname, sla->sla); 1615 goto err_sla; 1616 } 1617 } 1618 if (sla->sla_set && sla->sla > ia->sla_max) 1619 ia->sla_max = sla->sla; 1620 } 1621 break; 1622 err_sla: 1623 ia->sla_len--; 1624 return -1; 1625 #endif 1626 #endif 1627 case O_HOSTNAME_SHORT: 1628 ifo->options |= DHCPCD_HOSTNAME | DHCPCD_HOSTNAME_SHORT; 1629 break; 1630 case O_DEV: 1631 ARG_REQUIRED; 1632 #ifdef PLUGIN_DEV 1633 if (ctx->dev_load) 1634 free(ctx->dev_load); 1635 ctx->dev_load = strdup(arg); 1636 #endif 1637 break; 1638 case O_NODEV: 1639 ifo->options &= ~DHCPCD_DEV; 1640 break; 1641 case O_DEFINE: 1642 dop = &ifo->dhcp_override; 1643 dop_len = &ifo->dhcp_override_len; 1644 /* FALLTHROUGH */ 1645 case O_DEFINEND: 1646 if (dop == NULL) { 1647 dop = &ifo->nd_override; 1648 dop_len = &ifo->nd_override_len; 1649 } 1650 /* FALLTHROUGH */ 1651 case O_DEFINE6: 1652 if (dop == NULL) { 1653 dop = &ifo->dhcp6_override; 1654 dop_len = &ifo->dhcp6_override_len; 1655 } 1656 /* FALLTHROUGH */ 1657 case O_VENDOPT: 1658 if (dop == NULL) { 1659 dop = &ifo->vivso_override; 1660 dop_len = &ifo->vivso_override_len; 1661 } 1662 *edop = *ldop = NULL; 1663 /* FALLTHROUGH */ 1664 case O_EMBED: 1665 if (dop == NULL) { 1666 if (*edop) { 1667 dop = &(*edop)->embopts; 1668 dop_len = &(*edop)->embopts_len; 1669 } else if (ldop) { 1670 dop = &(*ldop)->embopts; 1671 dop_len = &(*ldop)->embopts_len; 1672 } else { 1673 logerrx("embed must be after a define " 1674 "or encap"); 1675 return -1; 1676 } 1677 } 1678 /* FALLTHROUGH */ 1679 case O_ENCAP: 1680 ARG_REQUIRED; 1681 if (dop == NULL) { 1682 if (*ldop == NULL) { 1683 logerrx("encap must be after a define"); 1684 return -1; 1685 } 1686 dop = &(*ldop)->encopts; 1687 dop_len = &(*ldop)->encopts_len; 1688 } 1689 1690 /* Shared code for define, define6, embed and encap */ 1691 1692 /* code */ 1693 if (opt == O_EMBED) /* Embedded options don't have codes */ 1694 u = 0; 1695 else { 1696 fp = strwhite(arg); 1697 if (fp == NULL) { 1698 logerrx("invalid syntax: %s", arg); 1699 return -1; 1700 } 1701 *fp++ = '\0'; 1702 u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); 1703 if (e) { 1704 logerrx("invalid code: %s", arg); 1705 return -1; 1706 } 1707 arg = strskipwhite(fp); 1708 if (arg == NULL) { 1709 logerrx("invalid syntax"); 1710 return -1; 1711 } 1712 } 1713 /* type */ 1714 fp = strwhite(arg); 1715 if (fp) 1716 *fp++ = '\0'; 1717 np = strchr(arg, ':'); 1718 /* length */ 1719 if (np) { 1720 *np++ = '\0'; 1721 bp = NULL; /* No bitflag */ 1722 l = (long)strtou(np, NULL, 0, 0, LONG_MAX, &e); 1723 if (e) { 1724 logerrx("failed to convert length"); 1725 return -1; 1726 } 1727 } else { 1728 l = 0; 1729 bp = strchr(arg, '='); /* bitflag assignment */ 1730 if (bp) 1731 *bp++ = '\0'; 1732 } 1733 t = 0; 1734 if (strcasecmp(arg, "request") == 0) { 1735 t |= OT_REQUEST; 1736 arg = strskipwhite(fp); 1737 fp = strwhite(arg); 1738 if (fp == NULL) { 1739 logerrx("incomplete request type"); 1740 return -1; 1741 } 1742 *fp++ = '\0'; 1743 } else if (strcasecmp(arg, "norequest") == 0) { 1744 t |= OT_NOREQ; 1745 arg = strskipwhite(fp); 1746 fp = strwhite(arg); 1747 if (fp == NULL) { 1748 logerrx("incomplete request type"); 1749 return -1; 1750 } 1751 *fp++ = '\0'; 1752 } 1753 if (strcasecmp(arg, "optional") == 0) { 1754 t |= OT_OPTIONAL; 1755 arg = strskipwhite(fp); 1756 fp = strwhite(arg); 1757 if (fp == NULL) { 1758 logerrx("incomplete optional type"); 1759 return -1; 1760 } 1761 *fp++ = '\0'; 1762 } 1763 if (strcasecmp(arg, "index") == 0) { 1764 t |= OT_INDEX; 1765 arg = strskipwhite(fp); 1766 fp = strwhite(arg); 1767 if (fp == NULL) { 1768 logerrx("incomplete index type"); 1769 return -1; 1770 } 1771 *fp++ = '\0'; 1772 } 1773 if (strcasecmp(arg, "array") == 0) { 1774 t |= OT_ARRAY; 1775 arg = strskipwhite(fp); 1776 fp = strwhite(arg); 1777 if (fp == NULL) { 1778 logerrx("incomplete array type"); 1779 return -1; 1780 } 1781 *fp++ = '\0'; 1782 } 1783 if (strcasecmp(arg, "ipaddress") == 0) 1784 t |= OT_ADDRIPV4; 1785 else if (strcasecmp(arg, "ip6address") == 0) 1786 t |= OT_ADDRIPV6; 1787 else if (strcasecmp(arg, "string") == 0) 1788 t |= OT_STRING; 1789 else if (strcasecmp(arg, "byte") == 0) 1790 t |= OT_UINT8; 1791 else if (strcasecmp(arg, "bitflags") == 0) 1792 t |= OT_BITFLAG; 1793 else if (strcasecmp(arg, "uint8") == 0) 1794 t |= OT_UINT8; 1795 else if (strcasecmp(arg, "int8") == 0) 1796 t |= OT_INT8; 1797 else if (strcasecmp(arg, "uint16") == 0) 1798 t |= OT_UINT16; 1799 else if (strcasecmp(arg, "int16") == 0) 1800 t |= OT_INT16; 1801 else if (strcasecmp(arg, "uint32") == 0) 1802 t |= OT_UINT32; 1803 else if (strcasecmp(arg, "int32") == 0) 1804 t |= OT_INT32; 1805 else if (strcasecmp(arg, "flag") == 0) 1806 t |= OT_FLAG; 1807 else if (strcasecmp(arg, "raw") == 0) 1808 t |= OT_STRING | OT_RAW; 1809 else if (strcasecmp(arg, "ascii") == 0) 1810 t |= OT_STRING | OT_ASCII; 1811 else if (strcasecmp(arg, "domain") == 0) 1812 t |= OT_STRING | OT_DOMAIN | OT_RFC1035; 1813 else if (strcasecmp(arg, "dname") == 0) 1814 t |= OT_STRING | OT_DOMAIN; 1815 else if (strcasecmp(arg, "binhex") == 0) 1816 t |= OT_STRING | OT_BINHEX; 1817 else if (strcasecmp(arg, "embed") == 0) 1818 t |= OT_EMBED; 1819 else if (strcasecmp(arg, "encap") == 0) 1820 t |= OT_ENCAP; 1821 else if (strcasecmp(arg, "rfc3361") ==0) 1822 t |= OT_STRING | OT_RFC3361; 1823 else if (strcasecmp(arg, "rfc3442") ==0) 1824 t |= OT_STRING | OT_RFC3442; 1825 else if (strcasecmp(arg, "option") == 0) 1826 t |= OT_OPTION; 1827 else { 1828 logerrx("unknown type: %s", arg); 1829 return -1; 1830 } 1831 if (l && !(t & (OT_STRING | OT_BINHEX))) { 1832 logwarnx("ignoring length for type: %s", arg); 1833 l = 0; 1834 } 1835 if (t & OT_ARRAY && t & (OT_STRING | OT_BINHEX) && 1836 !(t & (OT_RFC1035 | OT_DOMAIN))) 1837 { 1838 logwarnx("ignoring array for strings"); 1839 t &= ~OT_ARRAY; 1840 } 1841 if (t & OT_BITFLAG) { 1842 if (bp == NULL) 1843 logwarnx("missing bitflag assignment"); 1844 } 1845 /* variable */ 1846 if (!fp) { 1847 if (!(t & OT_OPTION)) { 1848 logerrx("type %s requires a variable name", 1849 arg); 1850 return -1; 1851 } 1852 np = NULL; 1853 } else { 1854 arg = strskipwhite(fp); 1855 fp = strwhite(arg); 1856 if (fp) 1857 *fp++ = '\0'; 1858 if (strcasecmp(arg, "reserved")) { 1859 np = strdup(arg); 1860 if (np == NULL) { 1861 logerr(__func__); 1862 return -1; 1863 } 1864 } else { 1865 np = NULL; 1866 t |= OT_RESERVED; 1867 } 1868 } 1869 if (opt != O_EMBED) { 1870 for (dl = 0, ndop = *dop; dl < *dop_len; dl++, ndop++) 1871 { 1872 /* type 0 seems freshly malloced struct 1873 * for us to use */ 1874 if (ndop->option == u || ndop->type == 0) 1875 break; 1876 } 1877 if (dl == *dop_len) 1878 ndop = NULL; 1879 } else 1880 ndop = NULL; 1881 if (ndop == NULL) { 1882 ndop = reallocarray(*dop, *dop_len + 1, sizeof(**dop)); 1883 if (ndop == NULL) { 1884 logerr(__func__); 1885 free(np); 1886 return -1; 1887 } 1888 *dop = ndop; 1889 ndop = &(*dop)[(*dop_len)++]; 1890 ndop->embopts = NULL; 1891 ndop->embopts_len = 0; 1892 ndop->encopts = NULL; 1893 ndop->encopts_len = 0; 1894 } else 1895 free_dhcp_opt_embenc(ndop); 1896 ndop->option = (uint32_t)u; /* could have been 0 */ 1897 ndop->type = t; 1898 ndop->len = (size_t)l; 1899 ndop->var = np; 1900 if (bp) { 1901 dl = strlen(bp); 1902 memcpy(ndop->bitflags, bp, dl); 1903 memset(ndop->bitflags + dl, 0, 1904 sizeof(ndop->bitflags) - dl); 1905 } else 1906 memset(ndop->bitflags, 0, sizeof(ndop->bitflags)); 1907 /* Save the define for embed and encap options */ 1908 switch (opt) { 1909 case O_DEFINE: 1910 case O_DEFINEND: 1911 case O_DEFINE6: 1912 case O_VENDOPT: 1913 *ldop = ndop; 1914 break; 1915 case O_ENCAP: 1916 *edop = ndop; 1917 break; 1918 } 1919 break; 1920 case O_VENDCLASS: 1921 ARG_REQUIRED; 1922 fp = strwhite(arg); 1923 if (fp) 1924 *fp++ = '\0'; 1925 u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); 1926 if (e) { 1927 logerrx("invalid code: %s", arg); 1928 return -1; 1929 } 1930 fp = strskipwhite(fp); 1931 if (fp) { 1932 s = parse_string(NULL, 0, fp); 1933 if (s == -1) { 1934 logerr(__func__); 1935 return -1; 1936 } 1937 dl = (size_t)s; 1938 if (dl + (sizeof(uint16_t) * 2) > UINT16_MAX) { 1939 logerrx("vendor class is too big"); 1940 return -1; 1941 } 1942 np = malloc(dl); 1943 if (np == NULL) { 1944 logerr(__func__); 1945 return -1; 1946 } 1947 parse_string(np, dl, fp); 1948 } else { 1949 dl = 0; 1950 np = NULL; 1951 } 1952 vivco = reallocarray(ifo->vivco, 1953 ifo->vivco_len + 1, sizeof(*ifo->vivco)); 1954 if (vivco == NULL) { 1955 logerr( __func__); 1956 free(np); 1957 return -1; 1958 } 1959 ifo->vivco = vivco; 1960 ifo->vivco_en = (uint32_t)u; 1961 vivco = &ifo->vivco[ifo->vivco_len++]; 1962 vivco->len = dl; 1963 vivco->data = (uint8_t *)np; 1964 break; 1965 case O_AUTHPROTOCOL: 1966 ARG_REQUIRED; 1967 #ifdef AUTH 1968 fp = strwhite(arg); 1969 if (fp) 1970 *fp++ = '\0'; 1971 if (strcasecmp(arg, "token") == 0) 1972 ifo->auth.protocol = AUTH_PROTO_TOKEN; 1973 else if (strcasecmp(arg, "delayed") == 0) 1974 ifo->auth.protocol = AUTH_PROTO_DELAYED; 1975 else if (strcasecmp(arg, "delayedrealm") == 0) 1976 ifo->auth.protocol = AUTH_PROTO_DELAYEDREALM; 1977 else { 1978 logerrx("%s: unsupported protocol", arg); 1979 return -1; 1980 } 1981 arg = strskipwhite(fp); 1982 fp = strwhite(arg); 1983 if (arg == NULL) { 1984 ifo->auth.options |= DHCPCD_AUTH_SEND; 1985 if (ifo->auth.protocol == AUTH_PROTO_TOKEN) 1986 ifo->auth.protocol = AUTH_ALG_NONE; 1987 else 1988 ifo->auth.algorithm = AUTH_ALG_HMAC_MD5; 1989 ifo->auth.rdm = AUTH_RDM_MONOTONIC; 1990 break; 1991 } 1992 if (fp) 1993 *fp++ = '\0'; 1994 if (ifo->auth.protocol == AUTH_PROTO_TOKEN) { 1995 np = strchr(arg, '/'); 1996 if (np) { 1997 if (fp == NULL || np < fp) 1998 *np++ = '\0'; 1999 else 2000 np = NULL; 2001 } 2002 if (parse_uint32(&ifo->auth.token_snd_secretid, 2003 arg) == -1) 2004 logerrx("%s: not a number", arg); 2005 else 2006 ifo->auth.token_rcv_secretid = 2007 ifo->auth.token_snd_secretid; 2008 if (np && 2009 parse_uint32(&ifo->auth.token_rcv_secretid, 2010 np) == -1) 2011 logerrx("%s: not a number", arg); 2012 } else { 2013 if (strcasecmp(arg, "hmacmd5") == 0 || 2014 strcasecmp(arg, "hmac-md5") == 0) 2015 ifo->auth.algorithm = AUTH_ALG_HMAC_MD5; 2016 else { 2017 logerrx("%s: unsupported algorithm", arg); 2018 return 1; 2019 } 2020 } 2021 arg = fp; 2022 if (arg == NULL) { 2023 ifo->auth.options |= DHCPCD_AUTH_SEND; 2024 ifo->auth.rdm = AUTH_RDM_MONOTONIC; 2025 break; 2026 } 2027 if (strcasecmp(arg, "monocounter") == 0) { 2028 ifo->auth.rdm = AUTH_RDM_MONOTONIC; 2029 ifo->auth.options |= DHCPCD_AUTH_RDM_COUNTER; 2030 } else if (strcasecmp(arg, "monotonic") ==0 || 2031 strcasecmp(arg, "monotime") == 0) 2032 ifo->auth.rdm = AUTH_RDM_MONOTONIC; 2033 else { 2034 logerrx("%s: unsupported RDM", arg); 2035 return -1; 2036 } 2037 ifo->auth.options |= DHCPCD_AUTH_SEND; 2038 break; 2039 #else 2040 logerrx("no authentication support"); 2041 return -1; 2042 #endif 2043 case O_AUTHTOKEN: 2044 ARG_REQUIRED; 2045 #ifdef AUTH 2046 fp = strwhite(arg); 2047 if (fp == NULL) { 2048 logerrx("authtoken requires a realm"); 2049 return -1; 2050 } 2051 *fp++ = '\0'; 2052 token = calloc(1, sizeof(*token)); 2053 if (token == NULL) { 2054 logerr(__func__); 2055 return -1; 2056 } 2057 if (parse_uint32(&token->secretid, arg) == -1) { 2058 logerrx("%s: not a number", arg); 2059 goto invalid_token; 2060 } 2061 arg = fp; 2062 fp = strend(arg); 2063 if (fp == NULL) { 2064 logerrx("authtoken requies an a key"); 2065 goto invalid_token; 2066 } 2067 *fp++ = '\0'; 2068 s = parse_string(NULL, 0, arg); 2069 if (s == -1) { 2070 logerr("realm_len"); 2071 goto invalid_token; 2072 } 2073 if (s != 0) { 2074 token->realm_len = (size_t)s; 2075 token->realm = malloc(token->realm_len); 2076 if (token->realm == NULL) { 2077 logerr(__func__); 2078 goto invalid_token; 2079 } 2080 parse_string((char *)token->realm, token->realm_len, 2081 arg); 2082 } 2083 arg = fp; 2084 fp = strend(arg); 2085 if (fp == NULL) { 2086 logerrx("authtoken requies an expiry date"); 2087 goto invalid_token; 2088 } 2089 *fp++ = '\0'; 2090 if (*arg == '"') { 2091 arg++; 2092 np = strchr(arg, '"'); 2093 if (np) 2094 *np = '\0'; 2095 } 2096 if (strcmp(arg, "0") == 0 || strcasecmp(arg, "forever") == 0) 2097 token->expire =0; 2098 else { 2099 struct tm tm; 2100 2101 memset(&tm, 0, sizeof(tm)); 2102 if (strptime(arg, "%Y-%m-%d %H:%M", &tm) == NULL) { 2103 logerrx("%s: invalid date time", arg); 2104 goto invalid_token; 2105 } 2106 if ((token->expire = mktime(&tm)) == (time_t)-1) { 2107 logerr("%s: mktime", __func__); 2108 goto invalid_token; 2109 } 2110 } 2111 arg = fp; 2112 s = parse_string(NULL, 0, arg); 2113 if (s == -1 || s == 0) { 2114 if (s == -1) 2115 logerr("token_len"); 2116 else 2117 logerrx("authtoken needs a key"); 2118 goto invalid_token; 2119 } 2120 token->key_len = (size_t)s; 2121 token->key = malloc(token->key_len); 2122 if (token->key == NULL) { 2123 logerr(__func__); 2124 goto invalid_token; 2125 } 2126 parse_string((char *)token->key, token->key_len, arg); 2127 TAILQ_INSERT_TAIL(&ifo->auth.tokens, token, next); 2128 break; 2129 2130 invalid_token: 2131 free(token->realm); 2132 free(token); 2133 #else 2134 logerrx("no authentication support"); 2135 #endif 2136 return -1; 2137 case O_AUTHNOTREQUIRED: 2138 ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE; 2139 break; 2140 case O_DHCP: 2141 ifo->options |= DHCPCD_DHCP | DHCPCD_WANTDHCP | DHCPCD_IPV4; 2142 break; 2143 case O_NODHCP: 2144 ifo->options &= ~DHCPCD_DHCP; 2145 break; 2146 case O_DHCP6: 2147 ifo->options |= DHCPCD_DHCP6 | DHCPCD_IPV6; 2148 break; 2149 case O_NODHCP6: 2150 ifo->options &= ~DHCPCD_DHCP6; 2151 break; 2152 case O_CONTROLGRP: 2153 ARG_REQUIRED; 2154 #ifdef PRIVSEP 2155 /* Control group is already set by this point. 2156 * We don't need to pledge getpw either with this. */ 2157 if (IN_PRIVSEP(ctx)) 2158 break; 2159 #endif 2160 #ifdef _REENTRANT 2161 l = sysconf(_SC_GETGR_R_SIZE_MAX); 2162 if (l == -1) 2163 dl = 1024; 2164 else 2165 dl = (size_t)l; 2166 p = malloc(dl); 2167 if (p == NULL) { 2168 logerr(__func__); 2169 return -1; 2170 } 2171 while ((i = getgrnam_r(arg, &grpbuf, p, dl, &grp)) == 2172 ERANGE) 2173 { 2174 size_t nl = dl * 2; 2175 if (nl < dl) { 2176 logerrx("control_group: out of buffer"); 2177 free(p); 2178 return -1; 2179 } 2180 dl = nl; 2181 np = realloc(p, dl); 2182 if (np == NULL) { 2183 logerr(__func__); 2184 free(p); 2185 return -1; 2186 } 2187 p = np; 2188 } 2189 if (i != 0) { 2190 errno = i; 2191 logerr("getgrnam_r"); 2192 free(p); 2193 return -1; 2194 } 2195 if (grp == NULL) { 2196 if (!ctx->control_group) 2197 logerrx("controlgroup: %s: not found", arg); 2198 free(p); 2199 return -1; 2200 } 2201 ctx->control_group = grp->gr_gid; 2202 free(p); 2203 #else 2204 grp = getgrnam(arg); 2205 if (grp == NULL) { 2206 if (!ctx->control_group) 2207 logerrx("controlgroup: %s: not found", arg); 2208 return -1; 2209 } 2210 ctx->control_group = grp->gr_gid; 2211 #endif 2212 break; 2213 case O_GATEWAY: 2214 ifo->options |= DHCPCD_GATEWAY; 2215 break; 2216 case O_NOUP: 2217 ifo->options &= ~DHCPCD_IF_UP; 2218 break; 2219 case O_SLAAC: 2220 ARG_REQUIRED; 2221 np = strwhite(arg); 2222 if (np != NULL) { 2223 *np++ = '\0'; 2224 np = strskipwhite(np); 2225 } 2226 if (strcmp(arg, "private") == 0 || 2227 strcmp(arg, "stableprivate") == 0 || 2228 strcmp(arg, "stable") == 0) 2229 ifo->options |= DHCPCD_SLAACPRIVATE; 2230 else 2231 ifo->options &= ~DHCPCD_SLAACPRIVATE; 2232 if (np != NULL && 2233 (strcmp(np, "temp") == 0 || strcmp(np, "temporary") == 0)) 2234 ifo->options |= DHCPCD_SLAACTEMP; 2235 break; 2236 case O_BOOTP: 2237 ifo->options |= DHCPCD_BOOTP; 2238 break; 2239 case O_NODELAY: 2240 ifo->options &= ~DHCPCD_INITIAL_DELAY; 2241 break; 2242 case O_LASTLEASE_EXTEND: 2243 ifo->options |= DHCPCD_LASTLEASE | DHCPCD_LASTLEASE_EXTEND; 2244 break; 2245 case O_INACTIVE: 2246 ifo->options |= DHCPCD_INACTIVE; 2247 break; 2248 case O_MUDURL: 2249 ARG_REQUIRED; 2250 s = parse_string((char *)ifo->mudurl + 1, MUDURL_MAX_LEN, arg); 2251 if (s == -1) { 2252 logerr("mudurl"); 2253 return -1; 2254 } 2255 *ifo->mudurl = (uint8_t)s; 2256 break; 2257 case O_LINK_RCVBUF: 2258 #ifndef SMALL 2259 ARG_REQUIRED; 2260 ctx->link_rcvbuf = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e); 2261 if (e) { 2262 logerrx("failed to convert link_rcvbuf %s", arg); 2263 return -1; 2264 } 2265 #endif 2266 break; 2267 case O_CONFIGURE: 2268 ifo->options |= DHCPCD_CONFIGURE; 2269 break; 2270 case O_NOCONFIGURE: 2271 ifo->options &= ~DHCPCD_CONFIGURE; 2272 break; 2273 default: 2274 return 0; 2275 } 2276 2277 return 1; 2278 2279 #ifdef ARG_REQUIRED 2280 arg_required: 2281 logerrx("option %d requires an argument", opt); 2282 return -1; 2283 #undef ARG_REQUIRED 2284 #endif 2285 } 2286 2287 static int 2288 parse_config_line(struct dhcpcd_ctx *ctx, const char *ifname, 2289 struct if_options *ifo, const char *opt, char *line, 2290 struct dhcp_opt **ldop, struct dhcp_opt **edop) 2291 { 2292 unsigned int i; 2293 2294 for (i = 0; i < sizeof(cf_options) / sizeof(cf_options[0]); i++) { 2295 if (!cf_options[i].name || 2296 strcmp(cf_options[i].name, opt) != 0) 2297 continue; 2298 2299 if (cf_options[i].has_arg == required_argument && !line) { 2300 logerrx("option requires an argument -- %s", opt); 2301 return -1; 2302 } 2303 2304 return parse_option(ctx, ifname, ifo, cf_options[i].val, line, 2305 ldop, edop); 2306 } 2307 2308 if (!(ctx->options & DHCPCD_PRINT_PIDFILE)) 2309 logerrx("unknown option: %s", opt); 2310 return -1; 2311 } 2312 2313 static void 2314 finish_config(struct if_options *ifo) 2315 { 2316 2317 /* Terminate the encapsulated options */ 2318 if (ifo->vendor[0] && !(ifo->options & DHCPCD_VENDORRAW)) { 2319 ifo->vendor[0]++; 2320 ifo->vendor[ifo->vendor[0]] = DHO_END; 2321 /* We are called twice. 2322 * This should be fixed, but in the meantime, this 2323 * guard should suffice */ 2324 ifo->options |= DHCPCD_VENDORRAW; 2325 } 2326 2327 if (!(ifo->options & DHCPCD_ARP) || 2328 ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)) 2329 ifo->options &= ~DHCPCD_IPV4LL; 2330 2331 if (!(ifo->options & DHCPCD_IPV4)) 2332 ifo->options &= ~(DHCPCD_DHCP | DHCPCD_IPV4LL | DHCPCD_WAITIP4); 2333 2334 if (!(ifo->options & DHCPCD_IPV6)) 2335 ifo->options &= 2336 ~(DHCPCD_IPV6RS | DHCPCD_DHCP6 | DHCPCD_WAITIP6); 2337 2338 if (!(ifo->options & DHCPCD_IPV6RS)) 2339 ifo->options &= 2340 ~(DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS); 2341 } 2342 2343 struct if_options * 2344 default_config(struct dhcpcd_ctx *ctx) 2345 { 2346 struct if_options *ifo; 2347 2348 /* Seed our default options */ 2349 if ((ifo = calloc(1, sizeof(*ifo))) == NULL) { 2350 logerr(__func__); 2351 return NULL; 2352 } 2353 ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY; 2354 ifo->timeout = DEFAULT_TIMEOUT; 2355 ifo->reboot = DEFAULT_REBOOT; 2356 ifo->metric = -1; 2357 ifo->auth.options |= DHCPCD_AUTH_REQUIRE; 2358 rb_tree_init(&ifo->routes, &rt_compare_list_ops); 2359 #ifdef AUTH 2360 TAILQ_INIT(&ifo->auth.tokens); 2361 #endif 2362 2363 /* Inherit some global defaults */ 2364 if (ctx->options & DHCPCD_CONFIGURE) 2365 ifo->options |= DHCPCD_CONFIGURE; 2366 if (ctx->options & DHCPCD_PERSISTENT) 2367 ifo->options |= DHCPCD_PERSISTENT; 2368 if (ctx->options & DHCPCD_SLAACPRIVATE) 2369 ifo->options |= DHCPCD_SLAACPRIVATE; 2370 2371 return ifo; 2372 } 2373 2374 struct if_options * 2375 read_config(struct dhcpcd_ctx *ctx, 2376 const char *ifname, const char *ssid, const char *profile) 2377 { 2378 struct if_options *ifo; 2379 char buf[UDPLEN_MAX], *bp; /* 64k max config file size */ 2380 char *line, *option, *p; 2381 ssize_t buflen; 2382 size_t vlen; 2383 int skip, have_profile, new_block, had_block; 2384 #if !defined(INET) || !defined(INET6) 2385 size_t i; 2386 struct dhcp_opt *opt; 2387 #endif 2388 struct dhcp_opt *ldop, *edop; 2389 2390 /* Seed our default options */ 2391 if ((ifo = default_config(ctx)) == NULL) 2392 return NULL; 2393 if (default_options == 0) { 2394 default_options |= DHCPCD_CONFIGURE | DHCPCD_DAEMONISE | 2395 DHCPCD_GATEWAY; 2396 #ifdef INET 2397 skip = socket(PF_INET, SOCK_DGRAM, 0); 2398 if (skip != -1) { 2399 close(skip); 2400 default_options |= DHCPCD_IPV4 | DHCPCD_ARP | 2401 DHCPCD_DHCP | DHCPCD_IPV4LL; 2402 } 2403 #endif 2404 #ifdef INET6 2405 skip = socket(PF_INET6, SOCK_DGRAM, 0); 2406 if (skip != -1) { 2407 close(skip); 2408 default_options |= DHCPCD_IPV6 | DHCPCD_IPV6RS | 2409 DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS | 2410 DHCPCD_DHCP6; 2411 } 2412 #endif 2413 #ifdef PLUGIN_DEV 2414 default_options |= DHCPCD_DEV; 2415 #endif 2416 } 2417 ifo->options |= default_options; 2418 2419 CLEAR_CONFIG_BLOCK(ifo); 2420 2421 vlen = strlcpy((char *)ifo->vendorclassid + 1, ctx->vendor, 2422 sizeof(ifo->vendorclassid) - 1); 2423 ifo->vendorclassid[0] = (uint8_t)(vlen > 255 ? 0 : vlen); 2424 2425 /* Reset route order */ 2426 ctx->rt_order = 0; 2427 2428 /* Parse our embedded options file */ 2429 if (ifname == NULL && !(ctx->options & DHCPCD_PRINT_PIDFILE)) { 2430 /* Space for initial estimates */ 2431 #if defined(INET) && defined(INITDEFINES) 2432 ifo->dhcp_override = 2433 calloc(INITDEFINES, sizeof(*ifo->dhcp_override)); 2434 if (ifo->dhcp_override == NULL) 2435 logerr(__func__); 2436 else 2437 ifo->dhcp_override_len = INITDEFINES; 2438 #endif 2439 2440 #if defined(INET6) && defined(INITDEFINENDS) 2441 ifo->nd_override = 2442 calloc(INITDEFINENDS, sizeof(*ifo->nd_override)); 2443 if (ifo->nd_override == NULL) 2444 logerr(__func__); 2445 else 2446 ifo->nd_override_len = INITDEFINENDS; 2447 #endif 2448 #if defined(INET6) && defined(INITDEFINE6S) 2449 ifo->dhcp6_override = 2450 calloc(INITDEFINE6S, sizeof(*ifo->dhcp6_override)); 2451 if (ifo->dhcp6_override == NULL) 2452 logerr(__func__); 2453 else 2454 ifo->dhcp6_override_len = INITDEFINE6S; 2455 #endif 2456 2457 /* Now load our embedded config */ 2458 #ifdef EMBEDDED_CONFIG 2459 buflen = dhcp_readfile(ctx, EMBEDDED_CONFIG, buf, sizeof(buf)); 2460 if (buflen == -1) { 2461 logerr("%s: %s", __func__, EMBEDDED_CONFIG); 2462 return ifo; 2463 } 2464 if (buf[buflen - 1] != '\0') { 2465 if ((size_t)buflen < sizeof(buf) - 1) 2466 buflen++; 2467 buf[buflen - 1] = '\0'; 2468 } 2469 #else 2470 buflen = (ssize_t)strlcpy(buf, dhcpcd_embedded_conf, 2471 sizeof(buf)); 2472 if ((size_t)buflen >= sizeof(buf)) { 2473 logerrx("%s: embedded config too big", __func__); 2474 return ifo; 2475 } 2476 /* Our embedded config is NULL terminated */ 2477 #endif 2478 bp = buf; 2479 while ((line = get_line(&bp, &buflen)) != NULL) { 2480 option = strsep(&line, " \t"); 2481 if (line) 2482 line = strskipwhite(line); 2483 /* Trim trailing whitespace */ 2484 if (line) { 2485 p = line + strlen(line) - 1; 2486 while (p != line && 2487 (*p == ' ' || *p == '\t') && 2488 *(p - 1) != '\\') 2489 *p-- = '\0'; 2490 } 2491 parse_config_line(ctx, NULL, ifo, option, line, 2492 &ldop, &edop); 2493 } 2494 2495 #ifdef INET 2496 ctx->dhcp_opts = ifo->dhcp_override; 2497 ctx->dhcp_opts_len = ifo->dhcp_override_len; 2498 #else 2499 for (i = 0, opt = ifo->dhcp_override; 2500 i < ifo->dhcp_override_len; 2501 i++, opt++) 2502 free_dhcp_opt_embenc(opt); 2503 free(ifo->dhcp_override); 2504 #endif 2505 ifo->dhcp_override = NULL; 2506 ifo->dhcp_override_len = 0; 2507 2508 #ifdef INET6 2509 ctx->nd_opts = ifo->nd_override; 2510 ctx->nd_opts_len = ifo->nd_override_len; 2511 #ifdef DHCP6 2512 ctx->dhcp6_opts = ifo->dhcp6_override; 2513 ctx->dhcp6_opts_len = ifo->dhcp6_override_len; 2514 #endif 2515 #else 2516 for (i = 0, opt = ifo->nd_override; 2517 i < ifo->nd_override_len; 2518 i++, opt++) 2519 free_dhcp_opt_embenc(opt); 2520 free(ifo->nd_override); 2521 for (i = 0, opt = ifo->dhcp6_override; 2522 i < ifo->dhcp6_override_len; 2523 i++, opt++) 2524 free_dhcp_opt_embenc(opt); 2525 free(ifo->dhcp6_override); 2526 #endif 2527 ifo->nd_override = NULL; 2528 ifo->nd_override_len = 0; 2529 ifo->dhcp6_override = NULL; 2530 ifo->dhcp6_override_len = 0; 2531 2532 ctx->vivso = ifo->vivso_override; 2533 ctx->vivso_len = ifo->vivso_override_len; 2534 ifo->vivso_override = NULL; 2535 ifo->vivso_override_len = 0; 2536 } 2537 2538 /* Parse our options file */ 2539 buflen = dhcp_readfile(ctx, ctx->cffile, buf, sizeof(buf)); 2540 if (buflen == -1) { 2541 /* dhcpcd can continue without it, but no DNS options 2542 * would be requested ... */ 2543 logerr("%s: %s", __func__, ctx->cffile); 2544 return ifo; 2545 } 2546 if (buf[buflen - 1] != '\0') { 2547 if ((size_t)buflen < sizeof(buf) - 1) 2548 buflen++; 2549 buf[buflen - 1] = '\0'; 2550 } 2551 dhcp_filemtime(ctx, ctx->cffile, &ifo->mtime); 2552 2553 ldop = edop = NULL; 2554 skip = have_profile = new_block = 0; 2555 had_block = ifname == NULL ? 1 : 0; 2556 bp = buf; 2557 while ((line = get_line(&bp, &buflen)) != NULL) { 2558 option = strsep(&line, " \t"); 2559 if (line) 2560 line = strskipwhite(line); 2561 /* Trim trailing whitespace */ 2562 if (line) { 2563 p = line + strlen(line) - 1; 2564 while (p != line && 2565 (*p == ' ' || *p == '\t') && 2566 *(p - 1) != '\\') 2567 *p-- = '\0'; 2568 } 2569 if (skip == 0 && new_block) { 2570 had_block = 1; 2571 new_block = 0; 2572 ifo->options &= ~DHCPCD_WAITOPTS; 2573 SET_CONFIG_BLOCK(ifo); 2574 } 2575 2576 /* Start of an interface block, skip if not ours */ 2577 if (strcmp(option, "interface") == 0) { 2578 char **n; 2579 2580 new_block = 1; 2581 if (line == NULL) { 2582 /* No interface given */ 2583 skip = 1; 2584 continue; 2585 } 2586 if (ifname && strcmp(line, ifname) == 0) 2587 skip = 0; 2588 else 2589 skip = 1; 2590 if (ifname) 2591 continue; 2592 2593 n = reallocarray(ctx->ifcv, 2594 (size_t)ctx->ifcc + 1, sizeof(char *)); 2595 if (n == NULL) { 2596 logerr(__func__); 2597 continue; 2598 } 2599 ctx->ifcv = n; 2600 ctx->ifcv[ctx->ifcc] = strdup(line); 2601 if (ctx->ifcv[ctx->ifcc] == NULL) { 2602 logerr(__func__); 2603 continue; 2604 } 2605 ctx->ifcc++; 2606 continue; 2607 } 2608 /* Start of an ssid block, skip if not ours */ 2609 if (strcmp(option, "ssid") == 0) { 2610 new_block = 1; 2611 if (ssid && line && strcmp(line, ssid) == 0) 2612 skip = 0; 2613 else 2614 skip = 1; 2615 continue; 2616 } 2617 /* Start of a profile block, skip if not ours */ 2618 if (strcmp(option, "profile") == 0) { 2619 new_block = 1; 2620 if (profile && line && strcmp(line, profile) == 0) { 2621 skip = 0; 2622 have_profile = 1; 2623 } else 2624 skip = 1; 2625 continue; 2626 } 2627 /* Skip arping if we have selected a profile but not parsing 2628 * one. */ 2629 if (profile && !have_profile && strcmp(option, "arping") == 0) 2630 continue; 2631 if (skip) 2632 continue; 2633 2634 parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop); 2635 } 2636 2637 if (profile && !have_profile) { 2638 free_options(ctx, ifo); 2639 errno = ENOENT; 2640 return NULL; 2641 } 2642 2643 if (!had_block) 2644 ifo->options &= ~DHCPCD_WAITOPTS; 2645 CLEAR_CONFIG_BLOCK(ifo); 2646 finish_config(ifo); 2647 return ifo; 2648 } 2649 2650 int 2651 add_options(struct dhcpcd_ctx *ctx, const char *ifname, 2652 struct if_options *ifo, int argc, char **argv) 2653 { 2654 int oi, opt, r; 2655 unsigned long long wait_opts; 2656 2657 if (argc == 0) 2658 return 1; 2659 2660 optind = 0; 2661 r = 1; 2662 /* Don't apply the command line wait options to each interface, 2663 * only use the dhcpcd.conf entry for that. */ 2664 if (ifname != NULL) 2665 wait_opts = ifo->options & DHCPCD_WAITOPTS; 2666 while ((opt = getopt_long(argc, argv, 2667 ctx->options & DHCPCD_PRINT_PIDFILE ? NOERR_IF_OPTS : IF_OPTS, 2668 cf_options, &oi)) != -1) 2669 { 2670 r = parse_option(ctx, ifname, ifo, opt, optarg, NULL, NULL); 2671 if (r != 1) 2672 break; 2673 } 2674 if (ifname != NULL) { 2675 ifo->options &= ~DHCPCD_WAITOPTS; 2676 ifo->options |= wait_opts; 2677 } 2678 2679 finish_config(ifo); 2680 return r; 2681 } 2682 2683 void 2684 free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo) 2685 { 2686 size_t i; 2687 #ifdef RT_FREE_ROUTE_TABLE 2688 struct interface *ifp; 2689 struct rt *rt; 2690 #endif 2691 struct dhcp_opt *opt; 2692 struct vivco *vo; 2693 #ifdef AUTH 2694 struct token *token; 2695 #endif 2696 2697 if (ifo == NULL) 2698 return; 2699 2700 if (ifo->environ) { 2701 i = 0; 2702 while (ifo->environ[i]) 2703 free(ifo->environ[i++]); 2704 free(ifo->environ); 2705 } 2706 if (ifo->config) { 2707 i = 0; 2708 while (ifo->config[i]) 2709 free(ifo->config[i++]); 2710 free(ifo->config); 2711 } 2712 2713 #ifdef RT_FREE_ROUTE_TABLE 2714 /* Stupidly, we don't know the interface when creating the options. 2715 * As such, make sure each route has one so they can goto the 2716 * free list. */ 2717 ifp = ctx->ifaces != NULL ? TAILQ_FIRST(ctx->ifaces) : NULL; 2718 if (ifp != NULL) { 2719 RB_TREE_FOREACH(rt, &ifo->routes) { 2720 if (rt->rt_ifp == NULL) 2721 rt->rt_ifp = ifp; 2722 } 2723 } 2724 #endif 2725 rt_headclear0(ctx, &ifo->routes, AF_UNSPEC); 2726 2727 free(ifo->arping); 2728 free(ifo->blacklist); 2729 free(ifo->fallback); 2730 2731 for (opt = ifo->dhcp_override; 2732 ifo->dhcp_override_len > 0; 2733 opt++, ifo->dhcp_override_len--) 2734 free_dhcp_opt_embenc(opt); 2735 free(ifo->dhcp_override); 2736 for (opt = ifo->nd_override; 2737 ifo->nd_override_len > 0; 2738 opt++, ifo->nd_override_len--) 2739 free_dhcp_opt_embenc(opt); 2740 free(ifo->nd_override); 2741 for (opt = ifo->dhcp6_override; 2742 ifo->dhcp6_override_len > 0; 2743 opt++, ifo->dhcp6_override_len--) 2744 free_dhcp_opt_embenc(opt); 2745 free(ifo->dhcp6_override); 2746 for (vo = ifo->vivco; 2747 ifo->vivco_len > 0; 2748 vo++, ifo->vivco_len--) 2749 free(vo->data); 2750 free(ifo->vivco); 2751 for (opt = ifo->vivso_override; 2752 ifo->vivso_override_len > 0; 2753 opt++, ifo->vivso_override_len--) 2754 free_dhcp_opt_embenc(opt); 2755 free(ifo->vivso_override); 2756 2757 #if defined(INET6) && !defined(SMALL) 2758 for (; ifo->ia_len > 0; ifo->ia_len--) 2759 free(ifo->ia[ifo->ia_len - 1].sla); 2760 #endif 2761 free(ifo->ia); 2762 2763 #ifdef AUTH 2764 while ((token = TAILQ_FIRST(&ifo->auth.tokens))) { 2765 TAILQ_REMOVE(&ifo->auth.tokens, token, next); 2766 if (token->realm_len) 2767 free(token->realm); 2768 free(token->key); 2769 free(token); 2770 } 2771 #endif 2772 free(ifo); 2773 } 2774