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 {"arp_persistdefence", no_argument
, NULL
, O_ARP_PERSISTDEFENCE
},
172 {"request_time", required_argument
, NULL
, O_REQUEST_TIME
},
173 {"fallback_time", required_argument
, NULL
, O_FALLBACK_TIME
},
174 {"ipv4ll_time", required_argument
, NULL
, O_IPV4LL_TIME
},
175 {NULL
, 0, NULL
, '\0'}
179 add_environ(char ***array
, const char *value
, int uniq
)
181 char **newlist
, **list
= *array
;
183 char *match
= NULL
, *p
, *n
;
185 match
= strdup(value
);
190 p
= strchr(match
, '=');
192 logerrx("%s: no assignment: %s", __func__
, value
);
199 while (list
&& list
[i
]) {
200 /* We know that it must contain '=' due to the above test */
201 size_t listl
= (size_t)(strchr(list
[i
], '=') - list
[i
]);
203 if (l
== listl
&& strncmp(list
[i
], match
, l
) == 0) {
214 /* Append a space and the value to it */
217 n
= realloc(list
[i
], l
+ lv
+ 2);
225 memcpy(list
[i
] + l
+ 1, p
, lv
);
226 list
[i
][l
+ lv
+ 1] = '\0';
240 newlist
= reallocarray(list
, i
+ 2, sizeof(char *));
241 if (newlist
== NULL
) {
247 newlist
[i
+ 1] = NULL
;
252 #define PARSE_STRING 0
253 #define PARSE_STRING_NULL 1
254 #define PARSE_HWADDR 2
255 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
256 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
257 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
259 parse_str(char *sbuf
, size_t slen
, const char *str
, int flags
)
266 end
= str
+ strlen(str
);
267 /* If surrounded by quotes then it's a string */
275 l
= (size_t)hwaddr_aton(NULL
, str
);
277 if ((ssize_t
)l
== -1) {
287 hwaddr_aton((uint8_t *)sbuf
, str
);
292 /* Process escapes */
294 /* If processing a string on the clientid, first byte should be
295 * 0 to indicate a non hardware type */
296 if (flags
== PARSE_HWADDR
&& *str
) {
303 if (++l
> slen
&& sbuf
) {
309 switch((cmd
= *str
++)) {
330 /* Grab a hex code */
332 for (i
= 0; i
< 2; i
++) {
333 if (isxdigit((unsigned char)*str
) == 0)
340 *sbuf
++ = (char)strtol(c
, NULL
, 16);
345 /* Grab an octal code */
347 for (i
= 0; i
< 3; i
++) {
348 if (*str
< '0' || *str
> '7')
353 i
= (int)strtol(c
, NULL
, 8);
372 if (flags
== PARSE_STRING_NULL
) {
386 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
392 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
396 memcpy(iaid
, &narg
, sizeof(narg
));
400 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
412 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
415 return parse_iaid1(iaid
, arg
, len
, 1);
420 parse_uint32(uint32_t *i
, const char *arg
)
423 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
428 splitv(int *argc
, char **argv
, const char *arg
)
430 char **n
, **v
= argv
;
431 char *o
= strdup(arg
), *p
, *t
, *nt
;
438 while ((t
= strsep(&p
, ", "))) {
445 n
= reallocarray(v
, (size_t)(*argc
) + 1, sizeof(char *));
461 parse_addr(struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
465 if (arg
== NULL
|| *arg
== '\0') {
472 if ((p
= strchr(arg
, '/')) != NULL
) {
477 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
479 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
481 logerrx("invalid CIDR: %s", p
);
486 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
487 logerrx("invalid IP address: %s", arg
);
492 else if (net
!= NULL
&& addr
!= NULL
)
493 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
498 parse_addr(__unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
499 __unused
const char *arg
)
502 logerrx("No IPv4 support");
508 set_option_space(struct dhcpcd_ctx
*ctx
,
510 const struct dhcp_opt
**d
, size_t *dl
,
511 const struct dhcp_opt
**od
, size_t *odl
,
512 struct if_options
*ifo
,
513 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
516 #if !defined(INET) && !defined(INET6)
521 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
523 *dl
= ctx
->nd_opts_len
;
524 *od
= ifo
->nd_override
;
525 *odl
= ifo
->nd_override_len
;
526 *request
= ifo
->requestmasknd
;
527 *require
= ifo
->requiremasknd
;
529 *reject
= ifo
->rejectmasknd
;
534 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
535 *d
= ctx
->dhcp6_opts
;
536 *dl
= ctx
->dhcp6_opts_len
;
537 *od
= ifo
->dhcp6_override
;
538 *odl
= ifo
->dhcp6_override_len
;
539 *request
= ifo
->requestmask6
;
540 *require
= ifo
->requiremask6
;
542 *reject
= ifo
->rejectmask6
;
552 *dl
= ctx
->dhcp_opts_len
;
553 *od
= ifo
->dhcp_override
;
554 *odl
= ifo
->dhcp_override_len
;
561 *request
= ifo
->requestmask
;
562 *require
= ifo
->requiremask
;
564 *reject
= ifo
->rejectmask
;
568 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
575 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
576 free_dhcp_opt_embenc(o
);
578 opt
->embopts_len
= 0;
581 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
582 free_dhcp_opt_embenc(o
);
584 opt
->encopts_len
= 0;
589 strwhite(const char *s
)
594 while (*s
!= ' ' && *s
!= '\t') {
603 strskipwhite(const char *s
)
606 if (s
== NULL
|| *s
== '\0')
608 while (*s
== ' ' || *s
== '\t') {
617 /* Find the end pointer of a string. */
619 strend(const char *s
)
626 return strchr(s
, ' ');
628 for (; *s
!= '"' ; s
++) {
641 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
642 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
647 char *p
= NULL
, *bp
, *fp
, *np
;
649 struct in_addr addr
, addr2
;
652 const struct dhcp_opt
*d
, *od
;
653 uint8_t *request
, *require
, *no
, *reject
;
654 struct dhcp_opt
**dop
, *ndop
;
655 size_t *dop_len
, dl
, odl
;
669 struct if_sla
*sla
, *slap
;
679 /* Add a guard for static analysers.
680 * This should not be needed really because of the argument_required option
681 * in the options declaration above. */
682 #define ARG_REQUIRED if (arg == NULL) goto arg_required
685 case 'f': /* FALLTHROUGH */
686 case 'g': /* FALLTHROUGH */
687 case 'n': /* FALLTHROUGH */
688 case 'q': /* FALLTHROUGH */
689 case 'x': /* FALLTHROUGH */
690 case 'N': /* FALLTHROUGH */
691 case 'P': /* FALLTHROUGH */
692 case 'T': /* FALLTHROUGH */
693 case 'U': /* FALLTHROUGH */
694 case 'V': /* We need to handle non interface options */
697 ifo
->options
|= DHCPCD_BACKGROUND
;
701 if (IN_CONFIG_BLOCK(ifo
)) {
702 logerrx("%s: per interface scripts"
703 " are no longer supported",
707 if (ctx
->script
!= dhcpcd_default_script
)
709 s
= parse_nstring(NULL
, 0, arg
);
715 if (s
== -1 || (ctx
->script
= malloc(dl
)) == NULL
) {
720 s
= parse_nstring(ctx
->script
, dl
, arg
);
722 ctx
->script
[0] == '\0' ||
723 strcmp(ctx
->script
, "/dev/null") == 0)
730 ifo
->options
|= DHCPCD_DEBUG
;
734 add_environ(&ifo
->environ
, arg
, 1);
738 ifo
->options
|= DHCPCD_HOSTNAME
;
741 s
= parse_nstring(ifo
->hostname
, sizeof(ifo
->hostname
), arg
);
743 logerr("%s: hostname", __func__
);
746 if (s
!= 0 && ifo
->hostname
[0] == '.') {
747 logerrx("hostname cannot begin with .");
750 if (ifo
->hostname
[0] == '\0')
751 ifo
->options
&= ~DHCPCD_HOSTNAME
;
753 ifo
->options
|= DHCPCD_HOSTNAME
;
757 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
758 VENDORCLASSID_MAX_LEN
, arg
);
762 logerr("vendorclassid");
765 *ifo
->vendorclassid
= (uint8_t)s
;
769 /* per interface logging is not supported
770 * don't want to overide the commandline */
771 if (!IN_CONFIG_BLOCK(ifo
) && ctx
->logfile
== NULL
) {
773 ctx
->logfile
= strdup(arg
);
774 logopen(ctx
->logfile
);
778 ifo
->options
|= DHCPCD_RELEASE
;
782 if (strcmp(arg
, "-1") == 0) {
783 ifo
->leasetime
= DHCP_INFINITE_LIFETIME
;
786 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
787 0, 0, UINT32_MAX
, &e
);
789 logerrx("failed to convert leasetime %s", arg
);
795 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
797 logerrx("failed to convert metric %s", arg
);
803 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
805 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
806 &request
, &require
, &no
, &reject
);
807 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
808 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
809 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
811 logerrx("unknown option: %s", arg
);
817 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
819 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
820 &request
, &require
, &no
, &reject
);
821 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
822 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
823 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
825 logerrx("unknown option: %s", arg
);
830 ifo
->options
|= DHCPCD_PERSISTENT
;
833 if (parse_addr(&ifo
->req_addr
, NULL
, arg
) != 0)
835 ifo
->options
|= DHCPCD_REQUEST
;
836 ifo
->req_mask
.s_addr
= 0;
839 if (arg
&& *arg
!= '\0') {
840 /* Strip out a broadcast address */
841 p
= strchr(arg
, '/');
843 p
= strchr(p
+ 1, '/');
847 i
= parse_addr(&ifo
->req_addr
, &ifo
->req_mask
, arg
);
849 /* Ensure the original string is preserved */
852 i
= parse_addr(&ifo
->req_brd
, NULL
, p
);
857 ifo
->req_addr
.s_addr
= 0;
858 ifo
->req_mask
.s_addr
= 0;
860 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
861 ifo
->options
&= ~DHCPCD_STATIC
;
864 ifo
->options
|= DHCPCD_INFORM6
;
868 ifo
->timeout
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
870 logerrx("failed to convert timeout %s", arg
);
875 dl
= sizeof(ifo
->userclass
) - ifo
->userclass
[0] - 1;
876 s
= parse_string((char *)ifo
->userclass
+
877 ifo
->userclass
[0] + 2, dl
, arg
);
883 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
884 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
889 /* Some Microsoft DHCP servers expect userclass to be an
890 * opaque blob. This is not RFC 3004 compliant. */
891 s
= parse_string((char *)ifo
->userclass
+ 1,
892 sizeof(ifo
->userclass
) - 1, arg
);
894 logerr("msuserclass");
897 ifo
->userclass
[0] = (uint8_t)s
;
902 p
= strchr(arg
, ',');
904 logerrx("invalid vendor format: %s", arg
);
908 /* If vendor starts with , then it is not encapsulated */
911 s
= parse_string((char *)ifo
->vendor
+ 1,
912 VENDOR_MAX_LEN
, arg
);
917 ifo
->vendor
[0] = (uint8_t)s
;
918 ifo
->options
|= DHCPCD_VENDORRAW
;
922 /* Encapsulated vendor options */
923 if (ifo
->options
& DHCPCD_VENDORRAW
) {
924 ifo
->options
&= ~DHCPCD_VENDORRAW
;
928 /* Strip and preserve the comma */
930 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
933 logerrx("vendor option should be between"
934 " 1 and 254 inclusive");
939 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
940 if (inet_aton(arg
, &addr
) == 1) {
945 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
946 &addr
.s_addr
, sizeof(addr
.s_addr
));
947 s
= sizeof(addr
.s_addr
);
950 s
= parse_string((char *)ifo
->vendor
+
951 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
958 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
959 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
960 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
964 ifo
->options
|= DHCPCD_WAITIP
;
966 // Generally it's --waitip=46, but some expect
967 // --waitip="4 6" to work as well.
968 // It's easier to allow it rather than have confusing docs.
969 while (p
!= NULL
&& p
[0] != '\0') {
970 if (p
[0] == '4' || p
[1] == '4')
971 ifo
->options
|= DHCPCD_WAITIP4
;
972 if (p
[0] == '6' || p
[1] == '6')
973 ifo
->options
|= DHCPCD_WAITIP6
;
974 p
= strskipwhite(++p
);
979 ifo
->reboot
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
981 logerr("failed to convert reboot %s", arg
);
987 if (!IN_CONFIG_BLOCK(ifo
))
988 ctx
->ifav
= splitv(&ctx
->ifac
, ctx
->ifav
, arg
);
991 ifo
->options
&= ~DHCPCD_ARP
;
992 /* IPv4LL requires ARP */
993 ifo
->options
&= ~DHCPCD_IPV4LL
;
996 ifo
->options
&= ~DHCPCD_DAEMONISE
;
1000 /* Commas to spaces for shell */
1001 while ((p
= strchr(arg
, ',')))
1003 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
1004 p
= malloc(sizeof(char) * dl
);
1009 snprintf(p
, dl
, "skip_hooks=%s", arg
);
1010 add_environ(&ifo
->environ
, p
, 0);
1014 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
1015 if (ifname
!= NULL
) /* duid type only a global option */
1018 ctx
->duid_type
= DUID_DEFAULT
;
1019 else if (strcmp(arg
, "ll") == 0)
1020 ctx
->duid_type
= DUID_LL
;
1021 else if (strcmp(arg
, "llt") == 0)
1022 ctx
->duid_type
= DUID_LLT
;
1023 else if (strcmp(arg
, "uuid") == 0)
1024 ctx
->duid_type
= DUID_UUID
;
1026 dl
= hwaddr_aton(NULL
, arg
);
1028 no
= realloc(ctx
->duid
, dl
);
1033 ctx
->duid_len
= hwaddr_aton(no
, arg
);
1039 ifo
->options
|= DHCPCD_LASTLEASE
;
1043 ifo
->fqdn
= FQDN_BOTH
;
1046 if (strcmp(arg
, "none") == 0)
1047 ifo
->fqdn
= FQDN_NONE
;
1048 else if (strcmp(arg
, "ptr") == 0)
1049 ifo
->fqdn
= FQDN_PTR
;
1050 else if (strcmp(arg
, "both") == 0)
1051 ifo
->fqdn
= FQDN_BOTH
;
1052 else if (strcmp(arg
, "disable") == 0)
1053 ifo
->fqdn
= FQDN_DISABLE
;
1055 logerrx("invalid FQDN value: %s", arg
);
1060 ifo
->options
&= ~DHCPCD_GATEWAY
;
1063 ifo
->options
|= DHCPCD_XID_HWADDR
;
1066 /* Strings have a type of 0 */;
1067 ifo
->clientid
[1] = 0;
1069 s
= parse_hwaddr((char *)ifo
->clientid
+ 1,
1070 CLIENTID_MAX_LEN
, arg
);
1077 ifo
->options
|= DHCPCD_CLIENTID
;
1078 ifo
->clientid
[0] = (uint8_t)s
;
1079 ifo
->options
&= ~DHCPCD_DUID
;
1082 ifo
->options
|= DHCPCD_BROADCAST
;
1085 ifo
->options
&= ~DHCPCD_LINK
;
1088 ifo
->options
&= ~DHCPCD_IPV4LL
;
1091 ifo
->options
|= DHCPCD_MANAGER
;
1095 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1097 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1098 &request
, &require
, &no
, &reject
);
1099 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
1100 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1101 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1103 logerrx("unknown option: %s", arg
);
1109 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1111 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1112 &request
, &require
, &no
, &reject
);
1113 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1114 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1115 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1116 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1118 logerrx("unknown option: %s", arg
);
1124 p
= strchr(arg
, '=');
1126 logerrx("static assignment required");
1129 p
= strskipwhite(++p
);
1130 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1132 ifo
->options
&= ~DHCPCD_STATIC
;
1133 ifo
->req_addr
.s_addr
= INADDR_ANY
;
1136 if (parse_addr(&ifo
->req_addr
,
1137 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1141 ifo
->options
|= DHCPCD_STATIC
;
1142 ifo
->options
&= ~DHCPCD_INFORM
;
1143 } else if (strncmp(arg
, "subnet_mask=",
1144 strlen("subnet_mask=")) == 0)
1147 ifo
->req_mask
.s_addr
= INADDR_ANY
;
1150 if (parse_addr(&ifo
->req_mask
, NULL
, p
) != 0)
1152 } else if (strncmp(arg
, "broadcast_address=",
1153 strlen("broadcast_address=")) == 0)
1156 ifo
->req_brd
.s_addr
= INADDR_ANY
;
1159 if (parse_addr(&ifo
->req_brd
, NULL
, p
) != 0)
1161 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1162 strncmp(arg
, "static_routes=",
1163 strlen("static_routes=")) == 0 ||
1164 strncmp(arg
, "classless_static_routes=",
1165 strlen("classless_static_routes=")) == 0 ||
1166 strncmp(arg
, "ms_classless_static_routes=",
1167 strlen("ms_classless_static_routes=")) == 0)
1169 struct in_addr addr3
;
1172 rt_headclear(&ifo
->routes
, AF_INET
);
1173 add_environ(&ifo
->config
, arg
, 1);
1177 fp
= np
= strwhite(p
);
1179 logerrx("all routes need a gateway");
1183 np
= strskipwhite(np
);
1184 if (parse_addr(&addr
, &addr2
, p
) == -1 ||
1185 parse_addr(&addr3
, NULL
, np
) == -1)
1191 if ((rt
= rt_new0(ctx
)) == NULL
)
1193 sa_in_init(&rt
->rt_dest
, &addr
);
1194 sa_in_init(&rt
->rt_netmask
, &addr2
);
1195 sa_in_init(&rt
->rt_gateway
, &addr3
);
1196 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1197 add_environ(&ifo
->config
, arg
, 0);
1198 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1200 rt_headclear(&ifo
->routes
, AF_INET
);
1201 add_environ(&ifo
->config
, arg
, 1);
1204 if (parse_addr(&addr
, NULL
, p
) == -1)
1206 if ((rt
= rt_new0(ctx
)) == NULL
)
1208 addr2
.s_addr
= INADDR_ANY
;
1209 sa_in_init(&rt
->rt_dest
, &addr2
);
1210 sa_in_init(&rt
->rt_netmask
, &addr2
);
1211 sa_in_init(&rt
->rt_gateway
, &addr
);
1212 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1213 add_environ(&ifo
->config
, arg
, 0);
1214 } else if (strncmp(arg
, "interface_mtu=",
1215 strlen("interface_mtu=")) == 0 ||
1216 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1220 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1221 MTU_MIN
, MTU_MAX
, &e
);
1223 logerrx("invalid MTU %s", p
);
1226 } else if (strncmp(arg
, "ip6_address=", strlen("ip6_address=")) == 0) {
1228 memset(&ifo
->req_addr6
, 0,
1229 sizeof(ifo
->req_addr6
));
1233 np
= strchr(p
, '/');
1236 if ((i
= inet_pton(AF_INET6
, p
, &ifo
->req_addr6
)) == 1) {
1238 ifo
->req_prefix_len
= (uint8_t)strtou(np
,
1239 NULL
, 0, 0, 128, &e
);
1241 logerrx("%s: failed to "
1242 "convert prefix len",
1247 ifo
->req_prefix_len
= 128;
1252 logerrx("invalid AF_INET6: %s", p
);
1253 memset(&ifo
->req_addr6
, 0,
1254 sizeof(ifo
->req_addr6
));
1258 add_environ(&ifo
->config
, arg
, p
== NULL
? 1 : 0);
1262 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1264 if (strchr(arg
, '/') == NULL
)
1265 addr2
.s_addr
= INADDR_BROADCAST
;
1266 naddr
= reallocarray(ifo
->whitelist
,
1267 ifo
->whitelist_len
+ 2, sizeof(in_addr_t
));
1268 if (naddr
== NULL
) {
1272 ifo
->whitelist
= naddr
;
1273 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1274 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1277 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1279 if (strchr(arg
, '/') == NULL
)
1280 addr2
.s_addr
= INADDR_BROADCAST
;
1281 naddr
= reallocarray(ifo
->blacklist
,
1282 ifo
->blacklist_len
+ 2, sizeof(in_addr_t
));
1283 if (naddr
== NULL
) {
1287 ifo
->blacklist
= naddr
;
1288 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1289 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1293 if (!IN_CONFIG_BLOCK(ifo
))
1294 ctx
->ifdv
= splitv(&ctx
->ifdc
, ctx
->ifdv
, arg
);
1297 ifo
->options
|= DHCPCD_ONESHOT
;
1301 ifo
->options
&= ~DHCPCD_IPV6
;
1302 ifo
->options
|= DHCPCD_IPV4
;
1305 logerrx("INET has been compiled out");
1310 ifo
->options
&= ~DHCPCD_IPV4
;
1311 ifo
->options
|= DHCPCD_IPV6
;
1314 logerrx("INET6 has been compiled out");
1318 ifo
->options
|= DHCPCD_IPV4
;
1321 ifo
->options
&= ~DHCPCD_IPV4
;
1324 ifo
->options
|= DHCPCD_IPV6
;
1327 ifo
->options
&= ~DHCPCD_IPV6
;
1330 ifo
->options
|= DHCPCD_ANONYMOUS
;
1331 ifo
->options
&= ~DHCPCD_HOSTNAME
;
1332 ifo
->fqdn
= FQDN_DISABLE
;
1334 /* Block everything */
1335 memset(ifo
->nomask
, 0xff, sizeof(ifo
->nomask
));
1336 memset(ifo
->nomask6
, 0xff, sizeof(ifo
->nomask6
));
1338 /* Allow the bare minimum through */
1340 del_option_mask(ifo
->nomask
, DHO_SUBNETMASK
);
1341 del_option_mask(ifo
->nomask
, DHO_CSR
);
1342 del_option_mask(ifo
->nomask
, DHO_ROUTER
);
1343 del_option_mask(ifo
->nomask
, DHO_DNSSERVER
);
1344 del_option_mask(ifo
->nomask
, DHO_DNSDOMAIN
);
1345 del_option_mask(ifo
->nomask
, DHO_BROADCAST
);
1346 del_option_mask(ifo
->nomask
, DHO_STATICROUTE
);
1347 del_option_mask(ifo
->nomask
, DHO_SERVERID
);
1348 del_option_mask(ifo
->nomask
, DHO_RENEWALTIME
);
1349 del_option_mask(ifo
->nomask
, DHO_REBINDTIME
);
1350 del_option_mask(ifo
->nomask
, DHO_DNSSEARCH
);
1354 del_option_mask(ifo
->nomask6
, D6_OPTION_DNS_SERVERS
);
1355 del_option_mask(ifo
->nomask6
, D6_OPTION_DOMAIN_LIST
);
1356 del_option_mask(ifo
->nomask6
, D6_OPTION_SOL_MAX_RT
);
1357 del_option_mask(ifo
->nomask6
, D6_OPTION_INF_MAX_RT
);
1361 case O_RANDOMISE_HWADDR
:
1362 ifo
->randomise_hwaddr
= true;
1366 while (arg
!= NULL
) {
1370 if (parse_addr(&addr
, NULL
, arg
) != 0)
1372 naddr
= reallocarray(ifo
->arping
,
1373 (size_t)ifo
->arping_len
+ 1, sizeof(in_addr_t
));
1374 if (naddr
== NULL
) {
1378 ifo
->arping
= naddr
;
1379 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1380 arg
= strskipwhite(fp
);
1385 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1387 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1388 &request
, &require
, &no
, &reject
);
1389 if (make_option_mask(d
, dl
, od
, odl
,
1390 ifo
->dstmask
, arg
, 2) != 0)
1392 if (errno
== EINVAL
)
1393 logerrx("option does not take"
1394 " an IPv4 address: %s", arg
);
1396 logerrx("unknown option: %s", arg
);
1402 free(ifo
->fallback
);
1403 ifo
->fallback
= strdup(arg
);
1404 if (ifo
->fallback
== NULL
) {
1412 if (ctx
->options
& DHCPCD_MANAGER
&& !IN_CONFIG_BLOCK(ifo
)) {
1413 logerrx("IAID must belong in an interface block");
1416 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1417 logerrx("invalid IAID %s", arg
);
1420 ifo
->options
|= DHCPCD_IAID
;
1423 ifo
->options
|= DHCPCD_IPV6RS
;
1426 ifo
->options
&= ~DHCPCD_IPV6RS
;
1429 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1431 case O_IPV6RA_AUTOCONF
:
1432 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1434 case O_IPV6RA_NOAUTOCONF
:
1435 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1438 ifo
->options
|= DHCPCD_NOALIAS
;
1442 i
= D6_OPTION_IA_NA
;
1446 i
= D6_OPTION_IA_TA
;
1451 logwarnx("%s: IA_PD not compiled in", ifname
);
1454 if (ctx
->options
& DHCPCD_MANAGER
&&
1455 !IN_CONFIG_BLOCK(ifo
))
1457 logerrx("IA PD must belong in an "
1461 i
= D6_OPTION_IA_PD
;
1464 if (ctx
->options
& DHCPCD_MANAGER
&&
1465 !IN_CONFIG_BLOCK(ifo
) && arg
)
1467 logerrx("IA with IAID must belong in an "
1471 ifo
->options
|= DHCPCD_IA_FORCED
;
1475 fp
= strskipwhite(fp
);
1478 p
= strchr(arg
, '/');
1481 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1482 logerr("invalid IAID: %s", arg
);
1487 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1488 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1489 (arg
!= NULL
&& ifo
->ia
[sl
].iaid_set
&&
1490 ifo
->ia
[sl
].ia_type
== (uint16_t)i
&&
1491 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1492 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1493 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1494 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1501 ia
= reallocarray(ifo
->ia
,
1502 ifo
->ia_len
+ 1, sizeof(*ifo
->ia
));
1508 ia
= &ifo
->ia
[ifo
->ia_len
++];
1509 ia
->ia_type
= (uint16_t)i
;
1511 ia
->iaid
[0] = iaid
[0];
1512 ia
->iaid
[1] = iaid
[1];
1513 ia
->iaid
[2] = iaid
[2];
1514 ia
->iaid
[3] = iaid
[3];
1518 if (!ia
->iaid_set
||
1520 ia
->ia_type
== D6_OPTION_IA_TA
)
1522 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1526 p
= strchr(arg
, '/');
1529 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) != 1) {
1530 logerrx("invalid AF_INET6: %s", arg
);
1531 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1533 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1534 ia
->prefix_len
= (uint8_t)strtou(p
,
1535 NULL
, 0, 8, 120, &e
);
1537 logerrx("%s: failed to convert"
1554 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1557 for (p
= fp
; p
; p
= fp
) {
1561 fp
= strskipwhite(fp
);
1563 sla
= reallocarray(ia
->sla
,
1564 ia
->sla_len
+ 1, sizeof(*ia
->sla
));
1570 sla
= &ia
->sla
[ia
->sla_len
++];
1571 np
= strchr(p
, '/');
1574 if (strlcpy(sla
->ifname
, p
,
1575 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1577 logerrx("%s: interface name too long", arg
);
1580 sla
->sla_set
= false;
1581 sla
->prefix_len
= 0;
1585 np
= strchr(p
, '/');
1589 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1590 0, 0, UINT32_MAX
, &e
);
1591 sla
->sla_set
= true;
1593 logerrx("%s: failed to convert "
1602 np
= strchr(p
, '/');
1606 sla
->prefix_len
= (uint8_t)strtou(p
,
1607 NULL
, 0, 0, 120, &e
);
1609 logerrx("%s: failed to "
1610 "convert prefix len",
1618 np
= strchr(p
, '/');
1622 sla
->suffix
= (uint64_t)strtou(p
, NULL
,
1623 0, 0, UINT64_MAX
, &e
);
1625 logerrx("%s: failed to "
1633 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1634 slap
= &ia
->sla
[sl
];
1635 if (slap
->sla_set
!= sla
->sla_set
) {
1636 logerrx("%s: cannot mix automatic "
1641 if (ia
->prefix_len
&&
1642 (sla
->prefix_len
== ia
->prefix_len
||
1643 slap
->prefix_len
== ia
->prefix_len
))
1645 logerrx("%s: cannot delegte the same"
1646 "prefix length more than once",
1650 if (!sla
->sla_set
&&
1651 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1653 logwarnx("%s: cannot specify the "
1654 "same interface twice with "
1659 if (slap
->sla_set
&& sla
->sla_set
&&
1660 slap
->sla
== sla
->sla
)
1662 logerrx("%s: cannot"
1663 " assign the same SLA %u"
1665 sla
->ifname
, sla
->sla
);
1669 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1670 ia
->sla_max
= sla
->sla
;
1678 case O_HOSTNAME_SHORT
:
1679 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1685 free(ctx
->dev_load
);
1686 ctx
->dev_load
= strdup(arg
);
1690 ifo
->options
&= ~DHCPCD_DEV
;
1693 dop
= &ifo
->dhcp_override
;
1694 dop_len
= &ifo
->dhcp_override_len
;
1698 dop
= &ifo
->nd_override
;
1699 dop_len
= &ifo
->nd_override_len
;
1704 dop
= &ifo
->dhcp6_override
;
1705 dop_len
= &ifo
->dhcp6_override_len
;
1710 dop
= &ifo
->vivso_override
;
1711 dop_len
= &ifo
->vivso_override_len
;
1713 *edop
= *ldop
= NULL
;
1718 dop
= &(*edop
)->embopts
;
1719 dop_len
= &(*edop
)->embopts_len
;
1721 dop
= &(*ldop
)->embopts
;
1722 dop_len
= &(*ldop
)->embopts_len
;
1724 logerrx("embed must be after a define "
1733 if (*ldop
== NULL
) {
1734 logerrx("encap must be after a define");
1737 dop
= &(*ldop
)->encopts
;
1738 dop_len
= &(*ldop
)->encopts_len
;
1741 /* Shared code for define, define6, embed and encap */
1744 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1749 logerrx("invalid syntax: %s", arg
);
1753 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1755 logerrx("invalid code: %s", arg
);
1758 arg
= strskipwhite(fp
);
1760 logerrx("invalid syntax");
1768 np
= strchr(arg
, ':');
1772 bp
= NULL
; /* No bitflag */
1773 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1775 logerrx("failed to convert length");
1780 bp
= strchr(arg
, '='); /* bitflag assignment */
1785 if (strcasecmp(arg
, "request") == 0) {
1787 arg
= strskipwhite(fp
);
1790 logerrx("incomplete request type");
1794 } else if (strcasecmp(arg
, "norequest") == 0) {
1796 arg
= strskipwhite(fp
);
1799 logerrx("incomplete request type");
1804 if (strcasecmp(arg
, "optional") == 0) {
1806 arg
= strskipwhite(fp
);
1809 logerrx("incomplete optional type");
1814 if (strcasecmp(arg
, "index") == 0) {
1816 arg
= strskipwhite(fp
);
1819 logerrx("incomplete index type");
1824 if (strcasecmp(arg
, "array") == 0) {
1826 arg
= strskipwhite(fp
);
1829 logerrx("incomplete array type");
1834 if (strcasecmp(arg
, "ipaddress") == 0)
1836 else if (strcasecmp(arg
, "ip6address") == 0)
1838 else if (strcasecmp(arg
, "string") == 0)
1840 else if (strcasecmp(arg
, "uri") == 0)
1842 else if (strcasecmp(arg
, "byte") == 0)
1844 else if (strcasecmp(arg
, "bitflags") == 0)
1846 else if (strcasecmp(arg
, "uint8") == 0)
1848 else if (strcasecmp(arg
, "int8") == 0)
1850 else if (strcasecmp(arg
, "uint16") == 0)
1852 else if (strcasecmp(arg
, "int16") == 0)
1854 else if (strcasecmp(arg
, "uint32") == 0)
1856 else if (strcasecmp(arg
, "int32") == 0)
1858 else if (strcasecmp(arg
, "flag") == 0)
1860 else if (strcasecmp(arg
, "raw") == 0)
1861 t
|= OT_STRING
| OT_RAW
;
1862 else if (strcasecmp(arg
, "ascii") == 0)
1863 t
|= OT_STRING
| OT_ASCII
;
1864 else if (strcasecmp(arg
, "domain") == 0)
1865 t
|= OT_STRING
| OT_DOMAIN
| OT_RFC1035
;
1866 else if (strcasecmp(arg
, "dname") == 0)
1867 t
|= OT_STRING
| OT_DOMAIN
;
1868 else if (strcasecmp(arg
, "binhex") == 0)
1869 t
|= OT_STRING
| OT_BINHEX
;
1870 else if (strcasecmp(arg
, "embed") == 0)
1872 else if (strcasecmp(arg
, "encap") == 0)
1874 else if (strcasecmp(arg
, "rfc3361") ==0)
1875 t
|= OT_STRING
| OT_RFC3361
;
1876 else if (strcasecmp(arg
, "rfc3442") ==0)
1877 t
|= OT_STRING
| OT_RFC3442
;
1878 else if (strcasecmp(arg
, "option") == 0)
1881 logerrx("unknown type: %s", arg
);
1884 if (l
&& !(t
& (OT_STRING
| OT_BINHEX
))) {
1885 logwarnx("ignoring length for type: %s", arg
);
1888 if (t
& OT_ARRAY
&& t
& (OT_STRING
| OT_BINHEX
) &&
1889 !(t
& (OT_RFC1035
| OT_DOMAIN
)))
1891 logwarnx("ignoring array for strings");
1894 if (t
& OT_BITFLAG
) {
1896 logwarnx("missing bitflag assignment");
1900 if (!(t
& OT_OPTION
)) {
1901 logerrx("type %s requires a variable name",
1907 arg
= strskipwhite(fp
);
1911 if (strcasecmp(arg
, "reserved")) {
1922 if (opt
!= O_EMBED
) {
1923 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1925 /* type 0 seems freshly malloced struct
1927 if (ndop
->option
== u
|| ndop
->type
== 0)
1935 ndop
= reallocarray(*dop
, *dop_len
+ 1, sizeof(**dop
));
1942 ndop
= &(*dop
)[(*dop_len
)++];
1943 ndop
->embopts
= NULL
;
1944 ndop
->embopts_len
= 0;
1945 ndop
->encopts
= NULL
;
1946 ndop
->encopts_len
= 0;
1948 free_dhcp_opt_embenc(ndop
);
1949 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1951 ndop
->len
= (size_t)l
;
1955 memcpy(ndop
->bitflags
, bp
, dl
);
1956 memset(ndop
->bitflags
+ dl
, 0,
1957 sizeof(ndop
->bitflags
) - dl
);
1959 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1960 /* Save the define for embed and encap options */
1978 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1980 logerrx("invalid code: %s", arg
);
1983 fp
= strskipwhite(fp
);
1985 s
= parse_string(NULL
, 0, fp
);
1991 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1992 logerrx("vendor class is too big");
2000 parse_string(np
, dl
, fp
);
2005 vivco
= reallocarray(ifo
->vivco
,
2006 ifo
->vivco_len
+ 1, sizeof(*ifo
->vivco
));
2007 if (vivco
== NULL
) {
2013 ifo
->vivco_en
= (uint32_t)u
;
2014 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
2016 vivco
->data
= (uint8_t *)np
;
2018 case O_AUTHPROTOCOL
:
2024 if (strcasecmp(arg
, "token") == 0)
2025 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
2026 else if (strcasecmp(arg
, "delayed") == 0)
2027 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
2028 else if (strcasecmp(arg
, "delayedrealm") == 0)
2029 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
2031 logerrx("%s: unsupported protocol", arg
);
2034 arg
= strskipwhite(fp
);
2037 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2038 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
)
2039 ifo
->auth
.protocol
= AUTH_ALG_NONE
;
2041 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
2042 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2047 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
) {
2048 np
= strchr(arg
, '/');
2050 if (fp
== NULL
|| np
< fp
)
2055 if (parse_uint32(&ifo
->auth
.token_snd_secretid
,
2057 logerrx("%s: not a number", arg
);
2059 ifo
->auth
.token_rcv_secretid
=
2060 ifo
->auth
.token_snd_secretid
;
2062 parse_uint32(&ifo
->auth
.token_rcv_secretid
,
2064 logerrx("%s: not a number", arg
);
2066 if (strcasecmp(arg
, "hmacmd5") == 0 ||
2067 strcasecmp(arg
, "hmac-md5") == 0)
2068 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
2070 logerrx("%s: unsupported algorithm", arg
);
2076 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2077 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2080 if (strcasecmp(arg
, "monocounter") == 0) {
2081 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2082 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
2083 } else if (strcasecmp(arg
, "monotonic") ==0 ||
2084 strcasecmp(arg
, "monotime") == 0)
2085 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2087 logerrx("%s: unsupported RDM", arg
);
2090 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2093 logerrx("no authentication support");
2101 logerrx("authtoken requires a realm");
2105 token
= calloc(1, sizeof(*token
));
2106 if (token
== NULL
) {
2110 if (parse_uint32(&token
->secretid
, arg
) == -1) {
2111 logerrx("%s: not a number", arg
);
2117 logerrx("authtoken requires a realm");
2121 s
= parse_string(NULL
, 0, arg
);
2123 logerr("realm_len");
2127 token
->realm_len
= (size_t)s
;
2128 token
->realm
= malloc(token
->realm_len
);
2129 if (token
->realm
== NULL
) {
2133 parse_string((char *)token
->realm
, token
->realm_len
,
2139 logerrx("authtoken requies an expiry date");
2145 np
= strchr(arg
, '"');
2149 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
2154 memset(&tm
, 0, sizeof(tm
));
2155 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
2156 logerrx("%s: invalid date time", arg
);
2159 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
2160 logerr("%s: mktime", __func__
);
2165 s
= parse_string(NULL
, 0, arg
);
2166 if (s
== -1 || s
== 0) {
2168 logerr("token_len");
2170 logerrx("authtoken requires a key");
2173 token
->key_len
= (size_t)s
;
2174 token
->key
= malloc(token
->key_len
);
2175 if (token
->key
== NULL
) {
2179 parse_string((char *)token
->key
, token
->key_len
, arg
);
2180 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
2187 logerrx("no authentication support");
2190 case O_AUTHNOTREQUIRED
:
2191 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
2194 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_WANTDHCP
| DHCPCD_IPV4
;
2197 ifo
->options
&= ~DHCPCD_DHCP
;
2200 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
2203 ifo
->options
&= ~DHCPCD_DHCP6
;
2208 /* Control group is already set by this point.
2209 * We don't need to pledge getpw either with this. */
2210 if (IN_PRIVSEP(ctx
))
2214 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
2224 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, dl
, &grp
)) ==
2229 logerrx("control_group: out of buffer");
2234 np
= realloc(p
, dl
);
2244 logerr("getgrnam_r");
2249 if (!ctx
->control_group
)
2250 logerrx("controlgroup: %s: not found", arg
);
2254 ctx
->control_group
= grp
->gr_gid
;
2257 grp
= getgrnam(arg
);
2259 if (!ctx
->control_group
)
2260 logerrx("controlgroup: %s: not found", arg
);
2263 ctx
->control_group
= grp
->gr_gid
;
2267 ifo
->options
|= DHCPCD_GATEWAY
;
2270 ifo
->options
&= ~DHCPCD_IF_UP
;
2277 np
= strskipwhite(np
);
2279 if (strcmp(arg
, "private") == 0 ||
2280 strcmp(arg
, "stableprivate") == 0 ||
2281 strcmp(arg
, "stable") == 0)
2282 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2284 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2286 if (strcmp(arg
, "token") == 0) {
2288 logerrx("slaac token: no token specified");
2295 np
= strskipwhite(np
);
2297 if (inet_pton(AF_INET6
, arg
, &ifo
->token
) != 1) {
2298 logerrx("slaac token: invalid token");
2304 (strcmp(np
, "temp") == 0 || strcmp(np
, "temporary") == 0))
2305 ifo
->options
|= DHCPCD_SLAACTEMP
;
2308 ifo
->options
|= DHCPCD_BOOTP
;
2311 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2313 case O_LASTLEASE_EXTEND
:
2314 ifo
->options
|= DHCPCD_LASTLEASE
| DHCPCD_LASTLEASE_EXTEND
;
2317 ifo
->options
|= DHCPCD_INACTIVE
;
2321 s
= parse_string((char *)ifo
->mudurl
+ 1, MUDURL_MAX_LEN
, arg
);
2326 *ifo
->mudurl
= (uint8_t)s
;
2331 ctx
->link_rcvbuf
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
2333 logerrx("failed to convert link_rcvbuf %s", arg
);
2339 ifo
->options
|= DHCPCD_CONFIGURE
;
2342 ifo
->options
&= ~DHCPCD_CONFIGURE
;
2344 case O_ARP_PERSISTDEFENCE
:
2345 ifo
->options
|= DHCPCD_ARP_PERSISTDEFENCE
;
2347 case O_REQUEST_TIME
:
2350 (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
2352 logerrx("invalid request time: %s", arg
);
2357 case O_FALLBACK_TIME
:
2360 (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
2362 logerrx("invalid fallback time: %s", arg
);
2369 (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
2371 logerrx("invalid ipv4ll time: %s", arg
);
2384 logerrx("option %d requires an argument", opt
);
2391 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2392 struct if_options
*ifo
, const char *opt
, char *line
,
2393 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2397 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2398 if (!cf_options
[i
].name
||
2399 strcmp(cf_options
[i
].name
, opt
) != 0)
2402 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2403 logerrx("option requires an argument -- %s", opt
);
2407 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2411 if (!(ctx
->options
& DHCPCD_PRINT_PIDFILE
))
2412 logerrx("unknown option: %s", opt
);
2417 finish_config(struct if_options
*ifo
)
2420 /* Terminate the encapsulated options */
2421 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2423 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2424 /* We are called twice.
2425 * This should be fixed, but in the meantime, this
2426 * guard should suffice */
2427 ifo
->options
|= DHCPCD_VENDORRAW
;
2430 if (!(ifo
->options
& DHCPCD_ARP
) ||
2431 ifo
->options
& (DHCPCD_INFORM
| DHCPCD_STATIC
))
2432 ifo
->options
&= ~DHCPCD_IPV4LL
;
2434 if (!(ifo
->options
& DHCPCD_IPV4
))
2435 ifo
->options
&= ~(DHCPCD_DHCP
| DHCPCD_IPV4LL
| DHCPCD_WAITIP4
);
2437 if (!(ifo
->options
& DHCPCD_IPV6
))
2439 ~(DHCPCD_IPV6RS
| DHCPCD_DHCP6
| DHCPCD_WAITIP6
);
2441 if (!(ifo
->options
& DHCPCD_IPV6RS
))
2443 ~(DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
);
2446 static struct if_options
*
2447 default_config(struct dhcpcd_ctx
*ctx
)
2449 struct if_options
*ifo
;
2451 /* Seed our default options */
2452 if ((ifo
= calloc(1, sizeof(*ifo
))) == NULL
) {
2456 ifo
->options
|= DHCPCD_IF_UP
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2457 ifo
->timeout
= DEFAULT_TIMEOUT
;
2458 ifo
->reboot
= DEFAULT_REBOOT
;
2459 ifo
->request_time
= DEFAULT_REQUEST
;
2461 ifo
->fallback_time
= DEFAULT_FALLBACK
;
2462 ifo
->ipv4ll_time
= DEFAULT_IPV4LL
;
2465 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2466 rb_tree_init(&ifo
->routes
, &rt_compare_list_ops
);
2468 TAILQ_INIT(&ifo
->auth
.tokens
);
2471 /* Inherit some global defaults */
2472 if (ctx
->options
& DHCPCD_CONFIGURE
)
2473 ifo
->options
|= DHCPCD_CONFIGURE
;
2474 if (ctx
->options
& DHCPCD_PERSISTENT
)
2475 ifo
->options
|= DHCPCD_PERSISTENT
;
2476 if (ctx
->options
& DHCPCD_SLAACPRIVATE
)
2477 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2483 read_config(struct dhcpcd_ctx
*ctx
,
2484 const char *ifname
, const char *ssid
, const char *profile
)
2486 struct if_options
*ifo
;
2487 char buf
[UDPLEN_MAX
], *bp
; /* 64k max config file size */
2488 char *line
, *option
, *p
;
2491 int skip
, have_profile
, new_block
, had_block
;
2492 #if !defined(INET) || !defined(INET6)
2494 struct dhcp_opt
*opt
;
2496 struct dhcp_opt
*ldop
, *edop
;
2498 /* Seed our default options */
2499 if ((ifo
= default_config(ctx
)) == NULL
)
2501 if (default_options
== 0) {
2502 default_options
|= DHCPCD_CONFIGURE
| DHCPCD_DAEMONISE
|
2505 skip
= xsocket(PF_INET
, SOCK_DGRAM
, 0);
2508 default_options
|= DHCPCD_IPV4
| DHCPCD_ARP
|
2509 DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2513 skip
= xsocket(PF_INET6
, SOCK_DGRAM
, 0);
2516 default_options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
|
2517 DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
|
2522 default_options
|= DHCPCD_DEV
;
2525 ifo
->options
|= default_options
;
2527 CLEAR_CONFIG_BLOCK(ifo
);
2529 vlen
= strlcpy((char *)ifo
->vendorclassid
+ 1, ctx
->vendor
,
2530 sizeof(ifo
->vendorclassid
) - 1);
2531 ifo
->vendorclassid
[0] = (uint8_t)(vlen
> 255 ? 0 : vlen
);
2533 /* Reset route order */
2536 /* Parse our embedded options file */
2537 if (ifname
== NULL
&& !(ctx
->options
& DHCPCD_PRINT_PIDFILE
)) {
2538 /* Space for initial estimates */
2539 #if defined(INET) && defined(INITDEFINES)
2540 ifo
->dhcp_override
=
2541 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2542 if (ifo
->dhcp_override
== NULL
)
2545 ifo
->dhcp_override_len
= INITDEFINES
;
2548 #if defined(INET6) && defined(INITDEFINENDS)
2550 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2551 if (ifo
->nd_override
== NULL
)
2554 ifo
->nd_override_len
= INITDEFINENDS
;
2556 #if defined(INET6) && defined(INITDEFINE6S)
2557 ifo
->dhcp6_override
=
2558 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2559 if (ifo
->dhcp6_override
== NULL
)
2562 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2565 /* Now load our embedded config */
2566 #ifdef EMBEDDED_CONFIG
2567 buflen
= dhcp_readfile(ctx
, EMBEDDED_CONFIG
, buf
, sizeof(buf
));
2569 logerr("%s: %s", __func__
, EMBEDDED_CONFIG
);
2572 if (buf
[buflen
- 1] != '\0') {
2573 if ((size_t)buflen
< sizeof(buf
) - 1)
2575 buf
[buflen
- 1] = '\0';
2578 buflen
= (ssize_t
)strlcpy(buf
, dhcpcd_embedded_conf
,
2580 if ((size_t)buflen
>= sizeof(buf
)) {
2581 logerrx("%s: embedded config too big", __func__
);
2584 /* Our embedded config is NULL terminated */
2587 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2588 option
= strsep(&line
, " \t");
2590 line
= strskipwhite(line
);
2591 /* Trim trailing whitespace */
2593 p
= line
+ strlen(line
) - 1;
2595 (*p
== ' ' || *p
== '\t') &&
2599 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2604 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2605 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2607 for (i
= 0, opt
= ifo
->dhcp_override
;
2608 i
< ifo
->dhcp_override_len
;
2610 free_dhcp_opt_embenc(opt
);
2611 free(ifo
->dhcp_override
);
2613 ifo
->dhcp_override
= NULL
;
2614 ifo
->dhcp_override_len
= 0;
2617 ctx
->nd_opts
= ifo
->nd_override
;
2618 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2620 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2621 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2624 for (i
= 0, opt
= ifo
->nd_override
;
2625 i
< ifo
->nd_override_len
;
2627 free_dhcp_opt_embenc(opt
);
2628 free(ifo
->nd_override
);
2629 for (i
= 0, opt
= ifo
->dhcp6_override
;
2630 i
< ifo
->dhcp6_override_len
;
2632 free_dhcp_opt_embenc(opt
);
2633 free(ifo
->dhcp6_override
);
2635 ifo
->nd_override
= NULL
;
2636 ifo
->nd_override_len
= 0;
2637 ifo
->dhcp6_override
= NULL
;
2638 ifo
->dhcp6_override_len
= 0;
2640 ctx
->vivso
= ifo
->vivso_override
;
2641 ctx
->vivso_len
= ifo
->vivso_override_len
;
2642 ifo
->vivso_override
= NULL
;
2643 ifo
->vivso_override_len
= 0;
2646 /* Parse our options file */
2647 buflen
= dhcp_readfile(ctx
, ctx
->cffile
, buf
, sizeof(buf
));
2649 /* dhcpcd can continue without it, but no DNS options
2650 * would be requested ... */
2651 logerr("%s: %s", __func__
, ctx
->cffile
);
2654 if (buf
[buflen
- 1] != '\0') {
2655 if ((size_t)buflen
< sizeof(buf
) - 1)
2657 buf
[buflen
- 1] = '\0';
2659 dhcp_filemtime(ctx
, ctx
->cffile
, &ifo
->mtime
);
2662 skip
= have_profile
= new_block
= 0;
2663 had_block
= ifname
== NULL
? 1 : 0;
2665 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2666 option
= strsep(&line
, " \t");
2668 line
= strskipwhite(line
);
2669 /* Trim trailing whitespace */
2671 p
= line
+ strlen(line
) - 1;
2673 (*p
== ' ' || *p
== '\t') &&
2677 if (skip
== 0 && new_block
) {
2680 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2681 SET_CONFIG_BLOCK(ifo
);
2684 /* Start of an interface block, skip if not ours */
2685 if (strcmp(option
, "interface") == 0) {
2690 /* No interface given */
2694 if (ifname
&& strcmp(line
, ifname
) == 0)
2701 n
= reallocarray(ctx
->ifcv
,
2702 (size_t)ctx
->ifcc
+ 1, sizeof(char *));
2708 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2709 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2716 /* Start of an ssid block, skip if not ours */
2717 if (strcmp(option
, "ssid") == 0) {
2719 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2725 /* Start of a profile block, skip if not ours */
2726 if (strcmp(option
, "profile") == 0) {
2728 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2735 /* Skip arping if we have selected a profile but not parsing
2737 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2742 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2745 if (profile
&& !have_profile
) {
2746 free_options(ctx
, ifo
);
2752 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2753 CLEAR_CONFIG_BLOCK(ifo
);
2759 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2760 struct if_options
*ifo
, int argc
, char **argv
)
2763 unsigned long long wait_opts
;
2770 /* Don't apply the command line wait options to each interface,
2771 * only use the dhcpcd.conf entry for that. */
2773 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2774 while ((opt
= getopt_long(argc
, argv
,
2775 ctx
->options
& DHCPCD_PRINT_PIDFILE
? NOERR_IF_OPTS
: IF_OPTS
,
2776 cf_options
, &oi
)) != -1)
2778 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2782 if (ifname
!= NULL
) {
2783 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2784 ifo
->options
|= wait_opts
;
2792 free_options(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
)
2795 #ifdef RT_FREE_ROUTE_TABLE
2796 struct interface
*ifp
;
2799 struct dhcp_opt
*opt
;
2802 struct token
*token
;
2810 while (ifo
->environ
[i
])
2811 free(ifo
->environ
[i
++]);
2816 while (ifo
->config
[i
])
2817 free(ifo
->config
[i
++]);
2821 #ifdef RT_FREE_ROUTE_TABLE
2822 /* Stupidly, we don't know the interface when creating the options.
2823 * As such, make sure each route has one so they can goto the
2825 ifp
= ctx
->ifaces
!= NULL
? TAILQ_FIRST(ctx
->ifaces
) : NULL
;
2827 RB_TREE_FOREACH(rt
, &ifo
->routes
) {
2828 if (rt
->rt_ifp
== NULL
)
2833 rt_headclear0(ctx
, &ifo
->routes
, AF_UNSPEC
);
2836 free(ifo
->blacklist
);
2837 free(ifo
->fallback
);
2839 for (opt
= ifo
->dhcp_override
;
2840 ifo
->dhcp_override_len
> 0;
2841 opt
++, ifo
->dhcp_override_len
--)
2842 free_dhcp_opt_embenc(opt
);
2843 free(ifo
->dhcp_override
);
2844 for (opt
= ifo
->nd_override
;
2845 ifo
->nd_override_len
> 0;
2846 opt
++, ifo
->nd_override_len
--)
2847 free_dhcp_opt_embenc(opt
);
2848 free(ifo
->nd_override
);
2849 for (opt
= ifo
->dhcp6_override
;
2850 ifo
->dhcp6_override_len
> 0;
2851 opt
++, ifo
->dhcp6_override_len
--)
2852 free_dhcp_opt_embenc(opt
);
2853 free(ifo
->dhcp6_override
);
2854 for (vo
= ifo
->vivco
;
2856 vo
++, ifo
->vivco_len
--)
2859 for (opt
= ifo
->vivso_override
;
2860 ifo
->vivso_override_len
> 0;
2861 opt
++, ifo
->vivso_override_len
--)
2862 free_dhcp_opt_embenc(opt
);
2863 free(ifo
->vivso_override
);
2865 #if defined(INET6) && !defined(SMALL)
2866 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2867 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2872 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2873 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2874 if (token
->realm_len
)