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