1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2020 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 {"master", 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 {"arping", required_argument
, NULL
, O_ARPING
},
124 {"destination", required_argument
, NULL
, O_DESTINATION
},
125 {"fallback", required_argument
, NULL
, O_FALLBACK
},
126 {"ipv6rs", no_argument
, NULL
, O_IPV6RS
},
127 {"noipv6rs", no_argument
, NULL
, O_NOIPV6RS
},
128 {"ipv6ra_autoconf", no_argument
, NULL
, O_IPV6RA_AUTOCONF
},
129 {"ipv6ra_noautoconf", no_argument
, NULL
, O_IPV6RA_NOAUTOCONF
},
130 {"ipv6ra_fork", no_argument
, NULL
, O_IPV6RA_FORK
},
131 {"ipv4", no_argument
, NULL
, O_IPV4
},
132 {"noipv4", no_argument
, NULL
, O_NOIPV4
},
133 {"ipv6", no_argument
, NULL
, O_IPV6
},
134 {"noipv6", no_argument
, NULL
, O_NOIPV6
},
135 {"noalias", no_argument
, NULL
, O_NOALIAS
},
136 {"iaid", required_argument
, NULL
, O_IAID
},
137 {"ia_na", no_argument
, NULL
, O_IA_NA
},
138 {"ia_ta", no_argument
, NULL
, O_IA_TA
},
139 {"ia_pd", no_argument
, NULL
, O_IA_PD
},
140 {"hostname_short", no_argument
, NULL
, O_HOSTNAME_SHORT
},
141 {"dev", required_argument
, NULL
, O_DEV
},
142 {"nodev", no_argument
, NULL
, O_NODEV
},
143 {"define", required_argument
, NULL
, O_DEFINE
},
144 {"definend", required_argument
, NULL
, O_DEFINEND
},
145 {"define6", required_argument
, NULL
, O_DEFINE6
},
146 {"embed", required_argument
, NULL
, O_EMBED
},
147 {"encap", required_argument
, NULL
, O_ENCAP
},
148 {"vendopt", required_argument
, NULL
, O_VENDOPT
},
149 {"vendclass", required_argument
, NULL
, O_VENDCLASS
},
150 {"authprotocol", required_argument
, NULL
, O_AUTHPROTOCOL
},
151 {"authtoken", required_argument
, NULL
, O_AUTHTOKEN
},
152 {"noauthrequired", no_argument
, NULL
, O_AUTHNOTREQUIRED
},
153 {"dhcp", no_argument
, NULL
, O_DHCP
},
154 {"nodhcp", no_argument
, NULL
, O_NODHCP
},
155 {"dhcp6", no_argument
, NULL
, O_DHCP6
},
156 {"nodhcp6", no_argument
, NULL
, O_NODHCP6
},
157 {"controlgroup", required_argument
, NULL
, O_CONTROLGRP
},
158 {"slaac", required_argument
, NULL
, O_SLAAC
},
159 {"gateway", no_argument
, NULL
, O_GATEWAY
},
160 {"reject", required_argument
, NULL
, O_REJECT
},
161 {"bootp", no_argument
, NULL
, O_BOOTP
},
162 {"nodelay", no_argument
, NULL
, O_NODELAY
},
163 {"noup", no_argument
, NULL
, O_NOUP
},
164 {"lastleaseextend", no_argument
, NULL
, O_LASTLEASE_EXTEND
},
165 {"inactive", no_argument
, NULL
, O_INACTIVE
},
166 {"mudurl", required_argument
, NULL
, O_MUDURL
},
167 {"link_rcvbuf", required_argument
, NULL
, O_LINK_RCVBUF
},
168 {"configure", no_argument
, NULL
, O_CONFIGURE
},
169 {"noconfigure", no_argument
, NULL
, O_NOCONFIGURE
},
170 {NULL
, 0, NULL
, '\0'}
174 add_environ(char ***array
, const char *value
, int uniq
)
176 char **newlist
, **list
= *array
;
178 char *match
= NULL
, *p
, *n
;
180 match
= strdup(value
);
185 p
= strchr(match
, '=');
187 logerrx("%s: no assignment: %s", __func__
, value
);
194 while (list
&& list
[i
]) {
195 if (match
&& strncmp(list
[i
], match
, l
) == 0) {
206 /* Append a space and the value to it */
209 n
= realloc(list
[i
], l
+ lv
+ 2);
217 memcpy(list
[i
] + l
+ 1, p
, lv
);
218 list
[i
][l
+ lv
+ 1] = '\0';
232 newlist
= reallocarray(list
, i
+ 2, sizeof(char *));
233 if (newlist
== NULL
) {
239 newlist
[i
+ 1] = NULL
;
244 #define PARSE_STRING 0
245 #define PARSE_STRING_NULL 1
246 #define PARSE_HWADDR 2
247 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
248 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
249 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
251 parse_str(char *sbuf
, size_t slen
, const char *str
, int flags
)
258 end
= str
+ strlen(str
);
259 /* If surrounded by quotes then it's a string */
267 l
= (size_t)hwaddr_aton(NULL
, str
);
268 if ((ssize_t
) l
!= -1 && l
> 1) {
273 hwaddr_aton((uint8_t *)sbuf
, str
);
278 /* Process escapes */
280 /* If processing a string on the clientid, first byte should be
281 * 0 to indicate a non hardware type */
282 if (flags
== PARSE_HWADDR
&& *str
) {
289 if (++l
> slen
&& sbuf
) {
295 switch((cmd
= *str
++)) {
316 /* Grab a hex code */
318 for (i
= 0; i
< 2; i
++) {
319 if (isxdigit((unsigned char)*str
) == 0)
323 if (c
[1] != '\0' && sbuf
) {
325 *sbuf
++ = (char)strtol(c
, NULL
, 16);
330 /* Grab an octal code */
332 for (i
= 0; i
< 3; i
++) {
333 if (*str
< '0' || *str
> '7')
337 if (c
[2] != '\0' && sbuf
) {
338 i
= (int)strtol(c
, NULL
, 8);
356 if (flags
== PARSE_STRING_NULL
) {
370 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
376 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
380 memcpy(iaid
, &narg
, sizeof(narg
));
384 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
396 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
399 return parse_iaid1(iaid
, arg
, len
, 1);
404 parse_uint32(uint32_t *i
, const char *arg
)
407 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
412 splitv(int *argc
, char **argv
, const char *arg
)
414 char **n
, **v
= argv
;
415 char *o
= strdup(arg
), *p
, *t
, *nt
;
422 while ((t
= strsep(&p
, ", "))) {
429 n
= reallocarray(v
, (size_t)(*argc
) + 1, sizeof(char *));
445 parse_addr(struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
449 if (arg
== NULL
|| *arg
== '\0') {
456 if ((p
= strchr(arg
, '/')) != NULL
) {
461 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
463 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
465 logerrx("invalid CIDR: %s", p
);
470 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
471 logerrx("invalid IP address: %s", arg
);
476 else if (net
!= NULL
&& addr
!= NULL
)
477 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
482 parse_addr(__unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
483 __unused
const char *arg
)
486 logerrx("No IPv4 support");
492 set_option_space(struct dhcpcd_ctx
*ctx
,
494 const struct dhcp_opt
**d
, size_t *dl
,
495 const struct dhcp_opt
**od
, size_t *odl
,
496 struct if_options
*ifo
,
497 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
500 #if !defined(INET) && !defined(INET6)
505 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
507 *dl
= ctx
->nd_opts_len
;
508 *od
= ifo
->nd_override
;
509 *odl
= ifo
->nd_override_len
;
510 *request
= ifo
->requestmasknd
;
511 *require
= ifo
->requiremasknd
;
513 *reject
= ifo
->rejectmasknd
;
518 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
519 *d
= ctx
->dhcp6_opts
;
520 *dl
= ctx
->dhcp6_opts_len
;
521 *od
= ifo
->dhcp6_override
;
522 *odl
= ifo
->dhcp6_override_len
;
523 *request
= ifo
->requestmask6
;
524 *require
= ifo
->requiremask6
;
526 *reject
= ifo
->rejectmask6
;
536 *dl
= ctx
->dhcp_opts_len
;
537 *od
= ifo
->dhcp_override
;
538 *odl
= ifo
->dhcp_override_len
;
545 *request
= ifo
->requestmask
;
546 *require
= ifo
->requiremask
;
548 *reject
= ifo
->rejectmask
;
552 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
559 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
560 free_dhcp_opt_embenc(o
);
562 opt
->embopts_len
= 0;
565 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
566 free_dhcp_opt_embenc(o
);
568 opt
->encopts_len
= 0;
573 strwhite(const char *s
)
578 while (*s
!= ' ' && *s
!= '\t') {
587 strskipwhite(const char *s
)
590 if (s
== NULL
|| *s
== '\0')
592 while (*s
== ' ' || *s
== '\t') {
601 /* Find the end pointer of a string. */
603 strend(const char *s
)
610 return strchr(s
, ' ');
612 for (; *s
!= '"' ; s
++) {
625 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
626 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
631 char *p
= NULL
, *bp
, *fp
, *np
;
633 struct in_addr addr
, addr2
;
636 const struct dhcp_opt
*d
, *od
;
637 uint8_t *request
, *require
, *no
, *reject
;
638 struct dhcp_opt
**dop
, *ndop
;
639 size_t *dop_len
, dl
, odl
;
653 struct if_sla
*sla
, *slap
;
663 /* Add a guard for static analysers.
664 * This should not be needed really because of the argument_required option
665 * in the options declaration above. */
666 #define ARG_REQUIRED if (arg == NULL) goto arg_required
669 case 'f': /* FALLTHROUGH */
670 case 'g': /* FALLTHROUGH */
671 case 'n': /* FALLTHROUGH */
672 case 'q': /* FALLTHROUGH */
673 case 'x': /* FALLTHROUGH */
674 case 'N': /* FALLTHROUGH */
675 case 'P': /* FALLTHROUGH */
676 case 'T': /* FALLTHROUGH */
677 case 'U': /* FALLTHROUGH */
678 case 'V': /* We need to handle non interface options */
681 ifo
->options
|= DHCPCD_BACKGROUND
;
685 if (IN_CONFIG_BLOCK(ifo
)) {
686 logerrx("%s: per interface scripts"
687 " are no longer supported",
691 if (ctx
->script
!= dhcpcd_default_script
)
693 s
= parse_nstring(NULL
, 0, arg
);
699 if (s
== -1 || (ctx
->script
= malloc(dl
)) == NULL
) {
704 s
= parse_nstring(ctx
->script
, dl
, arg
);
706 ctx
->script
[0] == '\0' ||
707 strcmp(ctx
->script
, "/dev/null") == 0)
714 ifo
->options
|= DHCPCD_DEBUG
;
718 add_environ(&ifo
->environ
, arg
, 1);
722 ifo
->options
|= DHCPCD_HOSTNAME
;
725 s
= parse_nstring(ifo
->hostname
, sizeof(ifo
->hostname
), arg
);
727 logerr("%s: hostname", __func__
);
730 if (s
!= 0 && ifo
->hostname
[0] == '.') {
731 logerrx("hostname cannot begin with .");
734 if (ifo
->hostname
[0] == '\0')
735 ifo
->options
&= ~DHCPCD_HOSTNAME
;
737 ifo
->options
|= DHCPCD_HOSTNAME
;
741 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
742 VENDORCLASSID_MAX_LEN
, arg
);
746 logerr("vendorclassid");
749 *ifo
->vendorclassid
= (uint8_t)s
;
753 /* per interface logging is not supported
754 * don't want to overide the commandline */
755 if (!IN_CONFIG_BLOCK(ifo
) && ctx
->logfile
== NULL
) {
757 ctx
->logfile
= strdup(arg
);
758 logopen(ctx
->logfile
);
762 ifo
->options
|= DHCPCD_RELEASE
;
766 if (strcmp(arg
, "-1") == 0) {
767 ifo
->leasetime
= DHCP_INFINITE_LIFETIME
;
770 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
771 0, 0, UINT32_MAX
, &e
);
773 logerrx("failed to convert leasetime %s", arg
);
779 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
781 logerrx("failed to convert metric %s", arg
);
787 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
789 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
790 &request
, &require
, &no
, &reject
);
791 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
792 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
793 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
795 logerrx("unknown option: %s", arg
);
801 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
803 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
804 &request
, &require
, &no
, &reject
);
805 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
806 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
807 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
809 logerrx("unknown option: %s", arg
);
814 ifo
->options
|= DHCPCD_PERSISTENT
;
817 if (parse_addr(&ifo
->req_addr
, NULL
, arg
) != 0)
819 ifo
->options
|= DHCPCD_REQUEST
;
820 ifo
->req_mask
.s_addr
= 0;
823 if (arg
&& *arg
!= '\0') {
824 /* Strip out a broadcast address */
825 p
= strchr(arg
, '/');
827 p
= strchr(p
+ 1, '/');
831 i
= parse_addr(&ifo
->req_addr
, &ifo
->req_mask
, arg
);
833 /* Ensure the original string is preserved */
836 i
= parse_addr(&ifo
->req_brd
, NULL
, p
);
841 ifo
->req_addr
.s_addr
= 0;
842 ifo
->req_mask
.s_addr
= 0;
844 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
845 ifo
->options
&= ~DHCPCD_STATIC
;
848 ifo
->options
|= DHCPCD_INFORM6
;
852 ifo
->timeout
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
854 logerrx("failed to convert timeout %s", arg
);
859 dl
= sizeof(ifo
->userclass
) - ifo
->userclass
[0] - 1;
860 s
= parse_string((char *)ifo
->userclass
+
861 ifo
->userclass
[0] + 2, dl
, arg
);
867 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
868 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
873 /* Some Microsoft DHCP servers expect userclass to be an
874 * opaque blob. This is not RFC 3004 compliant. */
875 s
= parse_string((char *)ifo
->userclass
+ 1,
876 sizeof(ifo
->userclass
) - 1, arg
);
878 logerr("msuserclass");
881 ifo
->userclass
[0] = (uint8_t)s
;
886 p
= strchr(arg
, ',');
888 logerrx("invalid vendor format: %s", arg
);
892 /* If vendor starts with , then it is not encapsulated */
895 s
= parse_string((char *)ifo
->vendor
+ 1,
896 VENDOR_MAX_LEN
, arg
);
901 ifo
->vendor
[0] = (uint8_t)s
;
902 ifo
->options
|= DHCPCD_VENDORRAW
;
906 /* Encapsulated vendor options */
907 if (ifo
->options
& DHCPCD_VENDORRAW
) {
908 ifo
->options
&= ~DHCPCD_VENDORRAW
;
912 /* Strip and preserve the comma */
914 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
917 logerrx("vendor option should be between"
918 " 1 and 254 inclusive");
923 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
924 if (inet_aton(arg
, &addr
) == 1) {
929 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
930 &addr
.s_addr
, sizeof(addr
.s_addr
));
931 s
= sizeof(addr
.s_addr
);
934 s
= parse_string((char *)ifo
->vendor
+
935 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
942 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
943 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
944 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
948 ifo
->options
|= DHCPCD_WAITIP
;
949 if (arg
!= NULL
&& arg
[0] != '\0') {
950 if (arg
[0] == '4' || arg
[1] == '4')
951 ifo
->options
|= DHCPCD_WAITIP4
;
952 if (arg
[0] == '6' || arg
[1] == '6')
953 ifo
->options
|= DHCPCD_WAITIP6
;
958 ifo
->reboot
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
960 logerr("failed to convert reboot %s", arg
);
966 if (!IN_CONFIG_BLOCK(ifo
))
967 ctx
->ifav
= splitv(&ctx
->ifac
, ctx
->ifav
, arg
);
970 ifo
->options
&= ~DHCPCD_ARP
;
971 /* IPv4LL requires ARP */
972 ifo
->options
&= ~DHCPCD_IPV4LL
;
975 ifo
->options
&= ~DHCPCD_DAEMONISE
;
979 /* Commas to spaces for shell */
980 while ((p
= strchr(arg
, ',')))
982 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
983 p
= malloc(sizeof(char) * dl
);
988 snprintf(p
, dl
, "skip_hooks=%s", arg
);
989 add_environ(&ifo
->environ
, p
, 0);
993 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
994 if (ifname
!= NULL
) /* duid type only a global option */
997 ctx
->duid_type
= DUID_DEFAULT
;
998 else if (strcmp(arg
, "ll") == 0)
999 ctx
->duid_type
= DUID_LL
;
1000 else if (strcmp(arg
, "llt") == 0)
1001 ctx
->duid_type
= DUID_LLT
;
1002 else if (strcmp(arg
, "uuid") == 0)
1003 ctx
->duid_type
= DUID_UUID
;
1005 logwarnx("%s: invalid duid type", arg
);
1006 ctx
->duid_type
= DUID_DEFAULT
;
1010 ifo
->options
|= DHCPCD_LASTLEASE
;
1014 ifo
->fqdn
= FQDN_BOTH
;
1017 if (strcmp(arg
, "none") == 0)
1018 ifo
->fqdn
= FQDN_NONE
;
1019 else if (strcmp(arg
, "ptr") == 0)
1020 ifo
->fqdn
= FQDN_PTR
;
1021 else if (strcmp(arg
, "both") == 0)
1022 ifo
->fqdn
= FQDN_BOTH
;
1023 else if (strcmp(arg
, "disable") == 0)
1024 ifo
->fqdn
= FQDN_DISABLE
;
1026 logerrx("invalid FQDN value: %s", arg
);
1031 ifo
->options
&= ~DHCPCD_GATEWAY
;
1034 ifo
->options
|= DHCPCD_XID_HWADDR
;
1037 /* Strings have a type of 0 */;
1038 ifo
->clientid
[1] = 0;
1040 s
= parse_hwaddr((char *)ifo
->clientid
+ 1,
1041 CLIENTID_MAX_LEN
, arg
);
1048 ifo
->options
|= DHCPCD_CLIENTID
;
1049 ifo
->clientid
[0] = (uint8_t)s
;
1050 ifo
->options
&= ~DHCPCD_DUID
;
1053 ifo
->options
|= DHCPCD_BROADCAST
;
1056 ifo
->options
&= ~DHCPCD_LINK
;
1059 ifo
->options
&= ~DHCPCD_IPV4LL
;
1062 ifo
->options
|= DHCPCD_MASTER
;
1066 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1068 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1069 &request
, &require
, &no
, &reject
);
1070 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
1071 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1072 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1074 logerrx("unknown option: %s", arg
);
1080 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1082 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1083 &request
, &require
, &no
, &reject
);
1084 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1085 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1086 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1087 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1089 logerrx("unknown option: %s", arg
);
1095 p
= strchr(arg
, '=');
1097 logerrx("static assignment required");
1101 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1102 if (parse_addr(&ifo
->req_addr
,
1103 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1107 ifo
->options
|= DHCPCD_STATIC
;
1108 ifo
->options
&= ~DHCPCD_INFORM
;
1109 } else if (strncmp(arg
, "subnet_mask=",
1110 strlen("subnet_mask=")) == 0)
1112 if (parse_addr(&ifo
->req_mask
, NULL
, p
) != 0)
1114 } else if (strncmp(arg
, "broadcast_address=",
1115 strlen("broadcast_address=")) == 0)
1117 if (parse_addr(&ifo
->req_brd
, NULL
, p
) != 0)
1119 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1120 strncmp(arg
, "static_routes=",
1121 strlen("static_routes=")) == 0 ||
1122 strncmp(arg
, "classless_static_routes=",
1123 strlen("classless_static_routes=")) == 0 ||
1124 strncmp(arg
, "ms_classless_static_routes=",
1125 strlen("ms_classless_static_routes=")) == 0)
1127 struct in_addr addr3
;
1129 fp
= np
= strwhite(p
);
1131 logerrx("all routes need a gateway");
1135 np
= strskipwhite(np
);
1136 if (parse_addr(&addr
, &addr2
, p
) == -1 ||
1137 parse_addr(&addr3
, NULL
, np
) == -1)
1143 if ((rt
= rt_new0(ctx
)) == NULL
)
1145 sa_in_init(&rt
->rt_dest
, &addr
);
1146 sa_in_init(&rt
->rt_netmask
, &addr2
);
1147 sa_in_init(&rt
->rt_gateway
, &addr3
);
1148 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1149 add_environ(&ifo
->config
, arg
, 0);
1150 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1151 if (parse_addr(&addr
, NULL
, p
) == -1)
1153 if ((rt
= rt_new0(ctx
)) == NULL
)
1155 addr2
.s_addr
= INADDR_ANY
;
1156 sa_in_init(&rt
->rt_dest
, &addr2
);
1157 sa_in_init(&rt
->rt_netmask
, &addr2
);
1158 sa_in_init(&rt
->rt_gateway
, &addr
);
1159 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1160 add_environ(&ifo
->config
, arg
, 0);
1161 } else if (strncmp(arg
, "interface_mtu=",
1162 strlen("interface_mtu=")) == 0 ||
1163 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1165 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1166 MTU_MIN
, MTU_MAX
, &e
);
1168 logerrx("invalid MTU %s", p
);
1171 } else if (strncmp(arg
, "ip6_address=", strlen("ip6_address=")) == 0) {
1172 np
= strchr(p
, '/');
1175 if ((i
= inet_pton(AF_INET6
, p
, &ifo
->req_addr6
)) == 1) {
1177 ifo
->req_prefix_len
= (uint8_t)strtou(np
,
1178 NULL
, 0, 0, 128, &e
);
1180 logerrx("%s: failed to "
1181 "convert prefix len",
1186 ifo
->req_prefix_len
= 128;
1191 logerrx("invalid AF_INET6: %s", p
);
1192 memset(&ifo
->req_addr6
, 0,
1193 sizeof(ifo
->req_addr6
));
1197 add_environ(&ifo
->config
, arg
, 1);
1200 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1202 if (strchr(arg
, '/') == NULL
)
1203 addr2
.s_addr
= INADDR_BROADCAST
;
1204 naddr
= reallocarray(ifo
->whitelist
,
1205 ifo
->whitelist_len
+ 2, sizeof(in_addr_t
));
1206 if (naddr
== NULL
) {
1210 ifo
->whitelist
= naddr
;
1211 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1212 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1215 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1217 if (strchr(arg
, '/') == NULL
)
1218 addr2
.s_addr
= INADDR_BROADCAST
;
1219 naddr
= reallocarray(ifo
->blacklist
,
1220 ifo
->blacklist_len
+ 2, sizeof(in_addr_t
));
1221 if (naddr
== NULL
) {
1225 ifo
->blacklist
= naddr
;
1226 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1227 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1231 if (!IN_CONFIG_BLOCK(ifo
))
1232 ctx
->ifdv
= splitv(&ctx
->ifdc
, ctx
->ifdv
, arg
);
1235 ifo
->options
|= DHCPCD_ONESHOT
;
1239 ifo
->options
&= ~DHCPCD_IPV6
;
1240 ifo
->options
|= DHCPCD_IPV4
;
1243 logerrx("INET has been compiled out");
1248 ifo
->options
&= ~DHCPCD_IPV4
;
1249 ifo
->options
|= DHCPCD_IPV6
;
1252 logerrx("INET6 has been compiled out");
1256 ifo
->options
|= DHCPCD_IPV4
;
1259 ifo
->options
&= ~DHCPCD_IPV4
;
1262 ifo
->options
|= DHCPCD_IPV6
;
1265 ifo
->options
&= ~DHCPCD_IPV6
;
1268 ifo
->options
|= DHCPCD_ANONYMOUS
;
1269 ifo
->options
&= ~DHCPCD_HOSTNAME
;
1270 ifo
->fqdn
= FQDN_DISABLE
;
1272 /* Block everything */
1273 memset(ifo
->nomask
, 0xff, sizeof(ifo
->nomask
));
1274 memset(ifo
->nomask6
, 0xff, sizeof(ifo
->nomask6
));
1276 /* Allow the bare minimum through */
1278 del_option_mask(ifo
->nomask
, DHO_SUBNETMASK
);
1279 del_option_mask(ifo
->nomask
, DHO_CSR
);
1280 del_option_mask(ifo
->nomask
, DHO_ROUTER
);
1281 del_option_mask(ifo
->nomask
, DHO_DNSSERVER
);
1282 del_option_mask(ifo
->nomask
, DHO_DNSDOMAIN
);
1283 del_option_mask(ifo
->nomask
, DHO_BROADCAST
);
1284 del_option_mask(ifo
->nomask
, DHO_STATICROUTE
);
1285 del_option_mask(ifo
->nomask
, DHO_SERVERID
);
1286 del_option_mask(ifo
->nomask
, DHO_RENEWALTIME
);
1287 del_option_mask(ifo
->nomask
, DHO_REBINDTIME
);
1288 del_option_mask(ifo
->nomask
, DHO_DNSSEARCH
);
1292 del_option_mask(ifo
->nomask6
, D6_OPTION_DNS_SERVERS
);
1293 del_option_mask(ifo
->nomask6
, D6_OPTION_DOMAIN_LIST
);
1294 del_option_mask(ifo
->nomask6
, D6_OPTION_SOL_MAX_RT
);
1295 del_option_mask(ifo
->nomask6
, D6_OPTION_INF_MAX_RT
);
1301 while (arg
!= NULL
) {
1305 if (parse_addr(&addr
, NULL
, arg
) != 0)
1307 naddr
= reallocarray(ifo
->arping
,
1308 (size_t)ifo
->arping_len
+ 1, sizeof(in_addr_t
));
1309 if (naddr
== NULL
) {
1313 ifo
->arping
= naddr
;
1314 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1315 arg
= strskipwhite(fp
);
1320 if (ctx
->options
& DHCPCD_PRINT_PIDFILE
)
1322 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1323 &request
, &require
, &no
, &reject
);
1324 if (make_option_mask(d
, dl
, od
, odl
,
1325 ifo
->dstmask
, arg
, 2) != 0)
1327 if (errno
== EINVAL
)
1328 logerrx("option does not take"
1329 " an IPv4 address: %s", arg
);
1331 logerrx("unknown option: %s", arg
);
1337 free(ifo
->fallback
);
1338 ifo
->fallback
= strdup(arg
);
1339 if (ifo
->fallback
== NULL
) {
1347 if (!IN_CONFIG_BLOCK(ifo
)) {
1348 logerrx("IAID must belong in an interface block");
1351 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1352 logerrx("invalid IAID %s", arg
);
1355 ifo
->options
|= DHCPCD_IAID
;
1358 ifo
->options
|= DHCPCD_IPV6RS
;
1361 ifo
->options
&= ~DHCPCD_IPV6RS
;
1364 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1366 case O_IPV6RA_AUTOCONF
:
1367 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1369 case O_IPV6RA_NOAUTOCONF
:
1370 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1373 ifo
->options
|= DHCPCD_NOALIAS
;
1377 i
= D6_OPTION_IA_NA
;
1381 i
= D6_OPTION_IA_TA
;
1386 logwarnx("%s: IA_PD not compiled in", ifname
);
1389 if (!IN_CONFIG_BLOCK(ifo
)) {
1390 logerrx("IA PD must belong in an "
1394 i
= D6_OPTION_IA_PD
;
1397 if (!IN_CONFIG_BLOCK(ifo
) && arg
) {
1398 logerrx("IA with IAID must belong in an "
1402 ifo
->options
|= DHCPCD_IA_FORCED
;
1406 fp
= strskipwhite(fp
);
1409 p
= strchr(arg
, '/');
1412 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1413 logerr("invalid IAID: %s", arg
);
1418 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1419 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1420 (arg
!= NULL
&& ifo
->ia
[sl
].iaid_set
&&
1421 ifo
->ia
[sl
].ia_type
== (uint16_t)i
&&
1422 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1423 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1424 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1425 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1432 ia
= reallocarray(ifo
->ia
,
1433 ifo
->ia_len
+ 1, sizeof(*ifo
->ia
));
1439 ia
= &ifo
->ia
[ifo
->ia_len
++];
1440 ia
->ia_type
= (uint16_t)i
;
1442 ia
->iaid
[0] = iaid
[0];
1443 ia
->iaid
[1] = iaid
[1];
1444 ia
->iaid
[2] = iaid
[2];
1445 ia
->iaid
[3] = iaid
[3];
1449 if (!ia
->iaid_set
||
1451 ia
->ia_type
== D6_OPTION_IA_TA
)
1453 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1457 p
= strchr(arg
, '/');
1460 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) != 1) {
1461 logerrx("invalid AF_INET6: %s", arg
);
1462 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1464 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1465 ia
->prefix_len
= (uint8_t)strtou(p
,
1466 NULL
, 0, 8, 120, &e
);
1468 logerrx("%s: failed to convert"
1485 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1488 for (p
= fp
; p
; p
= fp
) {
1492 fp
= strskipwhite(fp
);
1494 sla
= reallocarray(ia
->sla
,
1495 ia
->sla_len
+ 1, sizeof(*ia
->sla
));
1501 sla
= &ia
->sla
[ia
->sla_len
++];
1502 np
= strchr(p
, '/');
1505 if (strlcpy(sla
->ifname
, p
,
1506 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1508 logerrx("%s: interface name too long", arg
);
1511 sla
->sla_set
= false;
1512 sla
->prefix_len
= 0;
1516 np
= strchr(p
, '/');
1520 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1521 0, 0, UINT32_MAX
, &e
);
1522 sla
->sla_set
= true;
1524 logerrx("%s: failed to convert "
1533 np
= strchr(p
, '/');
1537 sla
->prefix_len
= (uint8_t)strtou(p
,
1538 NULL
, 0, 0, 120, &e
);
1540 logerrx("%s: failed to "
1541 "convert prefix len",
1549 np
= strchr(p
, '/');
1553 sla
->suffix
= (uint64_t)strtou(p
, NULL
,
1554 0, 0, UINT64_MAX
, &e
);
1556 logerrx("%s: failed to "
1564 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1565 slap
= &ia
->sla
[sl
];
1566 if (slap
->sla_set
!= sla
->sla_set
) {
1567 logerrx("%s: cannot mix automatic "
1572 if (ia
->prefix_len
&&
1573 (sla
->prefix_len
== ia
->prefix_len
||
1574 slap
->prefix_len
== ia
->prefix_len
))
1576 logerrx("%s: cannot delegte the same"
1577 "prefix length more than once",
1581 if (!sla
->sla_set
&&
1582 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1584 logwarnx("%s: cannot specify the "
1585 "same interface twice with "
1590 if (slap
->sla_set
&& sla
->sla_set
&&
1591 slap
->sla
== sla
->sla
)
1593 logerrx("%s: cannot"
1594 " assign the same SLA %u"
1596 sla
->ifname
, sla
->sla
);
1600 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1601 ia
->sla_max
= sla
->sla
;
1609 case O_HOSTNAME_SHORT
:
1610 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1616 free(ctx
->dev_load
);
1617 ctx
->dev_load
= strdup(arg
);
1621 ifo
->options
&= ~DHCPCD_DEV
;
1624 dop
= &ifo
->dhcp_override
;
1625 dop_len
= &ifo
->dhcp_override_len
;
1629 dop
= &ifo
->nd_override
;
1630 dop_len
= &ifo
->nd_override_len
;
1635 dop
= &ifo
->dhcp6_override
;
1636 dop_len
= &ifo
->dhcp6_override_len
;
1641 dop
= &ifo
->vivso_override
;
1642 dop_len
= &ifo
->vivso_override_len
;
1644 *edop
= *ldop
= NULL
;
1649 dop
= &(*edop
)->embopts
;
1650 dop_len
= &(*edop
)->embopts_len
;
1652 dop
= &(*ldop
)->embopts
;
1653 dop_len
= &(*ldop
)->embopts_len
;
1655 logerrx("embed must be after a define "
1664 if (*ldop
== NULL
) {
1665 logerrx("encap must be after a define");
1668 dop
= &(*ldop
)->encopts
;
1669 dop_len
= &(*ldop
)->encopts_len
;
1672 /* Shared code for define, define6, embed and encap */
1675 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1680 logerrx("invalid syntax: %s", arg
);
1684 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1686 logerrx("invalid code: %s", arg
);
1689 arg
= strskipwhite(fp
);
1691 logerrx("invalid syntax");
1699 np
= strchr(arg
, ':');
1703 bp
= NULL
; /* No bitflag */
1704 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1706 logerrx("failed to convert length");
1711 bp
= strchr(arg
, '='); /* bitflag assignment */
1716 if (strcasecmp(arg
, "request") == 0) {
1718 arg
= strskipwhite(fp
);
1721 logerrx("incomplete request type");
1725 } else if (strcasecmp(arg
, "norequest") == 0) {
1727 arg
= strskipwhite(fp
);
1730 logerrx("incomplete request type");
1735 if (strcasecmp(arg
, "optional") == 0) {
1737 arg
= strskipwhite(fp
);
1740 logerrx("incomplete optional type");
1745 if (strcasecmp(arg
, "index") == 0) {
1747 arg
= strskipwhite(fp
);
1750 logerrx("incomplete index type");
1755 if (strcasecmp(arg
, "array") == 0) {
1757 arg
= strskipwhite(fp
);
1760 logerrx("incomplete array type");
1765 if (strcasecmp(arg
, "ipaddress") == 0)
1767 else if (strcasecmp(arg
, "ip6address") == 0)
1769 else if (strcasecmp(arg
, "string") == 0)
1771 else if (strcasecmp(arg
, "byte") == 0)
1773 else if (strcasecmp(arg
, "bitflags") == 0)
1775 else if (strcasecmp(arg
, "uint8") == 0)
1777 else if (strcasecmp(arg
, "int8") == 0)
1779 else if (strcasecmp(arg
, "uint16") == 0)
1781 else if (strcasecmp(arg
, "int16") == 0)
1783 else if (strcasecmp(arg
, "uint32") == 0)
1785 else if (strcasecmp(arg
, "int32") == 0)
1787 else if (strcasecmp(arg
, "flag") == 0)
1789 else if (strcasecmp(arg
, "raw") == 0)
1790 t
|= OT_STRING
| OT_RAW
;
1791 else if (strcasecmp(arg
, "ascii") == 0)
1792 t
|= OT_STRING
| OT_ASCII
;
1793 else if (strcasecmp(arg
, "domain") == 0)
1794 t
|= OT_STRING
| OT_DOMAIN
| OT_RFC1035
;
1795 else if (strcasecmp(arg
, "dname") == 0)
1796 t
|= OT_STRING
| OT_DOMAIN
;
1797 else if (strcasecmp(arg
, "binhex") == 0)
1798 t
|= OT_STRING
| OT_BINHEX
;
1799 else if (strcasecmp(arg
, "embed") == 0)
1801 else if (strcasecmp(arg
, "encap") == 0)
1803 else if (strcasecmp(arg
, "rfc3361") ==0)
1804 t
|= OT_STRING
| OT_RFC3361
;
1805 else if (strcasecmp(arg
, "rfc3442") ==0)
1806 t
|= OT_STRING
| OT_RFC3442
;
1807 else if (strcasecmp(arg
, "option") == 0)
1810 logerrx("unknown type: %s", arg
);
1813 if (l
&& !(t
& (OT_STRING
| OT_BINHEX
))) {
1814 logwarnx("ignoring length for type: %s", arg
);
1817 if (t
& OT_ARRAY
&& t
& (OT_STRING
| OT_BINHEX
) &&
1818 !(t
& (OT_RFC1035
| OT_DOMAIN
)))
1820 logwarnx("ignoring array for strings");
1823 if (t
& OT_BITFLAG
) {
1825 logwarnx("missing bitflag assignment");
1829 if (!(t
& OT_OPTION
)) {
1830 logerrx("type %s requires a variable name",
1836 arg
= strskipwhite(fp
);
1840 if (strcasecmp(arg
, "reserved")) {
1851 if (opt
!= O_EMBED
) {
1852 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1854 /* type 0 seems freshly malloced struct
1856 if (ndop
->option
== u
|| ndop
->type
== 0)
1864 ndop
= reallocarray(*dop
, *dop_len
+ 1, sizeof(**dop
));
1871 ndop
= &(*dop
)[(*dop_len
)++];
1872 ndop
->embopts
= NULL
;
1873 ndop
->embopts_len
= 0;
1874 ndop
->encopts
= NULL
;
1875 ndop
->encopts_len
= 0;
1877 free_dhcp_opt_embenc(ndop
);
1878 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1880 ndop
->len
= (size_t)l
;
1884 memcpy(ndop
->bitflags
, bp
, dl
);
1885 memset(ndop
->bitflags
+ dl
, 0,
1886 sizeof(ndop
->bitflags
) - dl
);
1888 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1889 /* Save the define for embed and encap options */
1907 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1909 logerrx("invalid code: %s", arg
);
1912 fp
= strskipwhite(fp
);
1914 s
= parse_string(NULL
, 0, fp
);
1920 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1921 logerrx("vendor class is too big");
1929 parse_string(np
, dl
, fp
);
1934 vivco
= reallocarray(ifo
->vivco
,
1935 ifo
->vivco_len
+ 1, sizeof(*ifo
->vivco
));
1936 if (vivco
== NULL
) {
1942 ifo
->vivco_en
= (uint32_t)u
;
1943 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
1945 vivco
->data
= (uint8_t *)np
;
1947 case O_AUTHPROTOCOL
:
1953 if (strcasecmp(arg
, "token") == 0)
1954 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
1955 else if (strcasecmp(arg
, "delayed") == 0)
1956 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
1957 else if (strcasecmp(arg
, "delayedrealm") == 0)
1958 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
1960 logerrx("%s: unsupported protocol", arg
);
1963 arg
= strskipwhite(fp
);
1966 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1967 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
)
1968 ifo
->auth
.protocol
= AUTH_ALG_NONE
;
1970 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1971 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1976 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
) {
1977 np
= strchr(arg
, '/');
1979 if (fp
== NULL
|| np
< fp
)
1984 if (parse_uint32(&ifo
->auth
.token_snd_secretid
,
1986 logerrx("%s: not a number", arg
);
1988 ifo
->auth
.token_rcv_secretid
=
1989 ifo
->auth
.token_snd_secretid
;
1991 parse_uint32(&ifo
->auth
.token_rcv_secretid
,
1993 logerrx("%s: not a number", arg
);
1995 if (strcasecmp(arg
, "hmacmd5") == 0 ||
1996 strcasecmp(arg
, "hmac-md5") == 0)
1997 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1999 logerrx("%s: unsupported algorithm", arg
);
2005 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2006 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2009 if (strcasecmp(arg
, "monocounter") == 0) {
2010 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2011 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
2012 } else if (strcasecmp(arg
, "monotonic") ==0 ||
2013 strcasecmp(arg
, "monotime") == 0)
2014 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
2016 logerrx("%s: unsupported RDM", arg
);
2019 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
2022 logerrx("no authentication support");
2030 logerrx("authtoken requires a realm");
2034 token
= calloc(1, sizeof(*token
));
2035 if (token
== NULL
) {
2039 if (parse_uint32(&token
->secretid
, arg
) == -1) {
2040 logerrx("%s: not a number", arg
);
2046 logerrx("authtoken requies an a key");
2050 s
= parse_string(NULL
, 0, arg
);
2052 logerr("realm_len");
2056 token
->realm_len
= (size_t)s
;
2057 token
->realm
= malloc(token
->realm_len
);
2058 if (token
->realm
== NULL
) {
2062 parse_string((char *)token
->realm
, token
->realm_len
,
2068 logerrx("authtoken requies an expiry date");
2074 np
= strchr(arg
, '"');
2078 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
2083 memset(&tm
, 0, sizeof(tm
));
2084 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
2085 logerrx("%s: invalid date time", arg
);
2088 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
2089 logerr("%s: mktime", __func__
);
2094 s
= parse_string(NULL
, 0, arg
);
2095 if (s
== -1 || s
== 0) {
2097 logerr("token_len");
2099 logerrx("authtoken needs a key");
2102 token
->key_len
= (size_t)s
;
2103 token
->key
= malloc(token
->key_len
);
2104 if (token
->key
== NULL
) {
2108 parse_string((char *)token
->key
, token
->key_len
, arg
);
2109 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
2116 logerrx("no authentication support");
2119 case O_AUTHNOTREQUIRED
:
2120 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
2123 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_WANTDHCP
| DHCPCD_IPV4
;
2126 ifo
->options
&= ~DHCPCD_DHCP
;
2129 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
2132 ifo
->options
&= ~DHCPCD_DHCP6
;
2137 /* Control group is already set by this point.
2138 * We don't need to pledge getpw either with this. */
2139 if (IN_PRIVSEP(ctx
))
2143 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
2153 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, dl
, &grp
)) ==
2158 logerrx("control_group: out of buffer");
2163 np
= realloc(p
, dl
);
2173 logerr("getgrnam_r");
2178 if (!ctx
->control_group
)
2179 logerrx("controlgroup: %s: not found", arg
);
2183 ctx
->control_group
= grp
->gr_gid
;
2186 grp
= getgrnam(arg
);
2188 if (!ctx
->control_group
)
2189 logerrx("controlgroup: %s: not found", arg
);
2192 ctx
->control_group
= grp
->gr_gid
;
2196 ifo
->options
|= DHCPCD_GATEWAY
;
2199 ifo
->options
&= ~DHCPCD_IF_UP
;
2206 np
= strskipwhite(np
);
2208 if (strcmp(arg
, "private") == 0 ||
2209 strcmp(arg
, "stableprivate") == 0 ||
2210 strcmp(arg
, "stable") == 0)
2211 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2213 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2215 (strcmp(np
, "temp") == 0 || strcmp(np
, "temporary") == 0))
2216 ifo
->options
|= DHCPCD_SLAACTEMP
;
2219 ifo
->options
|= DHCPCD_BOOTP
;
2222 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2224 case O_LASTLEASE_EXTEND
:
2225 ifo
->options
|= DHCPCD_LASTLEASE
| DHCPCD_LASTLEASE_EXTEND
;
2228 ifo
->options
|= DHCPCD_INACTIVE
;
2232 s
= parse_string((char *)ifo
->mudurl
+ 1, MUDURL_MAX_LEN
, arg
);
2237 *ifo
->mudurl
= (uint8_t)s
;
2242 ctx
->link_rcvbuf
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
2244 logerrx("failed to convert link_rcvbuf %s", arg
);
2250 ifo
->options
|= DHCPCD_CONFIGURE
;
2253 ifo
->options
&= ~DHCPCD_CONFIGURE
;
2263 logerrx("option %d requires an argument", opt
);
2270 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2271 struct if_options
*ifo
, const char *opt
, char *line
,
2272 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2276 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2277 if (!cf_options
[i
].name
||
2278 strcmp(cf_options
[i
].name
, opt
) != 0)
2281 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2282 logerrx("option requires an argument -- %s", opt
);
2286 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2290 if (!(ctx
->options
& DHCPCD_PRINT_PIDFILE
))
2291 logerrx("unknown option: %s", opt
);
2296 finish_config(struct if_options
*ifo
)
2299 /* Terminate the encapsulated options */
2300 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2302 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2303 /* We are called twice.
2304 * This should be fixed, but in the meantime, this
2305 * guard should suffice */
2306 ifo
->options
|= DHCPCD_VENDORRAW
;
2309 if (!(ifo
->options
& DHCPCD_ARP
) ||
2310 ifo
->options
& (DHCPCD_INFORM
| DHCPCD_STATIC
))
2311 ifo
->options
&= ~DHCPCD_IPV4LL
;
2313 if (!(ifo
->options
& DHCPCD_IPV4
))
2314 ifo
->options
&= ~(DHCPCD_DHCP
| DHCPCD_IPV4LL
| DHCPCD_WAITIP4
);
2316 if (!(ifo
->options
& DHCPCD_IPV6
))
2318 ~(DHCPCD_IPV6RS
| DHCPCD_DHCP6
| DHCPCD_WAITIP6
);
2320 if (!(ifo
->options
& DHCPCD_IPV6RS
))
2322 ~(DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
);
2326 default_config(struct dhcpcd_ctx
*ctx
)
2328 struct if_options
*ifo
;
2330 /* Seed our default options */
2331 if ((ifo
= calloc(1, sizeof(*ifo
))) == NULL
) {
2335 ifo
->options
|= DHCPCD_IF_UP
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2336 ifo
->timeout
= DEFAULT_TIMEOUT
;
2337 ifo
->reboot
= DEFAULT_REBOOT
;
2339 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2340 rb_tree_init(&ifo
->routes
, &rt_compare_list_ops
);
2342 TAILQ_INIT(&ifo
->auth
.tokens
);
2345 /* Inherit some global defaults */
2346 if (ctx
->options
& DHCPCD_PERSISTENT
)
2347 ifo
->options
|= DHCPCD_PERSISTENT
;
2348 if (ctx
->options
& DHCPCD_SLAACPRIVATE
)
2349 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2355 read_config(struct dhcpcd_ctx
*ctx
,
2356 const char *ifname
, const char *ssid
, const char *profile
)
2358 struct if_options
*ifo
;
2359 char buf
[UDPLEN_MAX
], *bp
; /* 64k max config file size */
2360 char *line
, *option
, *p
;
2363 int skip
, have_profile
, new_block
, had_block
;
2364 #if !defined(INET) || !defined(INET6)
2366 struct dhcp_opt
*opt
;
2368 struct dhcp_opt
*ldop
, *edop
;
2370 /* Seed our default options */
2371 if ((ifo
= default_config(ctx
)) == NULL
)
2373 if (default_options
== 0) {
2374 default_options
|= DHCPCD_DAEMONISE
|
2375 DHCPCD_CONFIGURE
| DHCPCD_GATEWAY
;
2377 skip
= socket(PF_INET
, SOCK_DGRAM
, 0);
2380 default_options
|= DHCPCD_IPV4
| DHCPCD_ARP
|
2381 DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2385 skip
= socket(PF_INET6
, SOCK_DGRAM
, 0);
2388 default_options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
|
2389 DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
|
2394 default_options
|= DHCPCD_DEV
;
2397 ifo
->options
|= default_options
;
2399 CLEAR_CONFIG_BLOCK(ifo
);
2401 vlen
= strlcpy((char *)ifo
->vendorclassid
+ 1, ctx
->vendor
,
2402 sizeof(ifo
->vendorclassid
) - 1);
2403 ifo
->vendorclassid
[0] = (uint8_t)(vlen
> 255 ? 0 : vlen
);
2405 /* Reset route order */
2408 /* Parse our embedded options file */
2409 if (ifname
== NULL
&& !(ctx
->options
& DHCPCD_PRINT_PIDFILE
)) {
2410 /* Space for initial estimates */
2411 #if defined(INET) && defined(INITDEFINES)
2412 ifo
->dhcp_override
=
2413 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2414 if (ifo
->dhcp_override
== NULL
)
2417 ifo
->dhcp_override_len
= INITDEFINES
;
2420 #if defined(INET6) && defined(INITDEFINENDS)
2422 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2423 if (ifo
->nd_override
== NULL
)
2426 ifo
->nd_override_len
= INITDEFINENDS
;
2428 #if defined(INET6) && defined(INITDEFINE6S)
2429 ifo
->dhcp6_override
=
2430 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2431 if (ifo
->dhcp6_override
== NULL
)
2434 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2437 /* Now load our embedded config */
2438 #ifdef EMBEDDED_CONFIG
2439 buflen
= dhcp_readfile(ctx
, EMBEDDED_CONFIG
, buf
, sizeof(buf
));
2441 logerr("%s: %s", __func__
, EMBEDDED_CONFIG
);
2444 if (buf
[buflen
- 1] != '\0') {
2445 if ((size_t)buflen
< sizeof(buf
) - 1)
2447 buf
[buflen
- 1] = '\0';
2450 buflen
= (ssize_t
)strlcpy(buf
, dhcpcd_embedded_conf
,
2452 if ((size_t)buflen
>= sizeof(buf
)) {
2453 logerrx("%s: embedded config too big", __func__
);
2456 /* Our embedded config is NULL terminated */
2459 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2460 option
= strsep(&line
, " \t");
2462 line
= strskipwhite(line
);
2463 /* Trim trailing whitespace */
2465 p
= line
+ strlen(line
) - 1;
2467 (*p
== ' ' || *p
== '\t') &&
2471 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2476 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2477 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2479 for (i
= 0, opt
= ifo
->dhcp_override
;
2480 i
< ifo
->dhcp_override_len
;
2482 free_dhcp_opt_embenc(opt
);
2483 free(ifo
->dhcp_override
);
2485 ifo
->dhcp_override
= NULL
;
2486 ifo
->dhcp_override_len
= 0;
2489 ctx
->nd_opts
= ifo
->nd_override
;
2490 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2492 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2493 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2496 for (i
= 0, opt
= ifo
->nd_override
;
2497 i
< ifo
->nd_override_len
;
2499 free_dhcp_opt_embenc(opt
);
2500 free(ifo
->nd_override
);
2501 for (i
= 0, opt
= ifo
->dhcp6_override
;
2502 i
< ifo
->dhcp6_override_len
;
2504 free_dhcp_opt_embenc(opt
);
2505 free(ifo
->dhcp6_override
);
2507 ifo
->nd_override
= NULL
;
2508 ifo
->nd_override_len
= 0;
2509 ifo
->dhcp6_override
= NULL
;
2510 ifo
->dhcp6_override_len
= 0;
2512 ctx
->vivso
= ifo
->vivso_override
;
2513 ctx
->vivso_len
= ifo
->vivso_override_len
;
2514 ifo
->vivso_override
= NULL
;
2515 ifo
->vivso_override_len
= 0;
2518 /* Parse our options file */
2519 buflen
= dhcp_readfile(ctx
, ctx
->cffile
, buf
, sizeof(buf
));
2521 /* dhcpcd can continue without it, but no DNS options
2522 * would be requested ... */
2523 logerr("%s: %s", __func__
, ctx
->cffile
);
2526 if (buf
[buflen
- 1] != '\0') {
2527 if ((size_t)buflen
< sizeof(buf
) - 1)
2529 buf
[buflen
- 1] = '\0';
2531 dhcp_filemtime(ctx
, ctx
->cffile
, &ifo
->mtime
);
2534 skip
= have_profile
= new_block
= 0;
2535 had_block
= ifname
== NULL
? 1 : 0;
2537 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2538 option
= strsep(&line
, " \t");
2540 line
= strskipwhite(line
);
2541 /* Trim trailing whitespace */
2543 p
= line
+ strlen(line
) - 1;
2545 (*p
== ' ' || *p
== '\t') &&
2549 if (skip
== 0 && new_block
) {
2552 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2553 SET_CONFIG_BLOCK(ifo
);
2556 /* Start of an interface block, skip if not ours */
2557 if (strcmp(option
, "interface") == 0) {
2562 /* No interface given */
2566 if (ifname
&& strcmp(line
, ifname
) == 0)
2573 n
= reallocarray(ctx
->ifcv
,
2574 (size_t)ctx
->ifcc
+ 1, sizeof(char *));
2580 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2581 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2588 /* Start of an ssid block, skip if not ours */
2589 if (strcmp(option
, "ssid") == 0) {
2591 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2597 /* Start of a profile block, skip if not ours */
2598 if (strcmp(option
, "profile") == 0) {
2600 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2607 /* Skip arping if we have selected a profile but not parsing
2609 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2614 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2617 if (profile
&& !have_profile
) {
2618 free_options(ctx
, ifo
);
2624 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2625 CLEAR_CONFIG_BLOCK(ifo
);
2631 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2632 struct if_options
*ifo
, int argc
, char **argv
)
2635 unsigned long long wait_opts
;
2642 /* Don't apply the command line wait options to each interface,
2643 * only use the dhcpcd.conf entry for that. */
2645 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2646 while ((opt
= getopt_long(argc
, argv
,
2647 ctx
->options
& DHCPCD_PRINT_PIDFILE
? NOERR_IF_OPTS
: IF_OPTS
,
2648 cf_options
, &oi
)) != -1)
2650 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2654 if (ifname
!= NULL
) {
2655 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2656 ifo
->options
|= wait_opts
;
2664 free_options(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
)
2667 #ifdef RT_FREE_ROUTE_TABLE
2668 struct interface
*ifp
;
2671 struct dhcp_opt
*opt
;
2674 struct token
*token
;
2682 while (ifo
->environ
[i
])
2683 free(ifo
->environ
[i
++]);
2688 while (ifo
->config
[i
])
2689 free(ifo
->config
[i
++]);
2693 #ifdef RT_FREE_ROUTE_TABLE
2694 /* Stupidly, we don't know the interface when creating the options.
2695 * As such, make sure each route has one so they can goto the
2697 ifp
= ctx
->ifaces
!= NULL
? TAILQ_FIRST(ctx
->ifaces
) : NULL
;
2699 RB_TREE_FOREACH(rt
, &ifo
->routes
) {
2700 if (rt
->rt_ifp
== NULL
)
2705 rt_headclear0(ctx
, &ifo
->routes
, AF_UNSPEC
);
2708 free(ifo
->blacklist
);
2709 free(ifo
->fallback
);
2711 for (opt
= ifo
->dhcp_override
;
2712 ifo
->dhcp_override_len
> 0;
2713 opt
++, ifo
->dhcp_override_len
--)
2714 free_dhcp_opt_embenc(opt
);
2715 free(ifo
->dhcp_override
);
2716 for (opt
= ifo
->nd_override
;
2717 ifo
->nd_override_len
> 0;
2718 opt
++, ifo
->nd_override_len
--)
2719 free_dhcp_opt_embenc(opt
);
2720 free(ifo
->nd_override
);
2721 for (opt
= ifo
->dhcp6_override
;
2722 ifo
->dhcp6_override_len
> 0;
2723 opt
++, ifo
->dhcp6_override_len
--)
2724 free_dhcp_opt_embenc(opt
);
2725 free(ifo
->dhcp6_override
);
2726 for (vo
= ifo
->vivco
;
2728 vo
++, ifo
->vivco_len
--)
2731 for (opt
= ifo
->vivso_override
;
2732 ifo
->vivso_override_len
> 0;
2733 opt
++, ifo
->vivso_override_len
--)
2734 free_dhcp_opt_embenc(opt
);
2735 free(ifo
->vivso_override
);
2737 #if defined(INET6) && !defined(SMALL)
2738 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2739 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2744 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2745 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2746 if (token
->realm_len
)