1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2023 Roy Marples <roy@marples.name>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/param.h>
30 #include <sys/types.h>
32 #include <arpa/inet.h>
51 #include "dhcpcd-embedded.h"
54 #include "if-options.h"
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)
63 static unsigned long long default_options
;
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'},
88 {"msuserclass", required_argument
, NULL
, O_MSUSERCLASS
},
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'}
175 add_environ(char ***array
, const char *value
, int uniq
)
177 char **newlist
, **list
= *array
;
179 char *match
= NULL
, *p
, *n
;
181 match
= strdup(value
);
186 p
= strchr(match
, '=');
188 logerrx("%s: no assignment: %s", __func__
, value
);
195 while (list
&& list
[i
]) {
196 /* We know that it must contain '=' due to the above test */
197 size_t listl
= (size_t)(strchr(list
[i
], '=') - list
[i
]);
199 if (l
== listl
&& strncmp(list
[i
], match
, l
) == 0) {
210 /* Append a space and the value to it */
213 n
= realloc(list
[i
], l
+ lv
+ 2);
221 memcpy(list
[i
] + l
+ 1, p
, lv
);
222 list
[i
][l
+ lv
+ 1] = '\0';
236 newlist
= reallocarray(list
, i
+ 2, sizeof(char *));
237 if (newlist
== NULL
) {
243 newlist
[i
+ 1] = NULL
;
248 #define PARSE_STRING 0
249 #define PARSE_STRING_NULL 1
250 #define PARSE_HWADDR 2
251 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
252 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
253 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
255 parse_str(char *sbuf
, size_t slen
, const char *str
, int flags
)
262 end
= str
+ strlen(str
);
263 /* If surrounded by quotes then it's a string */
271 l
= (size_t)hwaddr_aton(NULL
, str
);
273 if ((ssize_t
)l
== -1) {
283 hwaddr_aton((uint8_t *)sbuf
, str
);
288 /* Process escapes */
290 /* If processing a string on the clientid, first byte should be
291 * 0 to indicate a non hardware type */
292 if (flags
== PARSE_HWADDR
&& *str
) {
299 if (++l
> slen
&& sbuf
) {
305 switch((cmd
= *str
++)) {
326 /* Grab a hex code */
328 for (i
= 0; i
< 2; i
++) {
329 if (isxdigit((unsigned char)*str
) == 0)
336 *sbuf
++ = (char)strtol(c
, NULL
, 16);
341 /* Grab an octal code */
343 for (i
= 0; i
< 3; i
++) {
344 if (*str
< '0' || *str
> '7')
349 i
= (int)strtol(c
, NULL
, 8);
368 if (flags
== PARSE_STRING_NULL
) {
382 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
388 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
392 memcpy(iaid
, &narg
, sizeof(narg
));
396 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
408 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
411 return parse_iaid1(iaid
, arg
, len
, 1);
416 parse_uint32(uint32_t *i
, const char *arg
)
419 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
424 splitv(int *argc
, char **argv
, const char *arg
)
426 char **n
, **v
= argv
;
427 char *o
= strdup(arg
), *p
, *t
, *nt
;
434 while ((t
= strsep(&p
, ", "))) {
441 n
= reallocarray(v
, (size_t)(*argc
) + 1, sizeof(char *));
457 parse_addr(struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
461 if (arg
== NULL
|| *arg
== '\0') {
468 if ((p
= strchr(arg
, '/')) != NULL
) {
473 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
475 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
477 logerrx("invalid CIDR: %s", p
);
482 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
483 logerrx("invalid IP address: %s", arg
);
488 else if (net
!= NULL
&& addr
!= NULL
)
489 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
494 parse_addr(__unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
495 __unused
const char *arg
)
498 logerrx("No IPv4 support");
504 set_option_space(struct dhcpcd_ctx
*ctx
,
506 const struct dhcp_opt
**d
, size_t *dl
,
507 const struct dhcp_opt
**od
, size_t *odl
,
508 struct if_options
*ifo
,
509 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
512 #if !defined(INET) && !defined(INET6)
517 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
519 *dl
= ctx
->nd_opts_len
;
520 *od
= ifo
->nd_override
;
521 *odl
= ifo
->nd_override_len
;
522 *request
= ifo
->requestmasknd
;
523 *require
= ifo
->requiremasknd
;
525 *reject
= ifo
->rejectmasknd
;
530 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
531 *d
= ctx
->dhcp6_opts
;
532 *dl
= ctx
->dhcp6_opts_len
;
533 *od
= ifo
->dhcp6_override
;
534 *odl
= ifo
->dhcp6_override_len
;
535 *request
= ifo
->requestmask6
;
536 *require
= ifo
->requiremask6
;
538 *reject
= ifo
->rejectmask6
;
548 *dl
= ctx
->dhcp_opts_len
;
549 *od
= ifo
->dhcp_override
;
550 *odl
= ifo
->dhcp_override_len
;
557 *request
= ifo
->requestmask
;
558 *require
= ifo
->requiremask
;
560 *reject
= ifo
->rejectmask
;
564 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
571 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
572 free_dhcp_opt_embenc(o
);
574 opt
->embopts_len
= 0;
577 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
578 free_dhcp_opt_embenc(o
);
580 opt
->encopts_len
= 0;
585 strwhite(const char *s
)
590 while (*s
!= ' ' && *s
!= '\t') {
599 strskipwhite(const char *s
)
602 if (s
== NULL
|| *s
== '\0')
604 while (*s
== ' ' || *s
== '\t') {
613 /* Find the end pointer of a string. */
615 strend(const char *s
)
622 return strchr(s
, ' ');
624 for (; *s
!= '"' ; s
++) {
637 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
638 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
643 char *p
= NULL
, *bp
, *fp
, *np
;
645 struct in_addr addr
, addr2
;
648 const struct dhcp_opt
*d
, *od
;
649 uint8_t *request
, *require
, *no
, *reject
;
650 struct dhcp_opt
**dop
, *ndop
;
651 size_t *dop_len
, dl
, odl
;
665 struct if_sla
*sla
, *slap
;
675 /* Add a guard for static analysers.
676 * This should not be needed really because of the argument_required option
677 * in the options declaration above. */
678 #define ARG_REQUIRED if (arg == NULL) goto arg_required
681 case 'f': /* FALLTHROUGH */
682 case 'g': /* FALLTHROUGH */
683 case 'n': /* FALLTHROUGH */
684 case 'q': /* FALLTHROUGH */
685 case 'x': /* FALLTHROUGH */
686 case 'N': /* FALLTHROUGH */
687 case 'P': /* FALLTHROUGH */
688 case 'T': /* FALLTHROUGH */
689 case 'U': /* FALLTHROUGH */
690 case 'V': /* We need to handle non interface options */
693 ifo
->options
|= DHCPCD_BACKGROUND
;
697 if (IN_CONFIG_BLOCK(ifo
)) {
698 logerrx("%s: per interface scripts"
699 " are no longer supported",
703 if (ctx
->script
!= dhcpcd_default_script
)
705 s
= parse_nstring(NULL
, 0, arg
);
711 if (s
== -1 || (ctx
->script
= malloc(dl
)) == NULL
) {
716 s
= parse_nstring(ctx
->script
, dl
, arg
);
718 ctx
->script
[0] == '\0' ||
719 strcmp(ctx
->script
, "/dev/null") == 0)
726 ifo
->options
|= DHCPCD_DEBUG
;
730 add_environ(&ifo
->environ
, arg
, 1);
734 ifo
->options
|= DHCPCD_HOSTNAME
;
737 s
= parse_nstring(ifo
->hostname
, sizeof(ifo
->hostname
), arg
);
739 logerr("%s: hostname", __func__
);
742 if (s
!= 0 && ifo
->hostname
[0] == '.') {
743 logerrx("hostname cannot begin with .");
746 if (ifo
->hostname
[0] == '\0')
747 ifo
->options
&= ~DHCPCD_HOSTNAME
;
749 ifo
->options
|= DHCPCD_HOSTNAME
;
753 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
754 VENDORCLASSID_MAX_LEN
, arg
);
758 logerr("vendorclassid");
761 *ifo
->vendorclassid
= (uint8_t)s
;
765 /* per interface logging is not supported
766 * don't want to overide the commandline */
767 if (!IN_CONFIG_BLOCK(ifo
) && ctx
->logfile
== NULL
) {
769 ctx
->logfile
= strdup(arg
);
770 logopen(ctx
->logfile
);
774 ifo
->options
|= DHCPCD_RELEASE
;
778 if (strcmp(arg
, "-1") == 0) {
779 ifo
->leasetime
= DHCP_INFINITE_LIFETIME
;
782 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
783 0, 0, UINT32_MAX
, &e
);
785 logerrx("failed to convert leasetime %s", arg
);
791 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
793 logerrx("failed to convert metric %s", arg
);
799 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
801 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
802 &request
, &require
, &no
, &reject
);
803 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
804 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
805 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
807 logerrx("unknown option: %s", arg
);
813 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
815 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
816 &request
, &require
, &no
, &reject
);
817 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
818 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
819 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
821 logerrx("unknown option: %s", arg
);
826 ifo
->options
|= DHCPCD_PERSISTENT
;
829 if (parse_addr(&ifo
->req_addr
, NULL
, arg
) != 0)
831 ifo
->options
|= DHCPCD_REQUEST
;
832 ifo
->req_mask
.s_addr
= 0;
835 if (arg
&& *arg
!= '\0') {
836 /* Strip out a broadcast address */
837 p
= strchr(arg
, '/');
839 p
= strchr(p
+ 1, '/');
843 i
= parse_addr(&ifo
->req_addr
, &ifo
->req_mask
, arg
);
845 /* Ensure the original string is preserved */
848 i
= parse_addr(&ifo
->req_brd
, NULL
, p
);
853 ifo
->req_addr
.s_addr
= 0;
854 ifo
->req_mask
.s_addr
= 0;
856 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
857 ifo
->options
&= ~DHCPCD_STATIC
;
860 ifo
->options
|= DHCPCD_INFORM6
;
864 ifo
->timeout
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
866 logerrx("failed to convert timeout %s", arg
);
871 dl
= sizeof(ifo
->userclass
) - ifo
->userclass
[0] - 1;
872 s
= parse_string((char *)ifo
->userclass
+
873 ifo
->userclass
[0] + 2, dl
, arg
);
879 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
880 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
885 /* Some Microsoft DHCP servers expect userclass to be an
886 * opaque blob. This is not RFC 3004 compliant. */
887 s
= parse_string((char *)ifo
->userclass
+ 1,
888 sizeof(ifo
->userclass
) - 1, arg
);
890 logerr("msuserclass");
893 ifo
->userclass
[0] = (uint8_t)s
;
898 p
= strchr(arg
, ',');
900 logerrx("invalid vendor format: %s", arg
);
904 /* If vendor starts with , then it is not encapsulated */
907 s
= parse_string((char *)ifo
->vendor
+ 1,
908 VENDOR_MAX_LEN
, arg
);
913 ifo
->vendor
[0] = (uint8_t)s
;
914 ifo
->options
|= DHCPCD_VENDORRAW
;
918 /* Encapsulated vendor options */
919 if (ifo
->options
& DHCPCD_VENDORRAW
) {
920 ifo
->options
&= ~DHCPCD_VENDORRAW
;
924 /* Strip and preserve the comma */
926 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
929 logerrx("vendor option should be between"
930 " 1 and 254 inclusive");
935 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
936 if (inet_aton(arg
, &addr
) == 1) {
941 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
942 &addr
.s_addr
, sizeof(addr
.s_addr
));
943 s
= sizeof(addr
.s_addr
);
946 s
= parse_string((char *)ifo
->vendor
+
947 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
954 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
955 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
956 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
960 ifo
->options
|= DHCPCD_WAITIP
;
962 // Generally it's --waitip=46, but some expect
963 // --waitip="4 6" to work as well.
964 // It's easier to allow it rather than have confusing docs.
965 while (p
!= NULL
&& p
[0] != '\0') {
966 if (p
[0] == '4' || p
[1] == '4')
967 ifo
->options
|= DHCPCD_WAITIP4
;
968 if (p
[0] == '6' || p
[1] == '6')
969 ifo
->options
|= DHCPCD_WAITIP6
;
970 p
= strskipwhite(++p
);
975 ifo
->reboot
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
977 logerr("failed to convert reboot %s", arg
);
983 if (!IN_CONFIG_BLOCK(ifo
))
984 ctx
->ifav
= splitv(&ctx
->ifac
, ctx
->ifav
, arg
);
987 ifo
->options
&= ~DHCPCD_ARP
;
988 /* IPv4LL requires ARP */
989 ifo
->options
&= ~DHCPCD_IPV4LL
;
992 ifo
->options
&= ~DHCPCD_DAEMONISE
;
996 /* Commas to spaces for shell */
997 while ((p
= strchr(arg
, ',')))
999 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
1000 p
= malloc(sizeof(char) * dl
);
1005 snprintf(p
, dl
, "skip_hooks=%s", arg
);
1006 add_environ(&ifo
->environ
, p
, 0);
1010 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
1011 if (ifname
!= NULL
) /* duid type only a global option */
1014 ctx
->duid_type
= DUID_DEFAULT
;
1015 else if (strcmp(arg
, "ll") == 0)
1016 ctx
->duid_type
= DUID_LL
;
1017 else if (strcmp(arg
, "llt") == 0)
1018 ctx
->duid_type
= DUID_LLT
;
1019 else if (strcmp(arg
, "uuid") == 0)
1020 ctx
->duid_type
= DUID_UUID
;
1022 dl
= hwaddr_aton(NULL
, arg
);
1024 no
= realloc(ctx
->duid
, dl
);
1029 ctx
->duid_len
= hwaddr_aton(no
, arg
);
1035 ifo
->options
|= DHCPCD_LASTLEASE
;
1039 ifo
->fqdn
= FQDN_BOTH
;
1042 if (strcmp(arg
, "none") == 0)
1043 ifo
->fqdn
= FQDN_NONE
;
1044 else if (strcmp(arg
, "ptr") == 0)
1045 ifo
->fqdn
= FQDN_PTR
;
1046 else if (strcmp(arg
, "both") == 0)
1047 ifo
->fqdn
= FQDN_BOTH
;
1048 else if (strcmp(arg
, "disable") == 0)
1049 ifo
->fqdn
= FQDN_DISABLE
;
1051 logerrx("invalid FQDN value: %s", arg
);
1056 ifo
->options
&= ~DHCPCD_GATEWAY
;
1059 ifo
->options
|= DHCPCD_XID_HWADDR
;
1062 /* Strings have a type of 0 */;
1063 ifo
->clientid
[1] = 0;
1065 s
= parse_hwaddr((char *)ifo
->clientid
+ 1,
1066 CLIENTID_MAX_LEN
, arg
);
1073 ifo
->options
|= DHCPCD_CLIENTID
;
1074 ifo
->clientid
[0] = (uint8_t)s
;
1075 ifo
->options
&= ~DHCPCD_DUID
;
1078 ifo
->options
|= DHCPCD_BROADCAST
;
1081 ifo
->options
&= ~DHCPCD_LINK
;
1084 ifo
->options
&= ~DHCPCD_IPV4LL
;
1087 ifo
->options
|= DHCPCD_MANAGER
;
1091 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
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
, request
, arg
, -1) != 0 ||
1096 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1097 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1099 logerrx("unknown option: %s", arg
);
1105 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1107 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1108 &request
, &require
, &no
, &reject
);
1109 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1110 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1111 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1112 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1114 logerrx("unknown option: %s", arg
);
1120 p
= strchr(arg
, '=');
1122 logerrx("static assignment required");
1125 p
= strskipwhite(++p
);
1126 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1128 ifo
->options
&= ~DHCPCD_STATIC
;
1129 ifo
->req_addr
.s_addr
= INADDR_ANY
;
1132 if (parse_addr(&ifo
->req_addr
,
1133 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1137 ifo
->options
|= DHCPCD_STATIC
;
1138 ifo
->options
&= ~DHCPCD_INFORM
;
1139 } else if (strncmp(arg
, "subnet_mask=",
1140 strlen("subnet_mask=")) == 0)
1143 ifo
->req_mask
.s_addr
= INADDR_ANY
;
1146 if (parse_addr(&ifo
->req_mask
, NULL
, p
) != 0)
1148 } else if (strncmp(arg
, "broadcast_address=",
1149 strlen("broadcast_address=")) == 0)
1152 ifo
->req_brd
.s_addr
= INADDR_ANY
;
1155 if (parse_addr(&ifo
->req_brd
, NULL
, p
) != 0)
1157 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1158 strncmp(arg
, "static_routes=",
1159 strlen("static_routes=")) == 0 ||
1160 strncmp(arg
, "classless_static_routes=",
1161 strlen("classless_static_routes=")) == 0 ||
1162 strncmp(arg
, "ms_classless_static_routes=",
1163 strlen("ms_classless_static_routes=")) == 0)
1165 struct in_addr addr3
;
1168 rt_headclear(&ifo
->routes
, AF_INET
);
1169 add_environ(&ifo
->config
, arg
, 1);
1173 fp
= np
= strwhite(p
);
1175 logerrx("all routes need a gateway");
1179 np
= strskipwhite(np
);
1180 if (parse_addr(&addr
, &addr2
, p
) == -1 ||
1181 parse_addr(&addr3
, NULL
, np
) == -1)
1187 if ((rt
= rt_new0(ctx
)) == NULL
)
1189 sa_in_init(&rt
->rt_dest
, &addr
);
1190 sa_in_init(&rt
->rt_netmask
, &addr2
);
1191 sa_in_init(&rt
->rt_gateway
, &addr3
);
1192 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1193 add_environ(&ifo
->config
, arg
, 0);
1194 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1196 rt_headclear(&ifo
->routes
, AF_INET
);
1197 add_environ(&ifo
->config
, arg
, 1);
1200 if (parse_addr(&addr
, NULL
, p
) == -1)
1202 if ((rt
= rt_new0(ctx
)) == NULL
)
1204 addr2
.s_addr
= INADDR_ANY
;
1205 sa_in_init(&rt
->rt_dest
, &addr2
);
1206 sa_in_init(&rt
->rt_netmask
, &addr2
);
1207 sa_in_init(&rt
->rt_gateway
, &addr
);
1208 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1209 add_environ(&ifo
->config
, arg
, 0);
1210 } else if (strncmp(arg
, "interface_mtu=",
1211 strlen("interface_mtu=")) == 0 ||
1212 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1216 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1217 MTU_MIN
, MTU_MAX
, &e
);
1219 logerrx("invalid MTU %s", p
);
1222 } else if (strncmp(arg
, "ip6_address=", strlen("ip6_address=")) == 0) {
1224 memset(&ifo
->req_addr6
, 0,
1225 sizeof(ifo
->req_addr6
));
1229 np
= strchr(p
, '/');
1232 if ((i
= inet_pton(AF_INET6
, p
, &ifo
->req_addr6
)) == 1) {
1234 ifo
->req_prefix_len
= (uint8_t)strtou(np
,
1235 NULL
, 0, 0, 128, &e
);
1237 logerrx("%s: failed to "
1238 "convert prefix len",
1243 ifo
->req_prefix_len
= 128;
1248 logerrx("invalid AF_INET6: %s", p
);
1249 memset(&ifo
->req_addr6
, 0,
1250 sizeof(ifo
->req_addr6
));
1254 add_environ(&ifo
->config
, arg
, p
== NULL
? 1 : 0);
1258 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1260 if (strchr(arg
, '/') == NULL
)
1261 addr2
.s_addr
= INADDR_BROADCAST
;
1262 naddr
= reallocarray(ifo
->whitelist
,
1263 ifo
->whitelist_len
+ 2, sizeof(in_addr_t
));
1264 if (naddr
== NULL
) {
1268 ifo
->whitelist
= naddr
;
1269 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1270 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1273 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1275 if (strchr(arg
, '/') == NULL
)
1276 addr2
.s_addr
= INADDR_BROADCAST
;
1277 naddr
= reallocarray(ifo
->blacklist
,
1278 ifo
->blacklist_len
+ 2, sizeof(in_addr_t
));
1279 if (naddr
== NULL
) {
1283 ifo
->blacklist
= naddr
;
1284 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1285 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1289 if (!IN_CONFIG_BLOCK(ifo
))
1290 ctx
->ifdv
= splitv(&ctx
->ifdc
, ctx
->ifdv
, arg
);
1293 ifo
->options
|= DHCPCD_ONESHOT
;
1297 ifo
->options
&= ~DHCPCD_IPV6
;
1298 ifo
->options
|= DHCPCD_IPV4
;
1301 logerrx("INET has been compiled out");
1306 ifo
->options
&= ~DHCPCD_IPV4
;
1307 ifo
->options
|= DHCPCD_IPV6
;
1310 logerrx("INET6 has been compiled out");
1314 ifo
->options
|= DHCPCD_IPV4
;
1317 ifo
->options
&= ~DHCPCD_IPV4
;
1320 ifo
->options
|= DHCPCD_IPV6
;
1323 ifo
->options
&= ~DHCPCD_IPV6
;
1326 ifo
->options
|= DHCPCD_ANONYMOUS
;
1327 ifo
->options
&= ~DHCPCD_HOSTNAME
;
1328 ifo
->fqdn
= FQDN_DISABLE
;
1330 /* Block everything */
1331 memset(ifo
->nomask
, 0xff, sizeof(ifo
->nomask
));
1332 memset(ifo
->nomask6
, 0xff, sizeof(ifo
->nomask6
));
1334 /* Allow the bare minimum through */
1336 del_option_mask(ifo
->nomask
, DHO_SUBNETMASK
);
1337 del_option_mask(ifo
->nomask
, DHO_CSR
);
1338 del_option_mask(ifo
->nomask
, DHO_ROUTER
);
1339 del_option_mask(ifo
->nomask
, DHO_DNSSERVER
);
1340 del_option_mask(ifo
->nomask
, DHO_DNSDOMAIN
);
1341 del_option_mask(ifo
->nomask
, DHO_BROADCAST
);
1342 del_option_mask(ifo
->nomask
, DHO_STATICROUTE
);
1343 del_option_mask(ifo
->nomask
, DHO_SERVERID
);
1344 del_option_mask(ifo
->nomask
, DHO_RENEWALTIME
);
1345 del_option_mask(ifo
->nomask
, DHO_REBINDTIME
);
1346 del_option_mask(ifo
->nomask
, DHO_DNSSEARCH
);
1350 del_option_mask(ifo
->nomask6
, D6_OPTION_DNS_SERVERS
);
1351 del_option_mask(ifo
->nomask6
, D6_OPTION_DOMAIN_LIST
);
1352 del_option_mask(ifo
->nomask6
, D6_OPTION_SOL_MAX_RT
);
1353 del_option_mask(ifo
->nomask6
, D6_OPTION_INF_MAX_RT
);
1357 case O_RANDOMISE_HWADDR
:
1358 ifo
->randomise_hwaddr
= true;
1362 while (arg
!= NULL
) {
1366 if (parse_addr(&addr
, NULL
, arg
) != 0)
1368 naddr
= reallocarray(ifo
->arping
,
1369 (size_t)ifo
->arping_len
+ 1, sizeof(in_addr_t
));
1370 if (naddr
== NULL
) {
1374 ifo
->arping
= naddr
;
1375 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1376 arg
= strskipwhite(fp
);
1381 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1383 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1384 &request
, &require
, &no
, &reject
);
1385 if (make_option_mask(d
, dl
, od
, odl
,
1386 ifo
->dstmask
, arg
, 2) != 0)
1388 if (errno
== EINVAL
)
1389 logerrx("option does not take"
1390 " an IPv4 address: %s", arg
);
1392 logerrx("unknown option: %s", arg
);
1398 free(ifo
->fallback
);
1399 ifo
->fallback
= strdup(arg
);
1400 if (ifo
->fallback
== NULL
) {
1408 if (ctx
->options
& DHCPCD_MANAGER
&& !IN_CONFIG_BLOCK(ifo
)) {
1409 logerrx("IAID must belong in an interface block");
1412 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1413 logerrx("invalid IAID %s", arg
);
1416 ifo
->options
|= DHCPCD_IAID
;
1419 ifo
->options
|= DHCPCD_IPV6RS
;
1422 ifo
->options
&= ~DHCPCD_IPV6RS
;
1425 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1427 case O_IPV6RA_AUTOCONF
:
1428 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1430 case O_IPV6RA_NOAUTOCONF
:
1431 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1434 ifo
->options
|= DHCPCD_NOALIAS
;
1438 i
= D6_OPTION_IA_NA
;
1442 i
= D6_OPTION_IA_TA
;
1447 logwarnx("%s: IA_PD not compiled in", ifname
);
1450 if (ctx
->options
& DHCPCD_MANAGER
&&
1451 !IN_CONFIG_BLOCK(ifo
))
1453 logerrx("IA PD must belong in an "
1457 i
= D6_OPTION_IA_PD
;
1460 if (ctx
->options
& DHCPCD_MANAGER
&&
1461 !IN_CONFIG_BLOCK(ifo
) && arg
)
1463 logerrx("IA with IAID must belong in an "
1467 ifo
->options
|= DHCPCD_IA_FORCED
;
1471 fp
= strskipwhite(fp
);
1474 p
= strchr(arg
, '/');
1477 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1478 logerr("invalid IAID: %s", arg
);
1483 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1484 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1485 (arg
!= NULL
&& ifo
->ia
[sl
].iaid_set
&&
1486 ifo
->ia
[sl
].ia_type
== (uint16_t)i
&&
1487 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1488 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1489 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1490 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1497 ia
= reallocarray(ifo
->ia
,
1498 ifo
->ia_len
+ 1, sizeof(*ifo
->ia
));
1504 ia
= &ifo
->ia
[ifo
->ia_len
++];
1505 ia
->ia_type
= (uint16_t)i
;
1507 ia
->iaid
[0] = iaid
[0];
1508 ia
->iaid
[1] = iaid
[1];
1509 ia
->iaid
[2] = iaid
[2];
1510 ia
->iaid
[3] = iaid
[3];
1514 if (!ia
->iaid_set
||
1516 ia
->ia_type
== D6_OPTION_IA_TA
)
1518 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1522 p
= strchr(arg
, '/');
1525 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) != 1) {
1526 logerrx("invalid AF_INET6: %s", arg
);
1527 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1529 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1530 ia
->prefix_len
= (uint8_t)strtou(p
,
1531 NULL
, 0, 8, 120, &e
);
1533 logerrx("%s: failed to convert"
1550 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1553 for (p
= fp
; p
; p
= fp
) {
1557 fp
= strskipwhite(fp
);
1559 sla
= reallocarray(ia
->sla
,
1560 ia
->sla_len
+ 1, sizeof(*ia
->sla
));
1566 sla
= &ia
->sla
[ia
->sla_len
++];
1567 np
= strchr(p
, '/');
1570 if (strlcpy(sla
->ifname
, p
,
1571 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1573 logerrx("%s: interface name too long", arg
);
1576 sla
->sla_set
= false;
1577 sla
->prefix_len
= 0;
1581 np
= strchr(p
, '/');
1585 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1586 0, 0, UINT32_MAX
, &e
);
1587 sla
->sla_set
= true;
1589 logerrx("%s: failed to convert "
1598 np
= strchr(p
, '/');
1602 sla
->prefix_len
= (uint8_t)strtou(p
,
1603 NULL
, 0, 0, 120, &e
);
1605 logerrx("%s: failed to "
1606 "convert prefix len",
1614 np
= strchr(p
, '/');
1618 sla
->suffix
= (uint64_t)strtou(p
, NULL
,
1619 0, 0, UINT64_MAX
, &e
);
1621 logerrx("%s: failed to "
1629 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1630 slap
= &ia
->sla
[sl
];
1631 if (slap
->sla_set
!= sla
->sla_set
) {
1632 logerrx("%s: cannot mix automatic "
1637 if (ia
->prefix_len
&&
1638 (sla
->prefix_len
== ia
->prefix_len
||
1639 slap
->prefix_len
== ia
->prefix_len
))
1641 logerrx("%s: cannot delegte the same"
1642 "prefix length more than once",
1646 if (!sla
->sla_set
&&
1647 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1649 logwarnx("%s: cannot specify the "
1650 "same interface twice with "
1655 if (slap
->sla_set
&& sla
->sla_set
&&
1656 slap
->sla
== sla
->sla
)
1658 logerrx("%s: cannot"
1659 " assign the same SLA %u"
1661 sla
->ifname
, sla
->sla
);
1665 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1666 ia
->sla_max
= sla
->sla
;
1674 case O_HOSTNAME_SHORT
:
1675 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1681 free(ctx
->dev_load
);
1682 ctx
->dev_load
= strdup(arg
);
1686 ifo
->options
&= ~DHCPCD_DEV
;
1689 dop
= &ifo
->dhcp_override
;
1690 dop_len
= &ifo
->dhcp_override_len
;
1694 dop
= &ifo
->nd_override
;
1695 dop_len
= &ifo
->nd_override_len
;
1700 dop
= &ifo
->dhcp6_override
;
1701 dop_len
= &ifo
->dhcp6_override_len
;
1706 dop
= &ifo
->vivso_override
;
1707 dop_len
= &ifo
->vivso_override_len
;
1709 *edop
= *ldop
= NULL
;
1714 dop
= &(*edop
)->embopts
;
1715 dop_len
= &(*edop
)->embopts_len
;
1717 dop
= &(*ldop
)->embopts
;
1718 dop_len
= &(*ldop
)->embopts_len
;
1720 logerrx("embed must be after a define "
1729 if (*ldop
== NULL
) {
1730 logerrx("encap must be after a define");
1733 dop
= &(*ldop
)->encopts
;
1734 dop_len
= &(*ldop
)->encopts_len
;
1737 /* Shared code for define, define6, embed and encap */
1740 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1745 logerrx("invalid syntax: %s", arg
);
1749 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1751 logerrx("invalid code: %s", arg
);
1754 arg
= strskipwhite(fp
);
1756 logerrx("invalid syntax");
1764 np
= strchr(arg
, ':');
1768 bp
= NULL
; /* No bitflag */
1769 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1771 logerrx("failed to convert length");
1776 bp
= strchr(arg
, '='); /* bitflag assignment */
1781 if (strcasecmp(arg
, "request") == 0) {
1783 arg
= strskipwhite(fp
);
1786 logerrx("incomplete request type");
1790 } else if (strcasecmp(arg
, "norequest") == 0) {
1792 arg
= strskipwhite(fp
);
1795 logerrx("incomplete request type");
1800 if (strcasecmp(arg
, "optional") == 0) {
1802 arg
= strskipwhite(fp
);
1805 logerrx("incomplete optional type");
1810 if (strcasecmp(arg
, "index") == 0) {
1812 arg
= strskipwhite(fp
);
1815 logerrx("incomplete index type");
1820 if (strcasecmp(arg
, "array") == 0) {
1822 arg
= strskipwhite(fp
);
1825 logerrx("incomplete array type");
1830 if (strcasecmp(arg
, "ipaddress") == 0)
1832 else if (strcasecmp(arg
, "ip6address") == 0)
1834 else if (strcasecmp(arg
, "string") == 0)
1836 else if (strcasecmp(arg
, "byte") == 0)
1838 else if (strcasecmp(arg
, "bitflags") == 0)
1840 else if (strcasecmp(arg
, "uint8") == 0)
1842 else if (strcasecmp(arg
, "int8") == 0)
1844 else if (strcasecmp(arg
, "uint16") == 0)
1846 else if (strcasecmp(arg
, "int16") == 0)
1848 else if (strcasecmp(arg
, "uint32") == 0)
1850 else if (strcasecmp(arg
, "int32") == 0)
1852 else if (strcasecmp(arg
, "flag") == 0)
1854 else if (strcasecmp(arg
, "raw") == 0)
1855 t
|= OT_STRING
| OT_RAW
;
1856 else if (strcasecmp(arg
, "ascii") == 0)
1857 t
|= OT_STRING
| OT_ASCII
;
1858 else if (strcasecmp(arg
, "domain") == 0)
1859 t
|= OT_STRING
| OT_DOMAIN
| OT_RFC1035
;
1860 else if (strcasecmp(arg
, "dname") == 0)
1861 t
|= OT_STRING
| OT_DOMAIN
;
1862 else if (strcasecmp(arg
, "binhex") == 0)
1863 t
|= OT_STRING
| OT_BINHEX
;
1864 else if (strcasecmp(arg
, "embed") == 0)
1866 else if (strcasecmp(arg
, "encap") == 0)
1868 else if (strcasecmp(arg
, "rfc3361") ==0)
1869 t
|= OT_STRING
| OT_RFC3361
;
1870 else if (strcasecmp(arg
, "rfc3442") ==0)
1871 t
|= OT_STRING
| OT_RFC3442
;
1872 else if (strcasecmp(arg
, "option") == 0)
1875 logerrx("unknown type: %s", arg
);
1878 if (l
&& !(t
& (OT_STRING
| OT_BINHEX
))) {
1879 logwarnx("ignoring length for type: %s", arg
);
1882 if (t
& OT_ARRAY
&& t
& (OT_STRING
| OT_BINHEX
) &&
1883 !(t
& (OT_RFC1035
| OT_DOMAIN
)))
1885 logwarnx("ignoring array for strings");
1888 if (t
& OT_BITFLAG
) {
1890 logwarnx("missing bitflag assignment");
1894 if (!(t
& OT_OPTION
)) {
1895 logerrx("type %s requires a variable name",
1901 arg
= strskipwhite(fp
);
1905 if (strcasecmp(arg
, "reserved")) {
1916 if (opt
!= O_EMBED
) {
1917 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1919 /* type 0 seems freshly malloced struct
1921 if (ndop
->option
== u
|| ndop
->type
== 0)
1929 ndop
= reallocarray(*dop
, *dop_len
+ 1, sizeof(**dop
));
1936 ndop
= &(*dop
)[(*dop_len
)++];
1937 ndop
->embopts
= NULL
;
1938 ndop
->embopts_len
= 0;
1939 ndop
->encopts
= NULL
;
1940 ndop
->encopts_len
= 0;
1942 free_dhcp_opt_embenc(ndop
);
1943 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1945 ndop
->len
= (size_t)l
;
1949 memcpy(ndop
->bitflags
, bp
, dl
);
1950 memset(ndop
->bitflags
+ dl
, 0,
1951 sizeof(ndop
->bitflags
) - dl
);
1953 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1954 /* Save the define for embed and encap options */
1972 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1974 logerrx("invalid code: %s", arg
);
1977 fp
= strskipwhite(fp
);
1979 s
= parse_string(NULL
, 0, fp
);
1985 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1986 logerrx("vendor class is too big");
1994 parse_string(np
, dl
, fp
);
1999 vivco
= reallocarray(ifo
->vivco
,
2000 ifo
->vivco_len
+ 1, sizeof(*ifo
->vivco
));
2001 if (vivco
== NULL
) {
2007 ifo
->vivco_en
= (uint32_t)u
;
2008 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
2010 vivco
->data
= (uint8_t *)np
;
2012 case O_AUTHPROTOCOL
:
2018 if (strcasecmp(arg
, "token") == 0)
2019 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
2020 else if (strcasecmp(arg
, "delayed") == 0)
2021 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
2022 else if (strcasecmp(arg
, "delayedrealm") == 0)
2023 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
2025 logerrx("%s: unsupported protocol", arg
);
2028 arg
= strskipwhite(fp
);
2031 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2032 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
)
2033 ifo
->auth
.protocol
= AUTH_ALG_NONE
;
2035 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
2036 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2041 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
) {
2042 np
= strchr(arg
, '/');
2044 if (fp
== NULL
|| np
< fp
)
2049 if (parse_uint32(&ifo
->auth
.token_snd_secretid
,
2051 logerrx("%s: not a number", arg
);
2053 ifo
->auth
.token_rcv_secretid
=
2054 ifo
->auth
.token_snd_secretid
;
2056 parse_uint32(&ifo
->auth
.token_rcv_secretid
,
2058 logerrx("%s: not a number", arg
);
2060 if (strcasecmp(arg
, "hmacmd5") == 0 ||
2061 strcasecmp(arg
, "hmac-md5") == 0)
2062 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
2064 logerrx("%s: unsupported algorithm", arg
);
2070 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2071 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2074 if (strcasecmp(arg
, "monocounter") == 0) {
2075 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2076 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
2077 } else if (strcasecmp(arg
, "monotonic") ==0 ||
2078 strcasecmp(arg
, "monotime") == 0)
2079 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2081 logerrx("%s: unsupported RDM", arg
);
2084 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2087 logerrx("no authentication support");
2095 logerrx("authtoken requires a realm");
2099 token
= calloc(1, sizeof(*token
));
2100 if (token
== NULL
) {
2104 if (parse_uint32(&token
->secretid
, arg
) == -1) {
2105 logerrx("%s: not a number", arg
);
2111 logerrx("authtoken requires a realm");
2115 s
= parse_string(NULL
, 0, arg
);
2117 logerr("realm_len");
2121 token
->realm_len
= (size_t)s
;
2122 token
->realm
= malloc(token
->realm_len
);
2123 if (token
->realm
== NULL
) {
2127 parse_string((char *)token
->realm
, token
->realm_len
,
2133 logerrx("authtoken requies an expiry date");
2139 np
= strchr(arg
, '"');
2143 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
2148 memset(&tm
, 0, sizeof(tm
));
2149 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
2150 logerrx("%s: invalid date time", arg
);
2153 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
2154 logerr("%s: mktime", __func__
);
2159 s
= parse_string(NULL
, 0, arg
);
2160 if (s
== -1 || s
== 0) {
2162 logerr("token_len");
2164 logerrx("authtoken requires a key");
2167 token
->key_len
= (size_t)s
;
2168 token
->key
= malloc(token
->key_len
);
2169 if (token
->key
== NULL
) {
2173 parse_string((char *)token
->key
, token
->key_len
, arg
);
2174 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
2181 logerrx("no authentication support");
2184 case O_AUTHNOTREQUIRED
:
2185 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
2188 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_WANTDHCP
| DHCPCD_IPV4
;
2191 ifo
->options
&= ~DHCPCD_DHCP
;
2194 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
2197 ifo
->options
&= ~DHCPCD_DHCP6
;
2202 /* Control group is already set by this point.
2203 * We don't need to pledge getpw either with this. */
2204 if (IN_PRIVSEP(ctx
))
2208 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
2218 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, dl
, &grp
)) ==
2223 logerrx("control_group: out of buffer");
2228 np
= realloc(p
, dl
);
2238 logerr("getgrnam_r");
2243 if (!ctx
->control_group
)
2244 logerrx("controlgroup: %s: not found", arg
);
2248 ctx
->control_group
= grp
->gr_gid
;
2251 grp
= getgrnam(arg
);
2253 if (!ctx
->control_group
)
2254 logerrx("controlgroup: %s: not found", arg
);
2257 ctx
->control_group
= grp
->gr_gid
;
2261 ifo
->options
|= DHCPCD_GATEWAY
;
2264 ifo
->options
&= ~DHCPCD_IF_UP
;
2271 np
= strskipwhite(np
);
2273 if (strcmp(arg
, "private") == 0 ||
2274 strcmp(arg
, "stableprivate") == 0 ||
2275 strcmp(arg
, "stable") == 0)
2276 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2278 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2280 if (strcmp(arg
, "token") == 0) {
2282 logerrx("slaac token: no token specified");
2289 np
= strskipwhite(np
);
2291 if (inet_pton(AF_INET6
, arg
, &ifo
->token
) != 1) {
2292 logerrx("slaac token: invalid token");
2298 (strcmp(np
, "temp") == 0 || strcmp(np
, "temporary") == 0))
2299 ifo
->options
|= DHCPCD_SLAACTEMP
;
2302 ifo
->options
|= DHCPCD_BOOTP
;
2305 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2307 case O_LASTLEASE_EXTEND
:
2308 ifo
->options
|= DHCPCD_LASTLEASE
| DHCPCD_LASTLEASE_EXTEND
;
2311 ifo
->options
|= DHCPCD_INACTIVE
;
2315 s
= parse_string((char *)ifo
->mudurl
+ 1, MUDURL_MAX_LEN
, arg
);
2320 *ifo
->mudurl
= (uint8_t)s
;
2325 ctx
->link_rcvbuf
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
2327 logerrx("failed to convert link_rcvbuf %s", arg
);
2333 ifo
->options
|= DHCPCD_CONFIGURE
;
2336 ifo
->options
&= ~DHCPCD_CONFIGURE
;
2346 logerrx("option %d requires an argument", opt
);
2353 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2354 struct if_options
*ifo
, const char *opt
, char *line
,
2355 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2359 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2360 if (!cf_options
[i
].name
||
2361 strcmp(cf_options
[i
].name
, opt
) != 0)
2364 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2365 logerrx("option requires an argument -- %s", opt
);
2369 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2373 if (!(ctx
->options
& DHCPCD_PRINT_PIDFILE
))
2374 logerrx("unknown option: %s", opt
);
2379 finish_config(struct if_options
*ifo
)
2382 /* Terminate the encapsulated options */
2383 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2385 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2386 /* We are called twice.
2387 * This should be fixed, but in the meantime, this
2388 * guard should suffice */
2389 ifo
->options
|= DHCPCD_VENDORRAW
;
2392 if (!(ifo
->options
& DHCPCD_ARP
) ||
2393 ifo
->options
& (DHCPCD_INFORM
| DHCPCD_STATIC
))
2394 ifo
->options
&= ~DHCPCD_IPV4LL
;
2396 if (!(ifo
->options
& DHCPCD_IPV4
))
2397 ifo
->options
&= ~(DHCPCD_DHCP
| DHCPCD_IPV4LL
| DHCPCD_WAITIP4
);
2399 if (!(ifo
->options
& DHCPCD_IPV6
))
2401 ~(DHCPCD_IPV6RS
| DHCPCD_DHCP6
| DHCPCD_WAITIP6
);
2403 if (!(ifo
->options
& DHCPCD_IPV6RS
))
2405 ~(DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
);
2409 default_config(struct dhcpcd_ctx
*ctx
)
2411 struct if_options
*ifo
;
2413 /* Seed our default options */
2414 if ((ifo
= calloc(1, sizeof(*ifo
))) == NULL
) {
2418 ifo
->options
|= DHCPCD_IF_UP
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2419 ifo
->timeout
= DEFAULT_TIMEOUT
;
2420 ifo
->reboot
= DEFAULT_REBOOT
;
2422 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2423 rb_tree_init(&ifo
->routes
, &rt_compare_list_ops
);
2425 TAILQ_INIT(&ifo
->auth
.tokens
);
2428 /* Inherit some global defaults */
2429 if (ctx
->options
& DHCPCD_CONFIGURE
)
2430 ifo
->options
|= DHCPCD_CONFIGURE
;
2431 if (ctx
->options
& DHCPCD_PERSISTENT
)
2432 ifo
->options
|= DHCPCD_PERSISTENT
;
2433 if (ctx
->options
& DHCPCD_SLAACPRIVATE
)
2434 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2440 read_config(struct dhcpcd_ctx
*ctx
,
2441 const char *ifname
, const char *ssid
, const char *profile
)
2443 struct if_options
*ifo
;
2444 char buf
[UDPLEN_MAX
], *bp
; /* 64k max config file size */
2445 char *line
, *option
, *p
;
2448 int skip
, have_profile
, new_block
, had_block
;
2449 #if !defined(INET) || !defined(INET6)
2451 struct dhcp_opt
*opt
;
2453 struct dhcp_opt
*ldop
, *edop
;
2455 /* Seed our default options */
2456 if ((ifo
= default_config(ctx
)) == NULL
)
2458 if (default_options
== 0) {
2459 default_options
|= DHCPCD_CONFIGURE
| DHCPCD_DAEMONISE
|
2462 skip
= socket(PF_INET
, SOCK_DGRAM
, 0);
2465 default_options
|= DHCPCD_IPV4
| DHCPCD_ARP
|
2466 DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2470 skip
= socket(PF_INET6
, SOCK_DGRAM
, 0);
2473 default_options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
|
2474 DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
|
2479 default_options
|= DHCPCD_DEV
;
2482 ifo
->options
|= default_options
;
2484 CLEAR_CONFIG_BLOCK(ifo
);
2486 vlen
= strlcpy((char *)ifo
->vendorclassid
+ 1, ctx
->vendor
,
2487 sizeof(ifo
->vendorclassid
) - 1);
2488 ifo
->vendorclassid
[0] = (uint8_t)(vlen
> 255 ? 0 : vlen
);
2490 /* Reset route order */
2493 /* Parse our embedded options file */
2494 if (ifname
== NULL
&& !(ctx
->options
& DHCPCD_PRINT_PIDFILE
)) {
2495 /* Space for initial estimates */
2496 #if defined(INET) && defined(INITDEFINES)
2497 ifo
->dhcp_override
=
2498 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2499 if (ifo
->dhcp_override
== NULL
)
2502 ifo
->dhcp_override_len
= INITDEFINES
;
2505 #if defined(INET6) && defined(INITDEFINENDS)
2507 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2508 if (ifo
->nd_override
== NULL
)
2511 ifo
->nd_override_len
= INITDEFINENDS
;
2513 #if defined(INET6) && defined(INITDEFINE6S)
2514 ifo
->dhcp6_override
=
2515 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2516 if (ifo
->dhcp6_override
== NULL
)
2519 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2522 /* Now load our embedded config */
2523 #ifdef EMBEDDED_CONFIG
2524 buflen
= dhcp_readfile(ctx
, EMBEDDED_CONFIG
, buf
, sizeof(buf
));
2526 logerr("%s: %s", __func__
, EMBEDDED_CONFIG
);
2529 if (buf
[buflen
- 1] != '\0') {
2530 if ((size_t)buflen
< sizeof(buf
) - 1)
2532 buf
[buflen
- 1] = '\0';
2535 buflen
= (ssize_t
)strlcpy(buf
, dhcpcd_embedded_conf
,
2537 if ((size_t)buflen
>= sizeof(buf
)) {
2538 logerrx("%s: embedded config too big", __func__
);
2541 /* Our embedded config is NULL terminated */
2544 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2545 option
= strsep(&line
, " \t");
2547 line
= strskipwhite(line
);
2548 /* Trim trailing whitespace */
2550 p
= line
+ strlen(line
) - 1;
2552 (*p
== ' ' || *p
== '\t') &&
2556 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2561 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2562 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2564 for (i
= 0, opt
= ifo
->dhcp_override
;
2565 i
< ifo
->dhcp_override_len
;
2567 free_dhcp_opt_embenc(opt
);
2568 free(ifo
->dhcp_override
);
2570 ifo
->dhcp_override
= NULL
;
2571 ifo
->dhcp_override_len
= 0;
2574 ctx
->nd_opts
= ifo
->nd_override
;
2575 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2577 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2578 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2581 for (i
= 0, opt
= ifo
->nd_override
;
2582 i
< ifo
->nd_override_len
;
2584 free_dhcp_opt_embenc(opt
);
2585 free(ifo
->nd_override
);
2586 for (i
= 0, opt
= ifo
->dhcp6_override
;
2587 i
< ifo
->dhcp6_override_len
;
2589 free_dhcp_opt_embenc(opt
);
2590 free(ifo
->dhcp6_override
);
2592 ifo
->nd_override
= NULL
;
2593 ifo
->nd_override_len
= 0;
2594 ifo
->dhcp6_override
= NULL
;
2595 ifo
->dhcp6_override_len
= 0;
2597 ctx
->vivso
= ifo
->vivso_override
;
2598 ctx
->vivso_len
= ifo
->vivso_override_len
;
2599 ifo
->vivso_override
= NULL
;
2600 ifo
->vivso_override_len
= 0;
2603 /* Parse our options file */
2604 buflen
= dhcp_readfile(ctx
, ctx
->cffile
, buf
, sizeof(buf
));
2606 /* dhcpcd can continue without it, but no DNS options
2607 * would be requested ... */
2608 logerr("%s: %s", __func__
, ctx
->cffile
);
2611 if (buf
[buflen
- 1] != '\0') {
2612 if ((size_t)buflen
< sizeof(buf
) - 1)
2614 buf
[buflen
- 1] = '\0';
2616 dhcp_filemtime(ctx
, ctx
->cffile
, &ifo
->mtime
);
2619 skip
= have_profile
= new_block
= 0;
2620 had_block
= ifname
== NULL
? 1 : 0;
2622 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2623 option
= strsep(&line
, " \t");
2625 line
= strskipwhite(line
);
2626 /* Trim trailing whitespace */
2628 p
= line
+ strlen(line
) - 1;
2630 (*p
== ' ' || *p
== '\t') &&
2634 if (skip
== 0 && new_block
) {
2637 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2638 SET_CONFIG_BLOCK(ifo
);
2641 /* Start of an interface block, skip if not ours */
2642 if (strcmp(option
, "interface") == 0) {
2647 /* No interface given */
2651 if (ifname
&& strcmp(line
, ifname
) == 0)
2658 n
= reallocarray(ctx
->ifcv
,
2659 (size_t)ctx
->ifcc
+ 1, sizeof(char *));
2665 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2666 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2673 /* Start of an ssid block, skip if not ours */
2674 if (strcmp(option
, "ssid") == 0) {
2676 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2682 /* Start of a profile block, skip if not ours */
2683 if (strcmp(option
, "profile") == 0) {
2685 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2692 /* Skip arping if we have selected a profile but not parsing
2694 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2699 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2702 if (profile
&& !have_profile
) {
2703 free_options(ctx
, ifo
);
2709 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2710 CLEAR_CONFIG_BLOCK(ifo
);
2716 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2717 struct if_options
*ifo
, int argc
, char **argv
)
2720 unsigned long long wait_opts
;
2727 /* Don't apply the command line wait options to each interface,
2728 * only use the dhcpcd.conf entry for that. */
2730 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2731 while ((opt
= getopt_long(argc
, argv
,
2732 ctx
->options
& DHCPCD_PRINT_PIDFILE
? NOERR_IF_OPTS
: IF_OPTS
,
2733 cf_options
, &oi
)) != -1)
2735 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2739 if (ifname
!= NULL
) {
2740 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2741 ifo
->options
|= wait_opts
;
2749 free_options(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
)
2752 #ifdef RT_FREE_ROUTE_TABLE
2753 struct interface
*ifp
;
2756 struct dhcp_opt
*opt
;
2759 struct token
*token
;
2767 while (ifo
->environ
[i
])
2768 free(ifo
->environ
[i
++]);
2773 while (ifo
->config
[i
])
2774 free(ifo
->config
[i
++]);
2778 #ifdef RT_FREE_ROUTE_TABLE
2779 /* Stupidly, we don't know the interface when creating the options.
2780 * As such, make sure each route has one so they can goto the
2782 ifp
= ctx
->ifaces
!= NULL
? TAILQ_FIRST(ctx
->ifaces
) : NULL
;
2784 RB_TREE_FOREACH(rt
, &ifo
->routes
) {
2785 if (rt
->rt_ifp
== NULL
)
2790 rt_headclear0(ctx
, &ifo
->routes
, AF_UNSPEC
);
2793 free(ifo
->blacklist
);
2794 free(ifo
->fallback
);
2796 for (opt
= ifo
->dhcp_override
;
2797 ifo
->dhcp_override_len
> 0;
2798 opt
++, ifo
->dhcp_override_len
--)
2799 free_dhcp_opt_embenc(opt
);
2800 free(ifo
->dhcp_override
);
2801 for (opt
= ifo
->nd_override
;
2802 ifo
->nd_override_len
> 0;
2803 opt
++, ifo
->nd_override_len
--)
2804 free_dhcp_opt_embenc(opt
);
2805 free(ifo
->nd_override
);
2806 for (opt
= ifo
->dhcp6_override
;
2807 ifo
->dhcp6_override_len
> 0;
2808 opt
++, ifo
->dhcp6_override_len
--)
2809 free_dhcp_opt_embenc(opt
);
2810 free(ifo
->dhcp6_override
);
2811 for (vo
= ifo
->vivco
;
2813 vo
++, ifo
->vivco_len
--)
2816 for (opt
= ifo
->vivso_override
;
2817 ifo
->vivso_override_len
> 0;
2818 opt
++, ifo
->vivso_override_len
--)
2819 free_dhcp_opt_embenc(opt
);
2820 free(ifo
->vivso_override
);
2822 #if defined(INET6) && !defined(SMALL)
2823 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2824 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2829 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2830 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2831 if (token
->realm_len
)