]>
git.ipfire.org Git - thirdparty/dhcpcd.git/blob - src/if-options.c
1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2021 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 if (match
&& strncmp(list
[i
], match
, l
) == 0) {
207 /* Append a space and the value to it */
210 n
= realloc(list
[i
], l
+ lv
+ 2);
218 memcpy(list
[i
] + l
+ 1, p
, lv
);
219 list
[i
][l
+ lv
+ 1] = '\0';
233 newlist
= reallocarray(list
, i
+ 2, sizeof(char *));
234 if (newlist
== NULL
) {
240 newlist
[i
+ 1] = NULL
;
245 #define PARSE_STRING 0
246 #define PARSE_STRING_NULL 1
247 #define PARSE_HWADDR 2
248 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
249 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
250 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
252 parse_str(char *sbuf
, size_t slen
, const char *str
, int flags
)
259 end
= str
+ strlen(str
);
260 /* If surrounded by quotes then it's a string */
268 l
= (size_t)hwaddr_aton(NULL
, str
);
269 if ((ssize_t
) l
!= -1 && l
> 1) {
274 hwaddr_aton((uint8_t *)sbuf
, str
);
279 /* Process escapes */
281 /* If processing a string on the clientid, first byte should be
282 * 0 to indicate a non hardware type */
283 if (flags
== PARSE_HWADDR
&& *str
) {
290 if (++l
> slen
&& sbuf
) {
296 switch((cmd
= *str
++)) {
317 /* Grab a hex code */
319 for (i
= 0; i
< 2; i
++) {
320 if (isxdigit((unsigned char)*str
) == 0)
324 if (c
[1] != '\0' && sbuf
) {
326 *sbuf
++ = (char)strtol(c
, NULL
, 16);
331 /* Grab an octal code */
333 for (i
= 0; i
< 3; i
++) {
334 if (*str
< '0' || *str
> '7')
338 if (c
[2] != '\0' && sbuf
) {
339 i
= (int)strtol(c
, NULL
, 8);
357 if (flags
== PARSE_STRING_NULL
) {
371 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
377 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
381 memcpy(iaid
, &narg
, sizeof(narg
));
385 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
397 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
400 return parse_iaid1(iaid
, arg
, len
, 1);
405 parse_uint32(uint32_t *i
, const char *arg
)
408 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
413 splitv(int *argc
, char **argv
, const char *arg
)
415 char **n
, **v
= argv
;
416 char *o
= strdup(arg
), *p
, *t
, *nt
;
423 while ((t
= strsep(&p
, ", "))) {
430 n
= reallocarray(v
, (size_t)(*argc
) + 1, sizeof(char *));
446 parse_addr(struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
450 if (arg
== NULL
|| *arg
== '\0') {
457 if ((p
= strchr(arg
, '/')) != NULL
) {
462 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
464 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
466 logerrx("invalid CIDR: %s", p
);
471 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
472 logerrx("invalid IP address: %s", arg
);
477 else if (net
!= NULL
&& addr
!= NULL
)
478 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
483 parse_addr(__unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
484 __unused
const char *arg
)
487 logerrx("No IPv4 support");
493 set_option_space(struct dhcpcd_ctx
*ctx
,
495 const struct dhcp_opt
**d
, size_t *dl
,
496 const struct dhcp_opt
**od
, size_t *odl
,
497 struct if_options
*ifo
,
498 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
501 #if !defined(INET) && !defined(INET6)
506 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
508 *dl
= ctx
->nd_opts_len
;
509 *od
= ifo
->nd_override
;
510 *odl
= ifo
->nd_override_len
;
511 *request
= ifo
->requestmasknd
;
512 *require
= ifo
->requiremasknd
;
514 *reject
= ifo
->rejectmasknd
;
519 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
520 *d
= ctx
->dhcp6_opts
;
521 *dl
= ctx
->dhcp6_opts_len
;
522 *od
= ifo
->dhcp6_override
;
523 *odl
= ifo
->dhcp6_override_len
;
524 *request
= ifo
->requestmask6
;
525 *require
= ifo
->requiremask6
;
527 *reject
= ifo
->rejectmask6
;
537 *dl
= ctx
->dhcp_opts_len
;
538 *od
= ifo
->dhcp_override
;
539 *odl
= ifo
->dhcp_override_len
;
546 *request
= ifo
->requestmask
;
547 *require
= ifo
->requiremask
;
549 *reject
= ifo
->rejectmask
;
553 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
560 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
561 free_dhcp_opt_embenc(o
);
563 opt
->embopts_len
= 0;
566 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
567 free_dhcp_opt_embenc(o
);
569 opt
->encopts_len
= 0;
574 strwhite(const char *s
)
579 while (*s
!= ' ' && *s
!= '\t') {
588 strskipwhite(const char *s
)
591 if (s
== NULL
|| *s
== '\0')
593 while (*s
== ' ' || *s
== '\t') {
602 /* Find the end pointer of a string. */
604 strend(const char *s
)
611 return strchr(s
, ' ');
613 for (; *s
!= '"' ; s
++) {
626 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
627 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
632 char *p
= NULL
, *bp
, *fp
, *np
;
634 struct in_addr addr
, addr2
;
637 const struct dhcp_opt
*d
, *od
;
638 uint8_t *request
, *require
, *no
, *reject
;
639 struct dhcp_opt
**dop
, *ndop
;
640 size_t *dop_len
, dl
, odl
;
654 struct if_sla
*sla
, *slap
;
664 /* Add a guard for static analysers.
665 * This should not be needed really because of the argument_required option
666 * in the options declaration above. */
667 #define ARG_REQUIRED if (arg == NULL) goto arg_required
670 case 'f': /* FALLTHROUGH */
671 case 'g': /* FALLTHROUGH */
672 case 'n': /* FALLTHROUGH */
673 case 'q': /* FALLTHROUGH */
674 case 'x': /* FALLTHROUGH */
675 case 'N': /* FALLTHROUGH */
676 case 'P': /* FALLTHROUGH */
677 case 'T': /* FALLTHROUGH */
678 case 'U': /* FALLTHROUGH */
679 case 'V': /* We need to handle non interface options */
682 ifo
->options
|= DHCPCD_BACKGROUND
;
686 if (IN_CONFIG_BLOCK(ifo
)) {
687 logerrx("%s: per interface scripts"
688 " are no longer supported",
692 if (ctx
->script
!= dhcpcd_default_script
)
694 s
= parse_nstring(NULL
, 0, arg
);
700 if (s
== -1 || (ctx
->script
= malloc(dl
)) == NULL
) {
705 s
= parse_nstring(ctx
->script
, dl
, arg
);
707 ctx
->script
[0] == '\0' ||
708 strcmp(ctx
->script
, "/dev/null") == 0)
715 ifo
->options
|= DHCPCD_DEBUG
;
719 add_environ(&ifo
->environ
, arg
, 1);
723 ifo
->options
|= DHCPCD_HOSTNAME
;
726 s
= parse_nstring(ifo
->hostname
, sizeof(ifo
->hostname
), arg
);
728 logerr("%s: hostname", __func__
);
731 if (s
!= 0 && ifo
->hostname
[0] == '.') {
732 logerrx("hostname cannot begin with .");
735 if (ifo
->hostname
[0] == '\0')
736 ifo
->options
&= ~DHCPCD_HOSTNAME
;
738 ifo
->options
|= DHCPCD_HOSTNAME
;
742 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
743 VENDORCLASSID_MAX_LEN
, arg
);
747 logerr("vendorclassid");
750 *ifo
->vendorclassid
= (uint8_t)s
;
754 /* per interface logging is not supported
755 * don't want to overide the commandline */
756 if (!IN_CONFIG_BLOCK(ifo
) && ctx
->logfile
== NULL
) {
758 ctx
->logfile
= strdup(arg
);
759 logopen(ctx
->logfile
);
763 ifo
->options
|= DHCPCD_RELEASE
;
767 if (strcmp(arg
, "-1") == 0) {
768 ifo
->leasetime
= DHCP_INFINITE_LIFETIME
;
771 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
772 0, 0, UINT32_MAX
, &e
);
774 logerrx("failed to convert leasetime %s", arg
);
780 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
782 logerrx("failed to convert metric %s", arg
);
788 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
790 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
791 &request
, &require
, &no
, &reject
);
792 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
793 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
794 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
796 logerrx("unknown option: %s", arg
);
802 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
804 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
805 &request
, &require
, &no
, &reject
);
806 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
807 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
808 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
810 logerrx("unknown option: %s", arg
);
815 ifo
->options
|= DHCPCD_PERSISTENT
;
818 if (parse_addr(&ifo
->req_addr
, NULL
, arg
) != 0)
820 ifo
->options
|= DHCPCD_REQUEST
;
821 ifo
->req_mask
.s_addr
= 0;
824 if (arg
&& *arg
!= '\0') {
825 /* Strip out a broadcast address */
826 p
= strchr(arg
, '/');
828 p
= strchr(p
+ 1, '/');
832 i
= parse_addr(&ifo
->req_addr
, &ifo
->req_mask
, arg
);
834 /* Ensure the original string is preserved */
837 i
= parse_addr(&ifo
->req_brd
, NULL
, p
);
842 ifo
->req_addr
.s_addr
= 0;
843 ifo
->req_mask
.s_addr
= 0;
845 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
846 ifo
->options
&= ~DHCPCD_STATIC
;
849 ifo
->options
|= DHCPCD_INFORM6
;
853 ifo
->timeout
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
855 logerrx("failed to convert timeout %s", arg
);
860 dl
= sizeof(ifo
->userclass
) - ifo
->userclass
[0] - 1;
861 s
= parse_string((char *)ifo
->userclass
+
862 ifo
->userclass
[0] + 2, dl
, arg
);
868 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
869 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
874 /* Some Microsoft DHCP servers expect userclass to be an
875 * opaque blob. This is not RFC 3004 compliant. */
876 s
= parse_string((char *)ifo
->userclass
+ 1,
877 sizeof(ifo
->userclass
) - 1, arg
);
879 logerr("msuserclass");
882 ifo
->userclass
[0] = (uint8_t)s
;
887 p
= strchr(arg
, ',');
889 logerrx("invalid vendor format: %s", arg
);
893 /* If vendor starts with , then it is not encapsulated */
896 s
= parse_string((char *)ifo
->vendor
+ 1,
897 VENDOR_MAX_LEN
, arg
);
902 ifo
->vendor
[0] = (uint8_t)s
;
903 ifo
->options
|= DHCPCD_VENDORRAW
;
907 /* Encapsulated vendor options */
908 if (ifo
->options
& DHCPCD_VENDORRAW
) {
909 ifo
->options
&= ~DHCPCD_VENDORRAW
;
913 /* Strip and preserve the comma */
915 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
918 logerrx("vendor option should be between"
919 " 1 and 254 inclusive");
924 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
925 if (inet_aton(arg
, &addr
) == 1) {
930 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
931 &addr
.s_addr
, sizeof(addr
.s_addr
));
932 s
= sizeof(addr
.s_addr
);
935 s
= parse_string((char *)ifo
->vendor
+
936 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
943 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
944 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
945 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
949 ifo
->options
|= DHCPCD_WAITIP
;
950 if (arg
!= NULL
&& arg
[0] != '\0') {
951 if (arg
[0] == '4' || arg
[1] == '4')
952 ifo
->options
|= DHCPCD_WAITIP4
;
953 if (arg
[0] == '6' || arg
[1] == '6')
954 ifo
->options
|= DHCPCD_WAITIP6
;
959 ifo
->reboot
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
961 logerr("failed to convert reboot %s", arg
);
967 if (!IN_CONFIG_BLOCK(ifo
))
968 ctx
->ifav
= splitv(&ctx
->ifac
, ctx
->ifav
, arg
);
971 ifo
->options
&= ~DHCPCD_ARP
;
972 /* IPv4LL requires ARP */
973 ifo
->options
&= ~DHCPCD_IPV4LL
;
976 ifo
->options
&= ~DHCPCD_DAEMONISE
;
980 /* Commas to spaces for shell */
981 while ((p
= strchr(arg
, ',')))
983 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
984 p
= malloc(sizeof(char) * dl
);
989 snprintf(p
, dl
, "skip_hooks=%s", arg
);
990 add_environ(&ifo
->environ
, p
, 0);
994 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
995 if (ifname
!= NULL
) /* duid type only a global option */
998 ctx
->duid_type
= DUID_DEFAULT
;
999 else if (strcmp(arg
, "ll") == 0)
1000 ctx
->duid_type
= DUID_LL
;
1001 else if (strcmp(arg
, "llt") == 0)
1002 ctx
->duid_type
= DUID_LLT
;
1003 else if (strcmp(arg
, "uuid") == 0)
1004 ctx
->duid_type
= DUID_UUID
;
1006 dl
= hwaddr_aton(NULL
, arg
);
1008 no
= realloc(ctx
->duid
, dl
);
1013 ctx
->duid_len
= hwaddr_aton(no
, arg
);
1019 ifo
->options
|= DHCPCD_LASTLEASE
;
1023 ifo
->fqdn
= FQDN_BOTH
;
1026 if (strcmp(arg
, "none") == 0)
1027 ifo
->fqdn
= FQDN_NONE
;
1028 else if (strcmp(arg
, "ptr") == 0)
1029 ifo
->fqdn
= FQDN_PTR
;
1030 else if (strcmp(arg
, "both") == 0)
1031 ifo
->fqdn
= FQDN_BOTH
;
1032 else if (strcmp(arg
, "disable") == 0)
1033 ifo
->fqdn
= FQDN_DISABLE
;
1035 logerrx("invalid FQDN value: %s", arg
);
1040 ifo
->options
&= ~DHCPCD_GATEWAY
;
1043 ifo
->options
|= DHCPCD_XID_HWADDR
;
1046 /* Strings have a type of 0 */;
1047 ifo
->clientid
[1] = 0;
1049 s
= parse_hwaddr((char *)ifo
->clientid
+ 1,
1050 CLIENTID_MAX_LEN
, arg
);
1057 ifo
->options
|= DHCPCD_CLIENTID
;
1058 ifo
->clientid
[0] = (uint8_t)s
;
1059 ifo
->options
&= ~DHCPCD_DUID
;
1062 ifo
->options
|= DHCPCD_BROADCAST
;
1065 ifo
->options
&= ~DHCPCD_LINK
;
1068 ifo
->options
&= ~DHCPCD_IPV4LL
;
1071 ifo
->options
|= DHCPCD_MANAGER
;
1075 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1077 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1078 &request
, &require
, &no
, &reject
);
1079 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
1080 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1081 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1083 logerrx("unknown option: %s", arg
);
1089 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1091 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1092 &request
, &require
, &no
, &reject
);
1093 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1094 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1095 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1096 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1098 logerrx("unknown option: %s", arg
);
1104 p
= strchr(arg
, '=');
1106 logerrx("static assignment required");
1110 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1111 if (parse_addr(&ifo
->req_addr
,
1112 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1116 ifo
->options
|= DHCPCD_STATIC
;
1117 ifo
->options
&= ~DHCPCD_INFORM
;
1118 } else if (strncmp(arg
, "subnet_mask=",
1119 strlen("subnet_mask=")) == 0)
1121 if (parse_addr(&ifo
->req_mask
, NULL
, p
) != 0)
1123 } else if (strncmp(arg
, "broadcast_address=",
1124 strlen("broadcast_address=")) == 0)
1126 if (parse_addr(&ifo
->req_brd
, NULL
, p
) != 0)
1128 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1129 strncmp(arg
, "static_routes=",
1130 strlen("static_routes=")) == 0 ||
1131 strncmp(arg
, "classless_static_routes=",
1132 strlen("classless_static_routes=")) == 0 ||
1133 strncmp(arg
, "ms_classless_static_routes=",
1134 strlen("ms_classless_static_routes=")) == 0)
1136 struct in_addr addr3
;
1138 fp
= np
= strwhite(p
);
1140 logerrx("all routes need a gateway");
1144 np
= strskipwhite(np
);
1145 if (parse_addr(&addr
, &addr2
, p
) == -1 ||
1146 parse_addr(&addr3
, NULL
, np
) == -1)
1152 if ((rt
= rt_new0(ctx
)) == NULL
)
1154 sa_in_init(&rt
->rt_dest
, &addr
);
1155 sa_in_init(&rt
->rt_netmask
, &addr2
);
1156 sa_in_init(&rt
->rt_gateway
, &addr3
);
1157 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1158 add_environ(&ifo
->config
, arg
, 0);
1159 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1160 if (parse_addr(&addr
, NULL
, p
) == -1)
1162 if ((rt
= rt_new0(ctx
)) == NULL
)
1164 addr2
.s_addr
= INADDR_ANY
;
1165 sa_in_init(&rt
->rt_dest
, &addr2
);
1166 sa_in_init(&rt
->rt_netmask
, &addr2
);
1167 sa_in_init(&rt
->rt_gateway
, &addr
);
1168 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1169 add_environ(&ifo
->config
, arg
, 0);
1170 } else if (strncmp(arg
, "interface_mtu=",
1171 strlen("interface_mtu=")) == 0 ||
1172 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1174 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1175 MTU_MIN
, MTU_MAX
, &e
);
1177 logerrx("invalid MTU %s", p
);
1180 } else if (strncmp(arg
, "ip6_address=", strlen("ip6_address=")) == 0) {
1181 np
= strchr(p
, '/');
1184 if ((i
= inet_pton(AF_INET6
, p
, &ifo
->req_addr6
)) == 1) {
1186 ifo
->req_prefix_len
= (uint8_t)strtou(np
,
1187 NULL
, 0, 0, 128, &e
);
1189 logerrx("%s: failed to "
1190 "convert prefix len",
1195 ifo
->req_prefix_len
= 128;
1200 logerrx("invalid AF_INET6: %s", p
);
1201 memset(&ifo
->req_addr6
, 0,
1202 sizeof(ifo
->req_addr6
));
1206 add_environ(&ifo
->config
, arg
, 1);
1209 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1211 if (strchr(arg
, '/') == NULL
)
1212 addr2
.s_addr
= INADDR_BROADCAST
;
1213 naddr
= reallocarray(ifo
->whitelist
,
1214 ifo
->whitelist_len
+ 2, sizeof(in_addr_t
));
1215 if (naddr
== NULL
) {
1219 ifo
->whitelist
= naddr
;
1220 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1221 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1224 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1226 if (strchr(arg
, '/') == NULL
)
1227 addr2
.s_addr
= INADDR_BROADCAST
;
1228 naddr
= reallocarray(ifo
->blacklist
,
1229 ifo
->blacklist_len
+ 2, sizeof(in_addr_t
));
1230 if (naddr
== NULL
) {
1234 ifo
->blacklist
= naddr
;
1235 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1236 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1240 if (!IN_CONFIG_BLOCK(ifo
))
1241 ctx
->ifdv
= splitv(&ctx
->ifdc
, ctx
->ifdv
, arg
);
1244 ifo
->options
|= DHCPCD_ONESHOT
;
1248 ifo
->options
&= ~DHCPCD_IPV6
;
1249 ifo
->options
|= DHCPCD_IPV4
;
1252 logerrx("INET has been compiled out");
1257 ifo
->options
&= ~DHCPCD_IPV4
;
1258 ifo
->options
|= DHCPCD_IPV6
;
1261 logerrx("INET6 has been compiled out");
1265 ifo
->options
|= DHCPCD_IPV4
;
1268 ifo
->options
&= ~DHCPCD_IPV4
;
1271 ifo
->options
|= DHCPCD_IPV6
;
1274 ifo
->options
&= ~DHCPCD_IPV6
;
1277 ifo
->options
|= DHCPCD_ANONYMOUS
;
1278 ifo
->options
&= ~DHCPCD_HOSTNAME
;
1279 ifo
->fqdn
= FQDN_DISABLE
;
1281 /* Block everything */
1282 memset(ifo
->nomask
, 0xff, sizeof(ifo
->nomask
));
1283 memset(ifo
->nomask6
, 0xff, sizeof(ifo
->nomask6
));
1285 /* Allow the bare minimum through */
1287 del_option_mask(ifo
->nomask
, DHO_SUBNETMASK
);
1288 del_option_mask(ifo
->nomask
, DHO_CSR
);
1289 del_option_mask(ifo
->nomask
, DHO_ROUTER
);
1290 del_option_mask(ifo
->nomask
, DHO_DNSSERVER
);
1291 del_option_mask(ifo
->nomask
, DHO_DNSDOMAIN
);
1292 del_option_mask(ifo
->nomask
, DHO_BROADCAST
);
1293 del_option_mask(ifo
->nomask
, DHO_STATICROUTE
);
1294 del_option_mask(ifo
->nomask
, DHO_SERVERID
);
1295 del_option_mask(ifo
->nomask
, DHO_RENEWALTIME
);
1296 del_option_mask(ifo
->nomask
, DHO_REBINDTIME
);
1297 del_option_mask(ifo
->nomask
, DHO_DNSSEARCH
);
1301 del_option_mask(ifo
->nomask6
, D6_OPTION_DNS_SERVERS
);
1302 del_option_mask(ifo
->nomask6
, D6_OPTION_DOMAIN_LIST
);
1303 del_option_mask(ifo
->nomask6
, D6_OPTION_SOL_MAX_RT
);
1304 del_option_mask(ifo
->nomask6
, D6_OPTION_INF_MAX_RT
);
1308 case O_RANDOMISE_HWADDR
:
1309 ifo
->randomise_hwaddr
= true;
1313 while (arg
!= NULL
) {
1317 if (parse_addr(&addr
, NULL
, arg
) != 0)
1319 naddr
= reallocarray(ifo
->arping
,
1320 (size_t)ifo
->arping_len
+ 1, sizeof(in_addr_t
));
1321 if (naddr
== NULL
) {
1325 ifo
->arping
= naddr
;
1326 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1327 arg
= strskipwhite(fp
);
1332 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1334 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1335 &request
, &require
, &no
, &reject
);
1336 if (make_option_mask(d
, dl
, od
, odl
,
1337 ifo
->dstmask
, arg
, 2) != 0)
1339 if (errno
== EINVAL
)
1340 logerrx("option does not take"
1341 " an IPv4 address: %s", arg
);
1343 logerrx("unknown option: %s", arg
);
1349 free(ifo
->fallback
);
1350 ifo
->fallback
= strdup(arg
);
1351 if (ifo
->fallback
== NULL
) {
1359 if (ctx
->options
& DHCPCD_MANAGER
&& !IN_CONFIG_BLOCK(ifo
)) {
1360 logerrx("IAID must belong in an interface block");
1363 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1364 logerrx("invalid IAID %s", arg
);
1367 ifo
->options
|= DHCPCD_IAID
;
1370 ifo
->options
|= DHCPCD_IPV6RS
;
1373 ifo
->options
&= ~DHCPCD_IPV6RS
;
1376 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1378 case O_IPV6RA_AUTOCONF
:
1379 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1381 case O_IPV6RA_NOAUTOCONF
:
1382 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1385 ifo
->options
|= DHCPCD_NOALIAS
;
1389 i
= D6_OPTION_IA_NA
;
1393 i
= D6_OPTION_IA_TA
;
1398 logwarnx("%s: IA_PD not compiled in", ifname
);
1401 if (ctx
->options
& DHCPCD_MANAGER
&&
1402 !IN_CONFIG_BLOCK(ifo
))
1404 logerrx("IA PD must belong in an "
1408 i
= D6_OPTION_IA_PD
;
1411 if (ctx
->options
& DHCPCD_MANAGER
&&
1412 !IN_CONFIG_BLOCK(ifo
) && arg
)
1414 logerrx("IA with IAID must belong in an "
1418 ifo
->options
|= DHCPCD_IA_FORCED
;
1422 fp
= strskipwhite(fp
);
1425 p
= strchr(arg
, '/');
1428 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1429 logerr("invalid IAID: %s", arg
);
1434 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1435 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1436 (arg
!= NULL
&& ifo
->ia
[sl
].iaid_set
&&
1437 ifo
->ia
[sl
].ia_type
== (uint16_t)i
&&
1438 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1439 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1440 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1441 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1448 ia
= reallocarray(ifo
->ia
,
1449 ifo
->ia_len
+ 1, sizeof(*ifo
->ia
));
1455 ia
= &ifo
->ia
[ifo
->ia_len
++];
1456 ia
->ia_type
= (uint16_t)i
;
1458 ia
->iaid
[0] = iaid
[0];
1459 ia
->iaid
[1] = iaid
[1];
1460 ia
->iaid
[2] = iaid
[2];
1461 ia
->iaid
[3] = iaid
[3];
1465 if (!ia
->iaid_set
||
1467 ia
->ia_type
== D6_OPTION_IA_TA
)
1469 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1473 p
= strchr(arg
, '/');
1476 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) != 1) {
1477 logerrx("invalid AF_INET6: %s", arg
);
1478 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1480 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1481 ia
->prefix_len
= (uint8_t)strtou(p
,
1482 NULL
, 0, 8, 120, &e
);
1484 logerrx("%s: failed to convert"
1501 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1504 for (p
= fp
; p
; p
= fp
) {
1508 fp
= strskipwhite(fp
);
1510 sla
= reallocarray(ia
->sla
,
1511 ia
->sla_len
+ 1, sizeof(*ia
->sla
));
1517 sla
= &ia
->sla
[ia
->sla_len
++];
1518 np
= strchr(p
, '/');
1521 if (strlcpy(sla
->ifname
, p
,
1522 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1524 logerrx("%s: interface name too long", arg
);
1527 sla
->sla_set
= false;
1528 sla
->prefix_len
= 0;
1532 np
= strchr(p
, '/');
1536 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1537 0, 0, UINT32_MAX
, &e
);
1538 sla
->sla_set
= true;
1540 logerrx("%s: failed to convert "
1549 np
= strchr(p
, '/');
1553 sla
->prefix_len
= (uint8_t)strtou(p
,
1554 NULL
, 0, 0, 120, &e
);
1556 logerrx("%s: failed to "
1557 "convert prefix len",
1565 np
= strchr(p
, '/');
1569 sla
->suffix
= (uint64_t)strtou(p
, NULL
,
1570 0, 0, UINT64_MAX
, &e
);
1572 logerrx("%s: failed to "
1580 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1581 slap
= &ia
->sla
[sl
];
1582 if (slap
->sla_set
!= sla
->sla_set
) {
1583 logerrx("%s: cannot mix automatic "
1588 if (ia
->prefix_len
&&
1589 (sla
->prefix_len
== ia
->prefix_len
||
1590 slap
->prefix_len
== ia
->prefix_len
))
1592 logerrx("%s: cannot delegte the same"
1593 "prefix length more than once",
1597 if (!sla
->sla_set
&&
1598 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1600 logwarnx("%s: cannot specify the "
1601 "same interface twice with "
1606 if (slap
->sla_set
&& sla
->sla_set
&&
1607 slap
->sla
== sla
->sla
)
1609 logerrx("%s: cannot"
1610 " assign the same SLA %u"
1612 sla
->ifname
, sla
->sla
);
1616 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1617 ia
->sla_max
= sla
->sla
;
1625 case O_HOSTNAME_SHORT
:
1626 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1632 free(ctx
->dev_load
);
1633 ctx
->dev_load
= strdup(arg
);
1637 ifo
->options
&= ~DHCPCD_DEV
;
1640 dop
= &ifo
->dhcp_override
;
1641 dop_len
= &ifo
->dhcp_override_len
;
1645 dop
= &ifo
->nd_override
;
1646 dop_len
= &ifo
->nd_override_len
;
1651 dop
= &ifo
->dhcp6_override
;
1652 dop_len
= &ifo
->dhcp6_override_len
;
1657 dop
= &ifo
->vivso_override
;
1658 dop_len
= &ifo
->vivso_override_len
;
1660 *edop
= *ldop
= NULL
;
1665 dop
= &(*edop
)->embopts
;
1666 dop_len
= &(*edop
)->embopts_len
;
1668 dop
= &(*ldop
)->embopts
;
1669 dop_len
= &(*ldop
)->embopts_len
;
1671 logerrx("embed must be after a define "
1680 if (*ldop
== NULL
) {
1681 logerrx("encap must be after a define");
1684 dop
= &(*ldop
)->encopts
;
1685 dop_len
= &(*ldop
)->encopts_len
;
1688 /* Shared code for define, define6, embed and encap */
1691 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1696 logerrx("invalid syntax: %s", arg
);
1700 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1702 logerrx("invalid code: %s", arg
);
1705 arg
= strskipwhite(fp
);
1707 logerrx("invalid syntax");
1715 np
= strchr(arg
, ':');
1719 bp
= NULL
; /* No bitflag */
1720 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1722 logerrx("failed to convert length");
1727 bp
= strchr(arg
, '='); /* bitflag assignment */
1732 if (strcasecmp(arg
, "request") == 0) {
1734 arg
= strskipwhite(fp
);
1737 logerrx("incomplete request type");
1741 } else if (strcasecmp(arg
, "norequest") == 0) {
1743 arg
= strskipwhite(fp
);
1746 logerrx("incomplete request type");
1751 if (strcasecmp(arg
, "optional") == 0) {
1753 arg
= strskipwhite(fp
);
1756 logerrx("incomplete optional type");
1761 if (strcasecmp(arg
, "index") == 0) {
1763 arg
= strskipwhite(fp
);
1766 logerrx("incomplete index type");
1771 if (strcasecmp(arg
, "array") == 0) {
1773 arg
= strskipwhite(fp
);
1776 logerrx("incomplete array type");
1781 if (strcasecmp(arg
, "ipaddress") == 0)
1783 else if (strcasecmp(arg
, "ip6address") == 0)
1785 else if (strcasecmp(arg
, "string") == 0)
1787 else if (strcasecmp(arg
, "byte") == 0)
1789 else if (strcasecmp(arg
, "bitflags") == 0)
1791 else if (strcasecmp(arg
, "uint8") == 0)
1793 else if (strcasecmp(arg
, "int8") == 0)
1795 else if (strcasecmp(arg
, "uint16") == 0)
1797 else if (strcasecmp(arg
, "int16") == 0)
1799 else if (strcasecmp(arg
, "uint32") == 0)
1801 else if (strcasecmp(arg
, "int32") == 0)
1803 else if (strcasecmp(arg
, "flag") == 0)
1805 else if (strcasecmp(arg
, "raw") == 0)
1806 t
|= OT_STRING
| OT_RAW
;
1807 else if (strcasecmp(arg
, "ascii") == 0)
1808 t
|= OT_STRING
| OT_ASCII
;
1809 else if (strcasecmp(arg
, "domain") == 0)
1810 t
|= OT_STRING
| OT_DOMAIN
| OT_RFC1035
;
1811 else if (strcasecmp(arg
, "dname") == 0)
1812 t
|= OT_STRING
| OT_DOMAIN
;
1813 else if (strcasecmp(arg
, "binhex") == 0)
1814 t
|= OT_STRING
| OT_BINHEX
;
1815 else if (strcasecmp(arg
, "embed") == 0)
1817 else if (strcasecmp(arg
, "encap") == 0)
1819 else if (strcasecmp(arg
, "rfc3361") ==0)
1820 t
|= OT_STRING
| OT_RFC3361
;
1821 else if (strcasecmp(arg
, "rfc3442") ==0)
1822 t
|= OT_STRING
| OT_RFC3442
;
1823 else if (strcasecmp(arg
, "option") == 0)
1826 logerrx("unknown type: %s", arg
);
1829 if (l
&& !(t
& (OT_STRING
| OT_BINHEX
))) {
1830 logwarnx("ignoring length for type: %s", arg
);
1833 if (t
& OT_ARRAY
&& t
& (OT_STRING
| OT_BINHEX
) &&
1834 !(t
& (OT_RFC1035
| OT_DOMAIN
)))
1836 logwarnx("ignoring array for strings");
1839 if (t
& OT_BITFLAG
) {
1841 logwarnx("missing bitflag assignment");
1845 if (!(t
& OT_OPTION
)) {
1846 logerrx("type %s requires a variable name",
1852 arg
= strskipwhite(fp
);
1856 if (strcasecmp(arg
, "reserved")) {
1867 if (opt
!= O_EMBED
) {
1868 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1870 /* type 0 seems freshly malloced struct
1872 if (ndop
->option
== u
|| ndop
->type
== 0)
1880 ndop
= reallocarray(*dop
, *dop_len
+ 1, sizeof(**dop
));
1887 ndop
= &(*dop
)[(*dop_len
)++];
1888 ndop
->embopts
= NULL
;
1889 ndop
->embopts_len
= 0;
1890 ndop
->encopts
= NULL
;
1891 ndop
->encopts_len
= 0;
1893 free_dhcp_opt_embenc(ndop
);
1894 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1896 ndop
->len
= (size_t)l
;
1900 memcpy(ndop
->bitflags
, bp
, dl
);
1901 memset(ndop
->bitflags
+ dl
, 0,
1902 sizeof(ndop
->bitflags
) - dl
);
1904 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1905 /* Save the define for embed and encap options */
1923 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1925 logerrx("invalid code: %s", arg
);
1928 fp
= strskipwhite(fp
);
1930 s
= parse_string(NULL
, 0, fp
);
1936 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1937 logerrx("vendor class is too big");
1945 parse_string(np
, dl
, fp
);
1950 vivco
= reallocarray(ifo
->vivco
,
1951 ifo
->vivco_len
+ 1, sizeof(*ifo
->vivco
));
1952 if (vivco
== NULL
) {
1958 ifo
->vivco_en
= (uint32_t)u
;
1959 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
1961 vivco
->data
= (uint8_t *)np
;
1963 case O_AUTHPROTOCOL
:
1969 if (strcasecmp(arg
, "token") == 0)
1970 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
1971 else if (strcasecmp(arg
, "delayed") == 0)
1972 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
1973 else if (strcasecmp(arg
, "delayedrealm") == 0)
1974 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
1976 logerrx("%s: unsupported protocol", arg
);
1979 arg
= strskipwhite(fp
);
1982 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1983 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
)
1984 ifo
->auth
.protocol
= AUTH_ALG_NONE
;
1986 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1987 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1992 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
) {
1993 np
= strchr(arg
, '/');
1995 if (fp
== NULL
|| np
< fp
)
2000 if (parse_uint32(&ifo
->auth
.token_snd_secretid
,
2002 logerrx("%s: not a number", arg
);
2004 ifo
->auth
.token_rcv_secretid
=
2005 ifo
->auth
.token_snd_secretid
;
2007 parse_uint32(&ifo
->auth
.token_rcv_secretid
,
2009 logerrx("%s: not a number", arg
);
2011 if (strcasecmp(arg
, "hmacmd5") == 0 ||
2012 strcasecmp(arg
, "hmac-md5") == 0)
2013 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
2015 logerrx("%s: unsupported algorithm", arg
);
2021 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2022 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2025 if (strcasecmp(arg
, "monocounter") == 0) {
2026 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2027 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
2028 } else if (strcasecmp(arg
, "monotonic") ==0 ||
2029 strcasecmp(arg
, "monotime") == 0)
2030 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2032 logerrx("%s: unsupported RDM", arg
);
2035 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2038 logerrx("no authentication support");
2046 logerrx("authtoken requires a realm");
2050 token
= calloc(1, sizeof(*token
));
2051 if (token
== NULL
) {
2055 if (parse_uint32(&token
->secretid
, arg
) == -1) {
2056 logerrx("%s: not a number", arg
);
2062 logerrx("authtoken requies an a key");
2066 s
= parse_string(NULL
, 0, arg
);
2068 logerr("realm_len");
2072 token
->realm_len
= (size_t)s
;
2073 token
->realm
= malloc(token
->realm_len
);
2074 if (token
->realm
== NULL
) {
2078 parse_string((char *)token
->realm
, token
->realm_len
,
2084 logerrx("authtoken requies an expiry date");
2090 np
= strchr(arg
, '"');
2094 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
2099 memset(&tm
, 0, sizeof(tm
));
2100 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
2101 logerrx("%s: invalid date time", arg
);
2104 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
2105 logerr("%s: mktime", __func__
);
2110 s
= parse_string(NULL
, 0, arg
);
2111 if (s
== -1 || s
== 0) {
2113 logerr("token_len");
2115 logerrx("authtoken needs a key");
2118 token
->key_len
= (size_t)s
;
2119 token
->key
= malloc(token
->key_len
);
2120 if (token
->key
== NULL
) {
2124 parse_string((char *)token
->key
, token
->key_len
, arg
);
2125 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
2132 logerrx("no authentication support");
2135 case O_AUTHNOTREQUIRED
:
2136 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
2139 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_WANTDHCP
| DHCPCD_IPV4
;
2142 ifo
->options
&= ~DHCPCD_DHCP
;
2145 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
2148 ifo
->options
&= ~DHCPCD_DHCP6
;
2153 /* Control group is already set by this point.
2154 * We don't need to pledge getpw either with this. */
2155 if (IN_PRIVSEP(ctx
))
2159 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
2169 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, dl
, &grp
)) ==
2174 logerrx("control_group: out of buffer");
2179 np
= realloc(p
, dl
);
2189 logerr("getgrnam_r");
2194 if (!ctx
->control_group
)
2195 logerrx("controlgroup: %s: not found", arg
);
2199 ctx
->control_group
= grp
->gr_gid
;
2202 grp
= getgrnam(arg
);
2204 if (!ctx
->control_group
)
2205 logerrx("controlgroup: %s: not found", arg
);
2208 ctx
->control_group
= grp
->gr_gid
;
2212 ifo
->options
|= DHCPCD_GATEWAY
;
2215 ifo
->options
&= ~DHCPCD_IF_UP
;
2222 np
= strskipwhite(np
);
2224 if (strcmp(arg
, "private") == 0 ||
2225 strcmp(arg
, "stableprivate") == 0 ||
2226 strcmp(arg
, "stable") == 0)
2227 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2229 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2231 (strcmp(np
, "temp") == 0 || strcmp(np
, "temporary") == 0))
2232 ifo
->options
|= DHCPCD_SLAACTEMP
;
2235 ifo
->options
|= DHCPCD_BOOTP
;
2238 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2240 case O_LASTLEASE_EXTEND
:
2241 ifo
->options
|= DHCPCD_LASTLEASE
| DHCPCD_LASTLEASE_EXTEND
;
2244 ifo
->options
|= DHCPCD_INACTIVE
;
2248 s
= parse_string((char *)ifo
->mudurl
+ 1, MUDURL_MAX_LEN
, arg
);
2253 *ifo
->mudurl
= (uint8_t)s
;
2258 ctx
->link_rcvbuf
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
2260 logerrx("failed to convert link_rcvbuf %s", arg
);
2266 ifo
->options
|= DHCPCD_CONFIGURE
;
2269 ifo
->options
&= ~DHCPCD_CONFIGURE
;
2279 logerrx("option %d requires an argument", opt
);
2286 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2287 struct if_options
*ifo
, const char *opt
, char *line
,
2288 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2292 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2293 if (!cf_options
[i
].name
||
2294 strcmp(cf_options
[i
].name
, opt
) != 0)
2297 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2298 logerrx("option requires an argument -- %s", opt
);
2302 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2306 if (!(ctx
->options
& DHCPCD_PRINT_PIDFILE
))
2307 logerrx("unknown option: %s", opt
);
2312 finish_config(struct if_options
*ifo
)
2315 /* Terminate the encapsulated options */
2316 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2318 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2319 /* We are called twice.
2320 * This should be fixed, but in the meantime, this
2321 * guard should suffice */
2322 ifo
->options
|= DHCPCD_VENDORRAW
;
2325 if (!(ifo
->options
& DHCPCD_ARP
) ||
2326 ifo
->options
& (DHCPCD_INFORM
| DHCPCD_STATIC
))
2327 ifo
->options
&= ~DHCPCD_IPV4LL
;
2329 if (!(ifo
->options
& DHCPCD_IPV4
))
2330 ifo
->options
&= ~(DHCPCD_DHCP
| DHCPCD_IPV4LL
| DHCPCD_WAITIP4
);
2332 if (!(ifo
->options
& DHCPCD_IPV6
))
2334 ~(DHCPCD_IPV6RS
| DHCPCD_DHCP6
| DHCPCD_WAITIP6
);
2336 if (!(ifo
->options
& DHCPCD_IPV6RS
))
2338 ~(DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
);
2342 default_config(struct dhcpcd_ctx
*ctx
)
2344 struct if_options
*ifo
;
2346 /* Seed our default options */
2347 if ((ifo
= calloc(1, sizeof(*ifo
))) == NULL
) {
2351 ifo
->options
|= DHCPCD_IF_UP
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2352 ifo
->timeout
= DEFAULT_TIMEOUT
;
2353 ifo
->reboot
= DEFAULT_REBOOT
;
2355 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2356 rb_tree_init(&ifo
->routes
, &rt_compare_list_ops
);
2358 TAILQ_INIT(&ifo
->auth
.tokens
);
2361 /* Inherit some global defaults */
2362 if (ctx
->options
& DHCPCD_CONFIGURE
)
2363 ifo
->options
|= DHCPCD_CONFIGURE
;
2364 if (ctx
->options
& DHCPCD_PERSISTENT
)
2365 ifo
->options
|= DHCPCD_PERSISTENT
;
2366 if (ctx
->options
& DHCPCD_SLAACPRIVATE
)
2367 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2373 read_config(struct dhcpcd_ctx
*ctx
,
2374 const char *ifname
, const char *ssid
, const char *profile
)
2376 struct if_options
*ifo
;
2377 char buf
[UDPLEN_MAX
], *bp
; /* 64k max config file size */
2378 char *line
, *option
, *p
;
2381 int skip
, have_profile
, new_block
, had_block
;
2382 #if !defined(INET) || !defined(INET6)
2384 struct dhcp_opt
*opt
;
2386 struct dhcp_opt
*ldop
, *edop
;
2388 /* Seed our default options */
2389 if ((ifo
= default_config(ctx
)) == NULL
)
2391 if (default_options
== 0) {
2392 default_options
|= DHCPCD_CONFIGURE
| DHCPCD_DAEMONISE
|
2395 skip
= socket(PF_INET
, SOCK_DGRAM
, 0);
2398 default_options
|= DHCPCD_IPV4
| DHCPCD_ARP
|
2399 DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2403 skip
= socket(PF_INET6
, SOCK_DGRAM
, 0);
2406 default_options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
|
2407 DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
|
2412 default_options
|= DHCPCD_DEV
;
2415 ifo
->options
|= default_options
;
2417 CLEAR_CONFIG_BLOCK(ifo
);
2419 vlen
= strlcpy((char *)ifo
->vendorclassid
+ 1, ctx
->vendor
,
2420 sizeof(ifo
->vendorclassid
) - 1);
2421 ifo
->vendorclassid
[0] = (uint8_t)(vlen
> 255 ? 0 : vlen
);
2423 /* Reset route order */
2426 /* Parse our embedded options file */
2427 if (ifname
== NULL
&& !(ctx
->options
& DHCPCD_PRINT_PIDFILE
)) {
2428 /* Space for initial estimates */
2429 #if defined(INET) && defined(INITDEFINES)
2430 ifo
->dhcp_override
=
2431 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2432 if (ifo
->dhcp_override
== NULL
)
2435 ifo
->dhcp_override_len
= INITDEFINES
;
2438 #if defined(INET6) && defined(INITDEFINENDS)
2440 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2441 if (ifo
->nd_override
== NULL
)
2444 ifo
->nd_override_len
= INITDEFINENDS
;
2446 #if defined(INET6) && defined(INITDEFINE6S)
2447 ifo
->dhcp6_override
=
2448 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2449 if (ifo
->dhcp6_override
== NULL
)
2452 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2455 /* Now load our embedded config */
2456 #ifdef EMBEDDED_CONFIG
2457 buflen
= dhcp_readfile(ctx
, EMBEDDED_CONFIG
, buf
, sizeof(buf
));
2459 logerr("%s: %s", __func__
, EMBEDDED_CONFIG
);
2462 if (buf
[buflen
- 1] != '\0') {
2463 if ((size_t)buflen
< sizeof(buf
) - 1)
2465 buf
[buflen
- 1] = '\0';
2468 buflen
= (ssize_t
)strlcpy(buf
, dhcpcd_embedded_conf
,
2470 if ((size_t)buflen
>= sizeof(buf
)) {
2471 logerrx("%s: embedded config too big", __func__
);
2474 /* Our embedded config is NULL terminated */
2477 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2478 option
= strsep(&line
, " \t");
2480 line
= strskipwhite(line
);
2481 /* Trim trailing whitespace */
2483 p
= line
+ strlen(line
) - 1;
2485 (*p
== ' ' || *p
== '\t') &&
2489 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2494 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2495 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2497 for (i
= 0, opt
= ifo
->dhcp_override
;
2498 i
< ifo
->dhcp_override_len
;
2500 free_dhcp_opt_embenc(opt
);
2501 free(ifo
->dhcp_override
);
2503 ifo
->dhcp_override
= NULL
;
2504 ifo
->dhcp_override_len
= 0;
2507 ctx
->nd_opts
= ifo
->nd_override
;
2508 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2510 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2511 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2514 for (i
= 0, opt
= ifo
->nd_override
;
2515 i
< ifo
->nd_override_len
;
2517 free_dhcp_opt_embenc(opt
);
2518 free(ifo
->nd_override
);
2519 for (i
= 0, opt
= ifo
->dhcp6_override
;
2520 i
< ifo
->dhcp6_override_len
;
2522 free_dhcp_opt_embenc(opt
);
2523 free(ifo
->dhcp6_override
);
2525 ifo
->nd_override
= NULL
;
2526 ifo
->nd_override_len
= 0;
2527 ifo
->dhcp6_override
= NULL
;
2528 ifo
->dhcp6_override_len
= 0;
2530 ctx
->vivso
= ifo
->vivso_override
;
2531 ctx
->vivso_len
= ifo
->vivso_override_len
;
2532 ifo
->vivso_override
= NULL
;
2533 ifo
->vivso_override_len
= 0;
2536 /* Parse our options file */
2537 buflen
= dhcp_readfile(ctx
, ctx
->cffile
, buf
, sizeof(buf
));
2539 /* dhcpcd can continue without it, but no DNS options
2540 * would be requested ... */
2541 logerr("%s: %s", __func__
, ctx
->cffile
);
2544 if (buf
[buflen
- 1] != '\0') {
2545 if ((size_t)buflen
< sizeof(buf
) - 1)
2547 buf
[buflen
- 1] = '\0';
2549 dhcp_filemtime(ctx
, ctx
->cffile
, &ifo
->mtime
);
2552 skip
= have_profile
= new_block
= 0;
2553 had_block
= ifname
== NULL
? 1 : 0;
2555 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2556 option
= strsep(&line
, " \t");
2558 line
= strskipwhite(line
);
2559 /* Trim trailing whitespace */
2561 p
= line
+ strlen(line
) - 1;
2563 (*p
== ' ' || *p
== '\t') &&
2567 if (skip
== 0 && new_block
) {
2570 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2571 SET_CONFIG_BLOCK(ifo
);
2574 /* Start of an interface block, skip if not ours */
2575 if (strcmp(option
, "interface") == 0) {
2580 /* No interface given */
2584 if (ifname
&& strcmp(line
, ifname
) == 0)
2591 n
= reallocarray(ctx
->ifcv
,
2592 (size_t)ctx
->ifcc
+ 1, sizeof(char *));
2598 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2599 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2606 /* Start of an ssid block, skip if not ours */
2607 if (strcmp(option
, "ssid") == 0) {
2609 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2615 /* Start of a profile block, skip if not ours */
2616 if (strcmp(option
, "profile") == 0) {
2618 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2625 /* Skip arping if we have selected a profile but not parsing
2627 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2632 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2635 if (profile
&& !have_profile
) {
2636 free_options(ctx
, ifo
);
2642 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2643 CLEAR_CONFIG_BLOCK(ifo
);
2649 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2650 struct if_options
*ifo
, int argc
, char **argv
)
2653 unsigned long long wait_opts
;
2660 /* Don't apply the command line wait options to each interface,
2661 * only use the dhcpcd.conf entry for that. */
2663 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2664 while ((opt
= getopt_long(argc
, argv
,
2665 ctx
->options
& DHCPCD_PRINT_PIDFILE
? NOERR_IF_OPTS
: IF_OPTS
,
2666 cf_options
, &oi
)) != -1)
2668 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2672 if (ifname
!= NULL
) {
2673 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2674 ifo
->options
|= wait_opts
;
2682 free_options(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
)
2685 #ifdef RT_FREE_ROUTE_TABLE
2686 struct interface
*ifp
;
2689 struct dhcp_opt
*opt
;
2692 struct token
*token
;
2700 while (ifo
->environ
[i
])
2701 free(ifo
->environ
[i
++]);
2706 while (ifo
->config
[i
])
2707 free(ifo
->config
[i
++]);
2711 #ifdef RT_FREE_ROUTE_TABLE
2712 /* Stupidly, we don't know the interface when creating the options.
2713 * As such, make sure each route has one so they can goto the
2715 ifp
= ctx
->ifaces
!= NULL
? TAILQ_FIRST(ctx
->ifaces
) : NULL
;
2717 RB_TREE_FOREACH(rt
, &ifo
->routes
) {
2718 if (rt
->rt_ifp
== NULL
)
2723 rt_headclear0(ctx
, &ifo
->routes
, AF_UNSPEC
);
2726 free(ifo
->blacklist
);
2727 free(ifo
->fallback
);
2729 for (opt
= ifo
->dhcp_override
;
2730 ifo
->dhcp_override_len
> 0;
2731 opt
++, ifo
->dhcp_override_len
--)
2732 free_dhcp_opt_embenc(opt
);
2733 free(ifo
->dhcp_override
);
2734 for (opt
= ifo
->nd_override
;
2735 ifo
->nd_override_len
> 0;
2736 opt
++, ifo
->nd_override_len
--)
2737 free_dhcp_opt_embenc(opt
);
2738 free(ifo
->nd_override
);
2739 for (opt
= ifo
->dhcp6_override
;
2740 ifo
->dhcp6_override_len
> 0;
2741 opt
++, ifo
->dhcp6_override_len
--)
2742 free_dhcp_opt_embenc(opt
);
2743 free(ifo
->dhcp6_override
);
2744 for (vo
= ifo
->vivco
;
2746 vo
++, ifo
->vivco_len
--)
2749 for (opt
= ifo
->vivso_override
;
2750 ifo
->vivso_override_len
> 0;
2751 opt
++, ifo
->vivso_override_len
--)
2752 free_dhcp_opt_embenc(opt
);
2753 free(ifo
->vivso_override
);
2755 #if defined(INET6) && !defined(SMALL)
2756 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2757 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2762 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2763 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2764 if (token
->realm_len
)