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"
53 #include "if-options.h"
58 #define IN_CONFIG_BLOCK(ifo) ((ifo)->options & DHCPCD_FORKED)
59 #define SET_CONFIG_BLOCK(ifo) ((ifo)->options |= DHCPCD_FORKED)
60 #define CLEAR_CONFIG_BLOCK(ifo) ((ifo)->options &= ~DHCPCD_FORKED)
62 static unsigned long long default_options
;
64 const struct option cf_options
[] = {
65 {"background", no_argument
, NULL
, 'b'},
66 {"script", required_argument
, NULL
, 'c'},
67 {"debug", no_argument
, NULL
, 'd'},
68 {"env", required_argument
, NULL
, 'e'},
69 {"config", required_argument
, NULL
, 'f'},
70 {"reconfigure", no_argument
, NULL
, 'g'},
71 {"hostname", optional_argument
, NULL
, 'h'},
72 {"vendorclassid", optional_argument
, NULL
, 'i'},
73 {"logfile", required_argument
, NULL
, 'j'},
74 {"release", no_argument
, NULL
, 'k'},
75 {"leasetime", required_argument
, NULL
, 'l'},
76 {"metric", required_argument
, NULL
, 'm'},
77 {"rebind", no_argument
, NULL
, 'n'},
78 {"option", required_argument
, NULL
, 'o'},
79 {"persistent", no_argument
, NULL
, 'p'},
80 {"quiet", no_argument
, NULL
, 'q'},
81 {"request", optional_argument
, NULL
, 'r'},
82 {"inform", optional_argument
, NULL
, 's'},
83 {"inform6", optional_argument
, NULL
, O_INFORM6
},
84 {"timeout", required_argument
, NULL
, 't'},
85 {"userclass", required_argument
, NULL
, 'u'},
87 {"msuserclass", required_argument
, NULL
, O_MSUSERCLASS
},
89 {"vendor", required_argument
, NULL
, 'v'},
90 {"waitip", optional_argument
, NULL
, 'w'},
91 {"exit", no_argument
, NULL
, 'x'},
92 {"allowinterfaces", required_argument
, NULL
, 'z'},
93 {"reboot", required_argument
, NULL
, 'y'},
94 {"noarp", no_argument
, NULL
, 'A'},
95 {"nobackground", no_argument
, NULL
, 'B'},
96 {"nohook", required_argument
, NULL
, 'C'},
97 {"duid", no_argument
, NULL
, 'D'},
98 {"lastlease", no_argument
, NULL
, 'E'},
99 {"fqdn", optional_argument
, NULL
, 'F'},
100 {"nogateway", no_argument
, NULL
, 'G'},
101 {"xidhwaddr", no_argument
, NULL
, 'H'},
102 {"clientid", optional_argument
, NULL
, 'I'},
103 {"broadcast", no_argument
, NULL
, 'J'},
104 {"nolink", no_argument
, NULL
, 'K'},
105 {"noipv4ll", no_argument
, NULL
, 'L'},
106 {"master", no_argument
, NULL
, 'M'},
107 {"renew", no_argument
, NULL
, 'N'},
108 {"nooption", required_argument
, NULL
, 'O'},
109 {"printpidfile", no_argument
, NULL
, 'P'},
110 {"require", required_argument
, NULL
, 'Q'},
111 {"static", required_argument
, NULL
, 'S'},
112 {"test", no_argument
, NULL
, 'T'},
113 {"dumplease", no_argument
, NULL
, 'U'},
114 {"variables", no_argument
, NULL
, 'V'},
115 {"whitelist", required_argument
, NULL
, 'W'},
116 {"blacklist", required_argument
, NULL
, 'X'},
117 {"denyinterfaces", required_argument
, NULL
, 'Z'},
118 {"oneshot", no_argument
, NULL
, '1'},
119 {"ipv4only", no_argument
, NULL
, '4'},
120 {"ipv6only", no_argument
, NULL
, '6'},
121 {"anonymous", no_argument
, NULL
, O_ANONYMOUS
},
122 {"arping", required_argument
, NULL
, O_ARPING
},
123 {"destination", required_argument
, NULL
, O_DESTINATION
},
124 {"fallback", required_argument
, NULL
, O_FALLBACK
},
125 {"ipv6rs", no_argument
, NULL
, O_IPV6RS
},
126 {"noipv6rs", no_argument
, NULL
, O_NOIPV6RS
},
127 {"ipv6ra_autoconf", no_argument
, NULL
, O_IPV6RA_AUTOCONF
},
128 {"ipv6ra_noautoconf", no_argument
, NULL
, O_IPV6RA_NOAUTOCONF
},
129 {"ipv6ra_fork", no_argument
, NULL
, O_IPV6RA_FORK
},
130 {"ipv4", no_argument
, NULL
, O_IPV4
},
131 {"noipv4", no_argument
, NULL
, O_NOIPV4
},
132 {"ipv6", no_argument
, NULL
, O_IPV6
},
133 {"noipv6", no_argument
, NULL
, O_NOIPV6
},
134 {"noalias", no_argument
, NULL
, O_NOALIAS
},
135 {"iaid", required_argument
, NULL
, O_IAID
},
136 {"ia_na", no_argument
, NULL
, O_IA_NA
},
137 {"ia_ta", no_argument
, NULL
, O_IA_TA
},
138 {"ia_pd", no_argument
, NULL
, O_IA_PD
},
139 {"hostname_short", no_argument
, NULL
, O_HOSTNAME_SHORT
},
140 {"dev", required_argument
, NULL
, O_DEV
},
141 {"nodev", no_argument
, NULL
, O_NODEV
},
142 {"define", required_argument
, NULL
, O_DEFINE
},
143 {"definend", required_argument
, NULL
, O_DEFINEND
},
144 {"define6", required_argument
, NULL
, O_DEFINE6
},
145 {"embed", required_argument
, NULL
, O_EMBED
},
146 {"encap", required_argument
, NULL
, O_ENCAP
},
147 {"vendopt", required_argument
, NULL
, O_VENDOPT
},
148 {"vendclass", required_argument
, NULL
, O_VENDCLASS
},
149 {"authprotocol", required_argument
, NULL
, O_AUTHPROTOCOL
},
150 {"authtoken", required_argument
, NULL
, O_AUTHTOKEN
},
151 {"noauthrequired", no_argument
, NULL
, O_AUTHNOTREQUIRED
},
152 {"dhcp", no_argument
, NULL
, O_DHCP
},
153 {"nodhcp", no_argument
, NULL
, O_NODHCP
},
154 {"dhcp6", no_argument
, NULL
, O_DHCP6
},
155 {"nodhcp6", no_argument
, NULL
, O_NODHCP6
},
156 {"controlgroup", required_argument
, NULL
, O_CONTROLGRP
},
157 {"slaac", required_argument
, NULL
, O_SLAAC
},
158 {"gateway", no_argument
, NULL
, O_GATEWAY
},
159 {"reject", required_argument
, NULL
, O_REJECT
},
160 {"bootp", no_argument
, NULL
, O_BOOTP
},
161 {"nodelay", no_argument
, NULL
, O_NODELAY
},
162 {"noup", no_argument
, NULL
, O_NOUP
},
163 {"lastleaseextend", no_argument
, NULL
, O_LASTLEASE_EXTEND
},
164 {"inactive", no_argument
, NULL
, O_INACTIVE
},
165 {"mudurl", required_argument
, NULL
, O_MUDURL
},
166 {"link_rcvbuf", required_argument
, NULL
, O_LINK_RCVBUF
},
167 {"poll", optional_argument
, NULL
, O_POLL
},
168 {NULL
, 0, NULL
, '\0'}
172 add_environ(char ***array
, const char *value
, int uniq
)
174 char **newlist
, **list
= *array
;
176 char *match
= NULL
, *p
, *n
;
178 match
= strdup(value
);
183 p
= strchr(match
, '=');
185 logerrx("%s: no assignment: %s", __func__
, value
);
192 while (list
&& list
[i
]) {
193 if (match
&& strncmp(list
[i
], match
, l
) == 0) {
204 /* Append a space and the value to it */
207 n
= realloc(list
[i
], l
+ lv
+ 2);
215 memcpy(list
[i
] + l
+ 1, p
, lv
);
216 list
[i
][l
+ lv
+ 1] = '\0';
230 newlist
= reallocarray(list
, i
+ 2, sizeof(char *));
231 if (newlist
== NULL
) {
237 newlist
[i
+ 1] = NULL
;
242 #define PARSE_STRING 0
243 #define PARSE_STRING_NULL 1
244 #define PARSE_HWADDR 2
245 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
246 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
247 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
249 parse_str(char *sbuf
, size_t slen
, const char *str
, int flags
)
256 end
= str
+ strlen(str
);
257 /* If surrounded by quotes then it's a string */
265 l
= (size_t)hwaddr_aton(NULL
, str
);
266 if ((ssize_t
) l
!= -1 && l
> 1) {
271 hwaddr_aton((uint8_t *)sbuf
, str
);
276 /* Process escapes */
278 /* If processing a string on the clientid, first byte should be
279 * 0 to indicate a non hardware type */
280 if (flags
== PARSE_HWADDR
&& *str
) {
287 if (++l
> slen
&& sbuf
) {
293 switch((cmd
= *str
++)) {
314 /* Grab a hex code */
316 for (i
= 0; i
< 2; i
++) {
317 if (isxdigit((unsigned char)*str
) == 0)
321 if (c
[1] != '\0' && sbuf
) {
323 *sbuf
++ = (char)strtol(c
, NULL
, 16);
328 /* Grab an octal code */
330 for (i
= 0; i
< 3; i
++) {
331 if (*str
< '0' || *str
> '7')
335 if (c
[2] != '\0' && sbuf
) {
336 i
= (int)strtol(c
, NULL
, 8);
354 if (flags
== PARSE_STRING_NULL
) {
368 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
374 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
378 memcpy(iaid
, &narg
, sizeof(narg
));
382 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
394 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
397 return parse_iaid1(iaid
, arg
, len
, 1);
402 parse_uint32(uint32_t *i
, const char *arg
)
405 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
410 splitv(int *argc
, char **argv
, const char *arg
)
412 char **n
, **v
= argv
;
413 char *o
= strdup(arg
), *p
, *t
, *nt
;
420 while ((t
= strsep(&p
, ", "))) {
427 n
= reallocarray(v
, (size_t)(*argc
) + 1, sizeof(char *));
443 parse_addr(struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
447 if (arg
== NULL
|| *arg
== '\0') {
454 if ((p
= strchr(arg
, '/')) != NULL
) {
459 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
461 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
463 logerrx("`%s' is not a valid CIDR", p
);
468 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
469 logerrx("`%s' is not a valid IP address", arg
);
474 else if (net
!= NULL
&& addr
!= NULL
)
475 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
480 parse_addr(__unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
481 __unused
const char *arg
)
484 logerrx("No IPv4 support");
490 set_option_space(struct dhcpcd_ctx
*ctx
,
492 const struct dhcp_opt
**d
, size_t *dl
,
493 const struct dhcp_opt
**od
, size_t *odl
,
494 struct if_options
*ifo
,
495 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
498 #if !defined(INET) && !defined(INET6)
503 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
505 *dl
= ctx
->nd_opts_len
;
506 *od
= ifo
->nd_override
;
507 *odl
= ifo
->nd_override_len
;
508 *request
= ifo
->requestmasknd
;
509 *require
= ifo
->requiremasknd
;
511 *reject
= ifo
->rejectmasknd
;
516 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
517 *d
= ctx
->dhcp6_opts
;
518 *dl
= ctx
->dhcp6_opts_len
;
519 *od
= ifo
->dhcp6_override
;
520 *odl
= ifo
->dhcp6_override_len
;
521 *request
= ifo
->requestmask6
;
522 *require
= ifo
->requiremask6
;
524 *reject
= ifo
->rejectmask6
;
534 *dl
= ctx
->dhcp_opts_len
;
535 *od
= ifo
->dhcp_override
;
536 *odl
= ifo
->dhcp_override_len
;
543 *request
= ifo
->requestmask
;
544 *require
= ifo
->requiremask
;
546 *reject
= ifo
->rejectmask
;
550 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
557 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
558 free_dhcp_opt_embenc(o
);
560 opt
->embopts_len
= 0;
563 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
564 free_dhcp_opt_embenc(o
);
566 opt
->encopts_len
= 0;
571 strwhite(const char *s
)
576 while (*s
!= ' ' && *s
!= '\t') {
585 strskipwhite(const char *s
)
588 if (s
== NULL
|| *s
== '\0')
590 while (*s
== ' ' || *s
== '\t') {
599 /* Find the end pointer of a string. */
601 strend(const char *s
)
608 return strchr(s
, ' ');
610 for (; *s
!= '"' ; s
++) {
623 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
624 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
629 char *p
= NULL
, *bp
, *fp
, *np
;
631 struct in_addr addr
, addr2
;
634 const struct dhcp_opt
*d
, *od
;
635 uint8_t *request
, *require
, *no
, *reject
;
636 struct dhcp_opt
**dop
, *ndop
;
637 size_t *dop_len
, dl
, odl
;
651 struct if_sla
*sla
, *slap
;
661 /* Add a guard for static analysers.
662 * This should not be needed really because of the argument_required option
663 * in the options declaration above. */
664 #define ARG_REQUIRED if (arg == NULL) goto arg_required
667 case 'f': /* FALLTHROUGH */
668 case 'g': /* FALLTHROUGH */
669 case 'n': /* FALLTHROUGH */
670 case 'q': /* FALLTHROUGH */
671 case 'x': /* FALLTHROUGH */
672 case 'N': /* FALLTHROUGH */
673 case 'P': /* FALLTHROUGH */
674 case 'T': /* FALLTHROUGH */
675 case 'U': /* FALLTHROUGH */
676 case 'V': /* We need to handle non interface options */
679 ifo
->options
|= DHCPCD_BACKGROUND
;
683 if (IN_CONFIG_BLOCK(ifo
)) {
684 logerrx("%s: per interface scripts"
685 " are no longer supported",
689 if (ctx
->script
!= dhcpcd_default_script
)
691 s
= parse_nstring(NULL
, 0, arg
);
697 if (s
== -1 || (ctx
->script
= malloc(dl
)) == NULL
) {
702 s
= parse_nstring(ctx
->script
, dl
, arg
);
704 ctx
->script
[0] == '\0' ||
705 strcmp(ctx
->script
, "/dev/null") == 0)
712 ifo
->options
|= DHCPCD_DEBUG
;
716 add_environ(&ifo
->environ
, arg
, 1);
720 ifo
->options
|= DHCPCD_HOSTNAME
;
723 s
= parse_nstring(ifo
->hostname
, sizeof(ifo
->hostname
), arg
);
725 logerr("%s: hostname", __func__
);
728 if (s
!= 0 && ifo
->hostname
[0] == '.') {
729 logerrx("hostname cannot begin with .");
732 if (ifo
->hostname
[0] == '\0')
733 ifo
->options
&= ~DHCPCD_HOSTNAME
;
735 ifo
->options
|= DHCPCD_HOSTNAME
;
739 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
740 VENDORCLASSID_MAX_LEN
, arg
);
744 logerr("vendorclassid");
747 *ifo
->vendorclassid
= (uint8_t)s
;
751 /* per interface logging is not supported
752 * don't want to overide the commandline */
753 if (!IN_CONFIG_BLOCK(ifo
) && ctx
->logfile
== NULL
) {
755 ctx
->logfile
= strdup(arg
);
756 logopen(ctx
->logfile
);
760 ifo
->options
|= DHCPCD_RELEASE
;
764 if (strcmp(arg
, "-1") == 0) {
765 ifo
->leasetime
= DHCP_INFINITE_LIFETIME
;
768 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
769 0, 0, UINT32_MAX
, &e
);
771 logerrx("failed to convert leasetime %s", arg
);
777 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
779 logerrx("failed to convert metric %s", arg
);
785 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
786 &request
, &require
, &no
, &reject
);
787 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
788 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
789 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
791 logerrx("unknown option `%s'", arg
);
797 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
798 &request
, &require
, &no
, &reject
);
799 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
800 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
801 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
803 logerrx("unknown option `%s'", arg
);
808 ifo
->options
|= DHCPCD_PERSISTENT
;
811 if (parse_addr(&ifo
->req_addr
, NULL
, arg
) != 0)
813 ifo
->options
|= DHCPCD_REQUEST
;
814 ifo
->req_mask
.s_addr
= 0;
817 if (arg
&& *arg
!= '\0') {
818 /* Strip out a broadcast address */
819 p
= strchr(arg
, '/');
821 p
= strchr(p
+ 1, '/');
825 i
= parse_addr(&ifo
->req_addr
, &ifo
->req_mask
, arg
);
827 /* Ensure the original string is preserved */
830 i
= parse_addr(&ifo
->req_brd
, NULL
, p
);
835 ifo
->req_addr
.s_addr
= 0;
836 ifo
->req_mask
.s_addr
= 0;
838 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
839 ifo
->options
&= ~DHCPCD_STATIC
;
842 ifo
->options
|= DHCPCD_INFORM6
;
846 ifo
->timeout
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
848 logerrx("failed to convert timeout %s", arg
);
853 dl
= sizeof(ifo
->userclass
) - ifo
->userclass
[0] - 1;
854 s
= parse_string((char *)ifo
->userclass
+
855 ifo
->userclass
[0] + 2, dl
, arg
);
861 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
862 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
867 /* Some Microsoft DHCP servers expect userclass to be an
868 * opaque blob. This is not RFC 3004 compliant. */
869 s
= parse_string((char *)ifo
->userclass
+ 1,
870 sizeof(ifo
->userclass
) - 1, arg
);
872 logerr("msuserclass");
875 ifo
->userclass
[0] = (uint8_t)s
;
880 p
= strchr(arg
, ',');
882 logerrx("invalid vendor format: %s", arg
);
886 /* If vendor starts with , then it is not encapsulated */
889 s
= parse_string((char *)ifo
->vendor
+ 1,
890 VENDOR_MAX_LEN
, arg
);
895 ifo
->vendor
[0] = (uint8_t)s
;
896 ifo
->options
|= DHCPCD_VENDORRAW
;
900 /* Encapsulated vendor options */
901 if (ifo
->options
& DHCPCD_VENDORRAW
) {
902 ifo
->options
&= ~DHCPCD_VENDORRAW
;
906 /* Strip and preserve the comma */
908 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
911 logerrx("vendor option should be between"
912 " 1 and 254 inclusive");
917 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
918 if (inet_aton(arg
, &addr
) == 1) {
923 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
924 &addr
.s_addr
, sizeof(addr
.s_addr
));
925 s
= sizeof(addr
.s_addr
);
928 s
= parse_string((char *)ifo
->vendor
+
929 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
936 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
937 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
938 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
942 ifo
->options
|= DHCPCD_WAITIP
;
943 if (arg
!= NULL
&& arg
[0] != '\0') {
944 if (arg
[0] == '4' || arg
[1] == '4')
945 ifo
->options
|= DHCPCD_WAITIP4
;
946 if (arg
[0] == '6' || arg
[1] == '6')
947 ifo
->options
|= DHCPCD_WAITIP6
;
952 ifo
->reboot
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
954 logerr("failed to convert reboot %s", arg
);
960 if (!IN_CONFIG_BLOCK(ifo
))
961 ctx
->ifav
= splitv(&ctx
->ifac
, ctx
->ifav
, arg
);
964 ifo
->options
&= ~DHCPCD_ARP
;
965 /* IPv4LL requires ARP */
966 ifo
->options
&= ~DHCPCD_IPV4LL
;
969 ifo
->options
&= ~DHCPCD_DAEMONISE
;
973 /* Commas to spaces for shell */
974 while ((p
= strchr(arg
, ',')))
976 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
977 p
= malloc(sizeof(char) * dl
);
982 snprintf(p
, dl
, "skip_hooks=%s", arg
);
983 add_environ(&ifo
->environ
, p
, 0);
987 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
990 ifo
->options
|= DHCPCD_LASTLEASE
;
994 ifo
->fqdn
= FQDN_BOTH
;
997 if (strcmp(arg
, "none") == 0)
998 ifo
->fqdn
= FQDN_NONE
;
999 else if (strcmp(arg
, "ptr") == 0)
1000 ifo
->fqdn
= FQDN_PTR
;
1001 else if (strcmp(arg
, "both") == 0)
1002 ifo
->fqdn
= FQDN_BOTH
;
1003 else if (strcmp(arg
, "disable") == 0)
1004 ifo
->fqdn
= FQDN_DISABLE
;
1006 logerrx("invalid value `%s' for FQDN", arg
);
1011 ifo
->options
&= ~DHCPCD_GATEWAY
;
1014 ifo
->options
|= DHCPCD_XID_HWADDR
;
1017 /* Strings have a type of 0 */;
1018 ifo
->clientid
[1] = 0;
1020 s
= parse_hwaddr((char *)ifo
->clientid
+ 1,
1021 CLIENTID_MAX_LEN
, arg
);
1028 ifo
->options
|= DHCPCD_CLIENTID
;
1029 ifo
->clientid
[0] = (uint8_t)s
;
1030 ifo
->options
&= ~DHCPCD_DUID
;
1033 ifo
->options
|= DHCPCD_BROADCAST
;
1036 ifo
->options
&= ~DHCPCD_LINK
;
1039 ifo
->options
&= ~DHCPCD_IPV4LL
;
1042 ifo
->options
|= DHCPCD_MASTER
;
1046 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1047 &request
, &require
, &no
, &reject
);
1048 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
1049 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1050 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1052 logerrx("unknown option `%s'", arg
);
1058 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1059 &request
, &require
, &no
, &reject
);
1060 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1061 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1062 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1063 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1065 logerrx("unknown option `%s'", arg
);
1071 p
= strchr(arg
, '=');
1073 logerrx("static assignment required");
1077 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1078 if (parse_addr(&ifo
->req_addr
,
1079 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1083 ifo
->options
|= DHCPCD_STATIC
;
1084 ifo
->options
&= ~DHCPCD_INFORM
;
1085 } else if (strncmp(arg
, "subnet_mask=",
1086 strlen("subnet_mask=")) == 0)
1088 if (parse_addr(&ifo
->req_mask
, NULL
, p
) != 0)
1090 } else if (strncmp(arg
, "broadcast_address=",
1091 strlen("broadcast_address=")) == 0)
1093 if (parse_addr(&ifo
->req_brd
, NULL
, p
) != 0)
1095 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1096 strncmp(arg
, "static_routes=",
1097 strlen("static_routes=")) == 0 ||
1098 strncmp(arg
, "classless_static_routes=",
1099 strlen("classless_static_routes=")) == 0 ||
1100 strncmp(arg
, "ms_classless_static_routes=",
1101 strlen("ms_classless_static_routes=")) == 0)
1103 struct in_addr addr3
;
1105 fp
= np
= strwhite(p
);
1107 logerrx("all routes need a gateway");
1111 np
= strskipwhite(np
);
1112 if (parse_addr(&addr
, &addr2
, p
) == -1 ||
1113 parse_addr(&addr3
, NULL
, np
) == -1)
1119 if ((rt
= rt_new0(ctx
)) == NULL
)
1121 sa_in_init(&rt
->rt_dest
, &addr
);
1122 sa_in_init(&rt
->rt_netmask
, &addr2
);
1123 sa_in_init(&rt
->rt_gateway
, &addr3
);
1124 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1125 add_environ(&ifo
->config
, arg
, 0);
1126 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1127 if (parse_addr(&addr
, NULL
, p
) == -1)
1129 if ((rt
= rt_new0(ctx
)) == NULL
)
1131 addr2
.s_addr
= INADDR_ANY
;
1132 sa_in_init(&rt
->rt_dest
, &addr2
);
1133 sa_in_init(&rt
->rt_netmask
, &addr2
);
1134 sa_in_init(&rt
->rt_gateway
, &addr
);
1135 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1136 add_environ(&ifo
->config
, arg
, 0);
1137 } else if (strncmp(arg
, "interface_mtu=",
1138 strlen("interface_mtu=")) == 0 ||
1139 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1141 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1142 MTU_MIN
, MTU_MAX
, &e
);
1144 logerrx("invalid MTU %s", p
);
1147 } else if (strncmp(arg
, "ip6_address=", strlen("ip6_address=")) == 0) {
1148 np
= strchr(p
, '/');
1151 if ((i
= inet_pton(AF_INET6
, p
, &ifo
->req_addr6
)) == 1) {
1153 ifo
->req_prefix_len
= (uint8_t)strtou(np
,
1154 NULL
, 0, 0, 128, &e
);
1156 logerrx("%s: failed to "
1157 "convert prefix len",
1162 ifo
->req_prefix_len
= 128;
1167 logerrx("invalid AF_INET6: %s", p
);
1168 memset(&ifo
->req_addr6
, 0,
1169 sizeof(ifo
->req_addr6
));
1173 add_environ(&ifo
->config
, arg
, 1);
1176 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1178 if (strchr(arg
, '/') == NULL
)
1179 addr2
.s_addr
= INADDR_BROADCAST
;
1180 naddr
= reallocarray(ifo
->whitelist
,
1181 ifo
->whitelist_len
+ 2, sizeof(in_addr_t
));
1182 if (naddr
== NULL
) {
1186 ifo
->whitelist
= naddr
;
1187 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1188 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1191 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1193 if (strchr(arg
, '/') == NULL
)
1194 addr2
.s_addr
= INADDR_BROADCAST
;
1195 naddr
= reallocarray(ifo
->blacklist
,
1196 ifo
->blacklist_len
+ 2, sizeof(in_addr_t
));
1197 if (naddr
== NULL
) {
1201 ifo
->blacklist
= naddr
;
1202 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1203 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1207 if (!IN_CONFIG_BLOCK(ifo
))
1208 ctx
->ifdv
= splitv(&ctx
->ifdc
, ctx
->ifdv
, arg
);
1211 ifo
->options
|= DHCPCD_ONESHOT
;
1215 ifo
->options
&= ~DHCPCD_IPV6
;
1216 ifo
->options
|= DHCPCD_IPV4
;
1219 logerrx("INET has been compiled out");
1224 ifo
->options
&= ~DHCPCD_IPV4
;
1225 ifo
->options
|= DHCPCD_IPV6
;
1228 logerrx("INET6 has been compiled out");
1232 ifo
->options
|= DHCPCD_IPV4
;
1235 ifo
->options
&= ~DHCPCD_IPV4
;
1238 ifo
->options
|= DHCPCD_IPV6
;
1241 ifo
->options
&= ~DHCPCD_IPV6
;
1244 ifo
->options
|= DHCPCD_ANONYMOUS
;
1245 ifo
->options
&= ~DHCPCD_HOSTNAME
;
1246 ifo
->fqdn
= FQDN_DISABLE
;
1248 /* Block everything */
1249 memset(ifo
->nomask
, 0xff, sizeof(ifo
->nomask
));
1250 memset(ifo
->nomask6
, 0xff, sizeof(ifo
->nomask6
));
1252 /* Allow the bare minimum through */
1254 del_option_mask(ifo
->nomask
, DHO_SUBNETMASK
);
1255 del_option_mask(ifo
->nomask
, DHO_CSR
);
1256 del_option_mask(ifo
->nomask
, DHO_ROUTER
);
1257 del_option_mask(ifo
->nomask
, DHO_DNSSERVER
);
1258 del_option_mask(ifo
->nomask
, DHO_DNSDOMAIN
);
1259 del_option_mask(ifo
->nomask
, DHO_BROADCAST
);
1260 del_option_mask(ifo
->nomask
, DHO_STATICROUTE
);
1261 del_option_mask(ifo
->nomask
, DHO_SERVERID
);
1262 del_option_mask(ifo
->nomask
, DHO_RENEWALTIME
);
1263 del_option_mask(ifo
->nomask
, DHO_REBINDTIME
);
1264 del_option_mask(ifo
->nomask
, DHO_DNSSEARCH
);
1268 del_option_mask(ifo
->nomask6
, D6_OPTION_DNS_SERVERS
);
1269 del_option_mask(ifo
->nomask6
, D6_OPTION_DOMAIN_LIST
);
1270 del_option_mask(ifo
->nomask6
, D6_OPTION_SOL_MAX_RT
);
1271 del_option_mask(ifo
->nomask6
, D6_OPTION_INF_MAX_RT
);
1277 while (arg
!= NULL
) {
1281 if (parse_addr(&addr
, NULL
, arg
) != 0)
1283 naddr
= reallocarray(ifo
->arping
,
1284 (size_t)ifo
->arping_len
+ 1, sizeof(in_addr_t
));
1285 if (naddr
== NULL
) {
1289 ifo
->arping
= naddr
;
1290 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1291 arg
= strskipwhite(fp
);
1296 set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1297 &request
, &require
, &no
, &reject
);
1298 if (make_option_mask(d
, dl
, od
, odl
,
1299 ifo
->dstmask
, arg
, 2) != 0)
1301 if (errno
== EINVAL
)
1302 logerrx("option `%s' does not take"
1303 " an IPv4 address", arg
);
1305 logerrx("unknown option `%s'", arg
);
1311 free(ifo
->fallback
);
1312 ifo
->fallback
= strdup(arg
);
1313 if (ifo
->fallback
== NULL
) {
1321 if (!IN_CONFIG_BLOCK(ifo
)) {
1322 logerrx("IAID must belong in an interface block");
1325 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1326 logerrx("invalid IAID %s", arg
);
1329 ifo
->options
|= DHCPCD_IAID
;
1332 ifo
->options
|= DHCPCD_IPV6RS
;
1335 ifo
->options
&= ~DHCPCD_IPV6RS
;
1338 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1340 case O_IPV6RA_AUTOCONF
:
1341 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1343 case O_IPV6RA_NOAUTOCONF
:
1344 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1347 ifo
->options
|= DHCPCD_NOALIAS
;
1351 i
= D6_OPTION_IA_NA
;
1355 i
= D6_OPTION_IA_TA
;
1360 logwarnx("%s: IA_PD not compiled in", ifname
);
1363 if (!IN_CONFIG_BLOCK(ifo
)) {
1364 logerrx("IA PD must belong in an "
1368 i
= D6_OPTION_IA_PD
;
1371 if (!IN_CONFIG_BLOCK(ifo
) && arg
) {
1372 logerrx("IA with IAID must belong in an "
1376 ifo
->options
|= DHCPCD_IA_FORCED
;
1380 fp
= strskipwhite(fp
);
1383 p
= strchr(arg
, '/');
1386 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1387 logerr("invalid IAID: %s", arg
);
1392 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1393 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1394 (arg
!= NULL
&& ifo
->ia
[sl
].iaid_set
&&
1395 ifo
->ia
[sl
].ia_type
== (uint16_t)i
&&
1396 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1397 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1398 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1399 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1406 ia
= reallocarray(ifo
->ia
,
1407 ifo
->ia_len
+ 1, sizeof(*ifo
->ia
));
1413 ia
= &ifo
->ia
[ifo
->ia_len
++];
1414 ia
->ia_type
= (uint16_t)i
;
1416 ia
->iaid
[0] = iaid
[0];
1417 ia
->iaid
[1] = iaid
[1];
1418 ia
->iaid
[2] = iaid
[2];
1419 ia
->iaid
[3] = iaid
[3];
1423 if (!ia
->iaid_set
||
1425 ia
->ia_type
== D6_OPTION_IA_TA
)
1427 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1431 p
= strchr(arg
, '/');
1434 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) != 1) {
1435 logerrx("invalid AF_INET6: %s", arg
);
1436 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1438 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1439 ia
->prefix_len
= (uint8_t)strtou(p
,
1440 NULL
, 0, 8, 120, &e
);
1442 logerrx("%s: failed to convert"
1459 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1462 for (p
= fp
; p
; p
= fp
) {
1466 fp
= strskipwhite(fp
);
1468 sla
= reallocarray(ia
->sla
,
1469 ia
->sla_len
+ 1, sizeof(*ia
->sla
));
1475 sla
= &ia
->sla
[ia
->sla_len
++];
1476 np
= strchr(p
, '/');
1479 if (strlcpy(sla
->ifname
, p
,
1480 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1482 logerrx("%s: interface name too long", arg
);
1485 sla
->sla_set
= false;
1486 sla
->prefix_len
= 0;
1490 np
= strchr(p
, '/');
1494 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1495 0, 0, UINT32_MAX
, &e
);
1496 sla
->sla_set
= true;
1498 logerrx("%s: failed to convert "
1507 np
= strchr(p
, '/');
1511 sla
->prefix_len
= (uint8_t)strtou(p
,
1512 NULL
, 0, 0, 120, &e
);
1514 logerrx("%s: failed to "
1515 "convert prefix len",
1523 np
= strchr(p
, '/');
1527 sla
->suffix
= (uint64_t)strtou(p
, NULL
,
1528 0, 0, UINT64_MAX
, &e
);
1530 logerrx("%s: failed to "
1538 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1539 slap
= &ia
->sla
[sl
];
1540 if (slap
->sla_set
!= sla
->sla_set
) {
1541 logerrx("%s: cannot mix automatic "
1546 if (ia
->prefix_len
&&
1547 (sla
->prefix_len
== ia
->prefix_len
||
1548 slap
->prefix_len
== ia
->prefix_len
))
1550 logerrx("%s: cannot delegte the same"
1551 "prefix length more than once",
1555 if (!sla
->sla_set
&&
1556 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1558 logwarnx("%s: cannot specify the "
1559 "same interface twice with "
1564 if (slap
->sla_set
&& sla
->sla_set
&&
1565 slap
->sla
== sla
->sla
)
1567 logerrx("%s: cannot"
1568 " assign the same SLA %u"
1570 sla
->ifname
, sla
->sla
);
1574 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1575 ia
->sla_max
= sla
->sla
;
1583 case O_HOSTNAME_SHORT
:
1584 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1590 free(ctx
->dev_load
);
1591 ctx
->dev_load
= strdup(arg
);
1595 ifo
->options
&= ~DHCPCD_DEV
;
1598 dop
= &ifo
->dhcp_override
;
1599 dop_len
= &ifo
->dhcp_override_len
;
1603 dop
= &ifo
->nd_override
;
1604 dop_len
= &ifo
->nd_override_len
;
1609 dop
= &ifo
->dhcp6_override
;
1610 dop_len
= &ifo
->dhcp6_override_len
;
1615 dop
= &ifo
->vivso_override
;
1616 dop_len
= &ifo
->vivso_override_len
;
1618 *edop
= *ldop
= NULL
;
1623 dop
= &(*edop
)->embopts
;
1624 dop_len
= &(*edop
)->embopts_len
;
1626 dop
= &(*ldop
)->embopts
;
1627 dop_len
= &(*ldop
)->embopts_len
;
1629 logerrx("embed must be after a define "
1638 if (*ldop
== NULL
) {
1639 logerrx("encap must be after a define");
1642 dop
= &(*ldop
)->encopts
;
1643 dop_len
= &(*ldop
)->encopts_len
;
1646 /* Shared code for define, define6, embed and encap */
1649 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1654 logerrx("invalid syntax: %s", arg
);
1658 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1660 logerrx("invalid code: %s", arg
);
1663 arg
= strskipwhite(fp
);
1665 logerrx("invalid syntax");
1673 np
= strchr(arg
, ':');
1677 bp
= NULL
; /* No bitflag */
1678 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1680 logerrx("failed to convert length");
1685 bp
= strchr(arg
, '='); /* bitflag assignment */
1690 if (strcasecmp(arg
, "request") == 0) {
1692 arg
= strskipwhite(fp
);
1695 logerrx("incomplete request type");
1699 } else if (strcasecmp(arg
, "norequest") == 0) {
1701 arg
= strskipwhite(fp
);
1704 logerrx("incomplete request type");
1709 if (strcasecmp(arg
, "optional") == 0) {
1711 arg
= strskipwhite(fp
);
1714 logerrx("incomplete optional type");
1719 if (strcasecmp(arg
, "index") == 0) {
1721 arg
= strskipwhite(fp
);
1724 logerrx("incomplete index type");
1729 if (strcasecmp(arg
, "array") == 0) {
1731 arg
= strskipwhite(fp
);
1734 logerrx("incomplete array type");
1739 if (strcasecmp(arg
, "ipaddress") == 0)
1741 else if (strcasecmp(arg
, "ip6address") == 0)
1743 else if (strcasecmp(arg
, "string") == 0)
1745 else if (strcasecmp(arg
, "byte") == 0)
1747 else if (strcasecmp(arg
, "bitflags") == 0)
1749 else if (strcasecmp(arg
, "uint8") == 0)
1751 else if (strcasecmp(arg
, "int8") == 0)
1753 else if (strcasecmp(arg
, "uint16") == 0)
1755 else if (strcasecmp(arg
, "int16") == 0)
1757 else if (strcasecmp(arg
, "uint32") == 0)
1759 else if (strcasecmp(arg
, "int32") == 0)
1761 else if (strcasecmp(arg
, "flag") == 0)
1763 else if (strcasecmp(arg
, "raw") == 0)
1764 t
|= OT_STRING
| OT_RAW
;
1765 else if (strcasecmp(arg
, "ascii") == 0)
1766 t
|= OT_STRING
| OT_ASCII
;
1767 else if (strcasecmp(arg
, "domain") == 0)
1768 t
|= OT_STRING
| OT_DOMAIN
| OT_RFC1035
;
1769 else if (strcasecmp(arg
, "dname") == 0)
1770 t
|= OT_STRING
| OT_DOMAIN
;
1771 else if (strcasecmp(arg
, "binhex") == 0)
1772 t
|= OT_STRING
| OT_BINHEX
;
1773 else if (strcasecmp(arg
, "embed") == 0)
1775 else if (strcasecmp(arg
, "encap") == 0)
1777 else if (strcasecmp(arg
, "rfc3361") ==0)
1778 t
|= OT_STRING
| OT_RFC3361
;
1779 else if (strcasecmp(arg
, "rfc3442") ==0)
1780 t
|= OT_STRING
| OT_RFC3442
;
1781 else if (strcasecmp(arg
, "option") == 0)
1784 logerrx("unknown type: %s", arg
);
1787 if (l
&& !(t
& (OT_STRING
| OT_BINHEX
))) {
1788 logwarnx("ignoring length for type `%s'", arg
);
1791 if (t
& OT_ARRAY
&& t
& (OT_STRING
| OT_BINHEX
) &&
1792 !(t
& (OT_RFC1035
| OT_DOMAIN
)))
1794 logwarnx("ignoring array for strings");
1797 if (t
& OT_BITFLAG
) {
1799 logwarnx("missing bitflag assignment");
1803 if (!(t
& OT_OPTION
)) {
1804 logerrx("type %s requires a variable name",
1810 arg
= strskipwhite(fp
);
1814 if (strcasecmp(arg
, "reserved")) {
1825 if (opt
!= O_EMBED
) {
1826 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1828 /* type 0 seems freshly malloced struct
1830 if (ndop
->option
== u
|| ndop
->type
== 0)
1838 ndop
= reallocarray(*dop
, *dop_len
+ 1, sizeof(**dop
));
1845 ndop
= &(*dop
)[(*dop_len
)++];
1846 ndop
->embopts
= NULL
;
1847 ndop
->embopts_len
= 0;
1848 ndop
->encopts
= NULL
;
1849 ndop
->encopts_len
= 0;
1851 free_dhcp_opt_embenc(ndop
);
1852 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1854 ndop
->len
= (size_t)l
;
1858 memcpy(ndop
->bitflags
, bp
, dl
);
1859 memset(ndop
->bitflags
+ dl
, 0,
1860 sizeof(ndop
->bitflags
) - dl
);
1862 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1863 /* Save the define for embed and encap options */
1881 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1883 logerrx("invalid code: %s", arg
);
1886 fp
= strskipwhite(fp
);
1888 s
= parse_string(NULL
, 0, fp
);
1894 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1895 logerrx("vendor class is too big");
1903 parse_string(np
, dl
, fp
);
1908 vivco
= reallocarray(ifo
->vivco
,
1909 ifo
->vivco_len
+ 1, sizeof(*ifo
->vivco
));
1910 if (vivco
== NULL
) {
1916 ifo
->vivco_en
= (uint32_t)u
;
1917 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
1919 vivco
->data
= (uint8_t *)np
;
1921 case O_AUTHPROTOCOL
:
1927 if (strcasecmp(arg
, "token") == 0)
1928 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
1929 else if (strcasecmp(arg
, "delayed") == 0)
1930 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
1931 else if (strcasecmp(arg
, "delayedrealm") == 0)
1932 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
1934 logerrx("%s: unsupported protocol", arg
);
1937 arg
= strskipwhite(fp
);
1940 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1941 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
)
1942 ifo
->auth
.protocol
= AUTH_ALG_NONE
;
1944 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1945 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1950 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
) {
1951 np
= strchr(arg
, '/');
1953 if (fp
== NULL
|| np
< fp
)
1958 if (parse_uint32(&ifo
->auth
.token_snd_secretid
,
1960 logerrx("%s: not a number", arg
);
1962 ifo
->auth
.token_rcv_secretid
=
1963 ifo
->auth
.token_snd_secretid
;
1965 parse_uint32(&ifo
->auth
.token_rcv_secretid
,
1967 logerrx("%s: not a number", arg
);
1969 if (strcasecmp(arg
, "hmacmd5") == 0 ||
1970 strcasecmp(arg
, "hmac-md5") == 0)
1971 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1973 logerrx("%s: unsupported algorithm", arg
);
1979 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1980 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1983 if (strcasecmp(arg
, "monocounter") == 0) {
1984 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1985 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
1986 } else if (strcasecmp(arg
, "monotonic") ==0 ||
1987 strcasecmp(arg
, "monotime") == 0)
1988 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1990 logerrx("%s: unsupported RDM", arg
);
1993 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1996 logerrx("no authentication support");
2004 logerrx("authtoken requires a realm");
2008 token
= calloc(1, sizeof(*token
));
2009 if (token
== NULL
) {
2013 if (parse_uint32(&token
->secretid
, arg
) == -1) {
2014 logerrx("%s: not a number", arg
);
2020 logerrx("authtoken requies an a key");
2024 s
= parse_string(NULL
, 0, arg
);
2026 logerr("realm_len");
2030 token
->realm_len
= (size_t)s
;
2031 token
->realm
= malloc(token
->realm_len
);
2032 if (token
->realm
== NULL
) {
2036 parse_string((char *)token
->realm
, token
->realm_len
,
2042 logerrx("authtoken requies an expiry date");
2048 np
= strchr(arg
, '"');
2052 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
2057 memset(&tm
, 0, sizeof(tm
));
2058 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
2059 logerrx("%s: invalid date time", arg
);
2062 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
2063 logerr("%s: mktime", __func__
);
2068 s
= parse_string(NULL
, 0, arg
);
2069 if (s
== -1 || s
== 0) {
2071 logerr("token_len");
2073 logerrx("authtoken needs a key");
2076 token
->key_len
= (size_t)s
;
2077 token
->key
= malloc(token
->key_len
);
2078 if (token
->key
== NULL
) {
2082 parse_string((char *)token
->key
, token
->key_len
, arg
);
2083 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
2090 logerrx("no authentication support");
2093 case O_AUTHNOTREQUIRED
:
2094 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
2097 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_WANTDHCP
| DHCPCD_IPV4
;
2100 ifo
->options
&= ~DHCPCD_DHCP
;
2103 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
2106 ifo
->options
&= ~DHCPCD_DHCP6
;
2111 /* Control group is already set by this point.
2112 * We don't need to pledge getpw either with this. */
2113 if (IN_PRIVSEP(ctx
))
2117 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
2127 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, dl
, &grp
)) ==
2132 logerrx("control_group: out of buffer");
2137 np
= realloc(p
, dl
);
2147 logerr("getgrnam_r");
2152 if (!ctx
->control_group
)
2153 logerrx("controlgroup: %s: not found", arg
);
2157 ctx
->control_group
= grp
->gr_gid
;
2160 grp
= getgrnam(arg
);
2162 if (!ctx
->control_group
)
2163 logerrx("controlgroup: %s: not found", arg
);
2166 ctx
->control_group
= grp
->gr_gid
;
2170 ifo
->options
|= DHCPCD_GATEWAY
;
2173 ifo
->options
&= ~DHCPCD_IF_UP
;
2180 np
= strskipwhite(np
);
2182 if (strcmp(arg
, "private") == 0 ||
2183 strcmp(arg
, "stableprivate") == 0 ||
2184 strcmp(arg
, "stable") == 0)
2185 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2187 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2189 (strcmp(np
, "temp") == 0 || strcmp(np
, "temporary") == 0))
2190 ifo
->options
|= DHCPCD_SLAACTEMP
;
2193 ifo
->options
|= DHCPCD_BOOTP
;
2196 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2198 case O_LASTLEASE_EXTEND
:
2199 ifo
->options
|= DHCPCD_LASTLEASE
| DHCPCD_LASTLEASE_EXTEND
;
2202 ifo
->options
|= DHCPCD_INACTIVE
;
2206 s
= parse_string((char *)ifo
->mudurl
+ 1, MUDURL_MAX_LEN
, arg
);
2211 *ifo
->mudurl
= (uint8_t)s
;
2216 ctx
->link_rcvbuf
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
2218 logerrx("failed to convert link_rcvbuf %s", arg
);
2225 ifo
->poll
= IF_POLL_UP
;
2228 ifo
->poll
= (unsigned long)
2229 strtou(arg
, NULL
, 0, 0, ULONG_MAX
, &e
);
2231 logerrx("failed to convert poll %s", arg
);
2243 logerrx("option %d requires an argument", opt
);
2250 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2251 struct if_options
*ifo
, const char *opt
, char *line
,
2252 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2256 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2257 if (!cf_options
[i
].name
||
2258 strcmp(cf_options
[i
].name
, opt
) != 0)
2261 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2262 logerrx("option requires an argument -- %s", opt
);
2266 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2270 logerrx("unknown option: %s", opt
);
2275 finish_config(struct if_options
*ifo
)
2278 /* Terminate the encapsulated options */
2279 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2281 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2282 /* We are called twice.
2283 * This should be fixed, but in the meantime, this
2284 * guard should suffice */
2285 ifo
->options
|= DHCPCD_VENDORRAW
;
2288 if (!(ifo
->options
& DHCPCD_ARP
) ||
2289 ifo
->options
& (DHCPCD_INFORM
| DHCPCD_STATIC
))
2290 ifo
->options
&= ~DHCPCD_IPV4LL
;
2292 if (!(ifo
->options
& DHCPCD_IPV4
))
2293 ifo
->options
&= ~(DHCPCD_DHCP
| DHCPCD_IPV4LL
| DHCPCD_WAITIP4
);
2295 if (!(ifo
->options
& DHCPCD_IPV6
))
2297 ~(DHCPCD_IPV6RS
| DHCPCD_DHCP6
| DHCPCD_WAITIP6
);
2299 if (!(ifo
->options
& DHCPCD_IPV6RS
))
2301 ~(DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
);
2305 default_config(struct dhcpcd_ctx
*ctx
)
2307 struct if_options
*ifo
;
2309 /* Seed our default options */
2310 if ((ifo
= calloc(1, sizeof(*ifo
))) == NULL
) {
2314 ifo
->options
|= DHCPCD_IF_UP
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2315 ifo
->timeout
= DEFAULT_TIMEOUT
;
2316 ifo
->reboot
= DEFAULT_REBOOT
;
2318 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2319 rb_tree_init(&ifo
->routes
, &rt_compare_list_ops
);
2321 TAILQ_INIT(&ifo
->auth
.tokens
);
2324 /* Inherit some global defaults */
2325 if (ctx
->options
& DHCPCD_PERSISTENT
)
2326 ifo
->options
|= DHCPCD_PERSISTENT
;
2327 if (ctx
->options
& DHCPCD_SLAACPRIVATE
)
2328 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2334 read_config(struct dhcpcd_ctx
*ctx
,
2335 const char *ifname
, const char *ssid
, const char *profile
)
2337 struct if_options
*ifo
;
2338 char buf
[UDPLEN_MAX
], *bp
; /* 64k max config file size */
2339 char *line
, *option
, *p
;
2342 int skip
, have_profile
, new_block
, had_block
;
2343 #if !defined(INET) || !defined(INET6)
2345 struct dhcp_opt
*opt
;
2347 struct dhcp_opt
*ldop
, *edop
;
2349 /* Seed our default options */
2350 if ((ifo
= default_config(ctx
)) == NULL
)
2352 if (default_options
== 0) {
2353 default_options
|= DHCPCD_DAEMONISE
| DHCPCD_GATEWAY
;
2355 skip
= socket(PF_INET
, SOCK_DGRAM
, 0);
2358 default_options
|= DHCPCD_IPV4
| DHCPCD_ARP
|
2359 DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2363 skip
= socket(PF_INET6
, SOCK_DGRAM
, 0);
2366 default_options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
|
2367 DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
|
2372 default_options
|= DHCPCD_DEV
;
2375 ifo
->options
|= default_options
;
2377 CLEAR_CONFIG_BLOCK(ifo
);
2379 vlen
= strlcpy((char *)ifo
->vendorclassid
+ 1, ctx
->vendor
,
2380 sizeof(ifo
->vendorclassid
) - 1);
2381 ifo
->vendorclassid
[0] = (uint8_t)(vlen
> 255 ? 0 : vlen
);
2383 /* Reset route order */
2386 /* Parse our embedded options file */
2387 if (ifname
== NULL
&& !(ctx
->options
& DHCPCD_PRINT_PIDFILE
)) {
2388 /* Space for initial estimates */
2389 #if defined(INET) && defined(INITDEFINES)
2390 ifo
->dhcp_override
=
2391 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2392 if (ifo
->dhcp_override
== NULL
)
2395 ifo
->dhcp_override_len
= INITDEFINES
;
2398 #if defined(INET6) && defined(INITDEFINENDS)
2400 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2401 if (ifo
->nd_override
== NULL
)
2404 ifo
->nd_override_len
= INITDEFINENDS
;
2406 #if defined(INET6) && defined(INITDEFINE6S)
2407 ifo
->dhcp6_override
=
2408 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2409 if (ifo
->dhcp6_override
== NULL
)
2412 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2415 /* Now load our embedded config */
2416 #ifdef EMBEDDED_CONFIG
2417 buflen
= dhcp_readfile(ctx
, EMBEDDED_CONFIG
, buf
, sizeof(buf
));
2419 logerr("%s: %s", __func__
, EMBEDDED_CONFIG
);
2422 if (buf
[buflen
- 1] != '\0') {
2423 if ((size_t)buflen
< sizeof(buf
) - 1)
2425 buf
[buflen
- 1] = '\0';
2428 buflen
= (ssize_t
)strlcpy(buf
, dhcpcd_embedded_conf
,
2430 if ((size_t)buflen
>= sizeof(buf
)) {
2431 logerrx("%s: embedded config too big", __func__
);
2434 /* Our embedded config is NULL terminated */
2437 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2438 option
= strsep(&line
, " \t");
2440 line
= strskipwhite(line
);
2441 /* Trim trailing whitespace */
2443 p
= line
+ strlen(line
) - 1;
2445 (*p
== ' ' || *p
== '\t') &&
2449 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2454 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2455 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2457 for (i
= 0, opt
= ifo
->dhcp_override
;
2458 i
< ifo
->dhcp_override_len
;
2460 free_dhcp_opt_embenc(opt
);
2461 free(ifo
->dhcp_override
);
2463 ifo
->dhcp_override
= NULL
;
2464 ifo
->dhcp_override_len
= 0;
2467 ctx
->nd_opts
= ifo
->nd_override
;
2468 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2470 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2471 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2474 for (i
= 0, opt
= ifo
->nd_override
;
2475 i
< ifo
->nd_override_len
;
2477 free_dhcp_opt_embenc(opt
);
2478 free(ifo
->nd_override
);
2479 for (i
= 0, opt
= ifo
->dhcp6_override
;
2480 i
< ifo
->dhcp6_override_len
;
2482 free_dhcp_opt_embenc(opt
);
2483 free(ifo
->dhcp6_override
);
2485 ifo
->nd_override
= NULL
;
2486 ifo
->nd_override_len
= 0;
2487 ifo
->dhcp6_override
= NULL
;
2488 ifo
->dhcp6_override_len
= 0;
2490 ctx
->vivso
= ifo
->vivso_override
;
2491 ctx
->vivso_len
= ifo
->vivso_override_len
;
2492 ifo
->vivso_override
= NULL
;
2493 ifo
->vivso_override_len
= 0;
2496 /* Parse our options file */
2497 buflen
= dhcp_readfile(ctx
, ctx
->cffile
, buf
, sizeof(buf
));
2499 /* dhcpcd can continue without it, but no DNS options
2500 * would be requested ... */
2501 logerr("%s: %s", __func__
, ctx
->cffile
);
2504 if (buf
[buflen
- 1] != '\0') {
2505 if ((size_t)buflen
< sizeof(buf
) - 1)
2507 buf
[buflen
- 1] = '\0';
2509 dhcp_filemtime(ctx
, ctx
->cffile
, &ifo
->mtime
);
2512 skip
= have_profile
= new_block
= 0;
2513 had_block
= ifname
== NULL
? 1 : 0;
2515 while ((line
= get_line(&bp
, &buflen
)) != NULL
) {
2516 option
= strsep(&line
, " \t");
2518 line
= strskipwhite(line
);
2519 /* Trim trailing whitespace */
2521 p
= line
+ strlen(line
) - 1;
2523 (*p
== ' ' || *p
== '\t') &&
2527 if (skip
== 0 && new_block
) {
2530 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2531 SET_CONFIG_BLOCK(ifo
);
2534 /* Start of an interface block, skip if not ours */
2535 if (strcmp(option
, "interface") == 0) {
2540 /* No interface given */
2544 if (ifname
&& strcmp(line
, ifname
) == 0)
2551 n
= reallocarray(ctx
->ifcv
,
2552 (size_t)ctx
->ifcc
+ 1, sizeof(char *));
2558 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2559 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2566 /* Start of an ssid block, skip if not ours */
2567 if (strcmp(option
, "ssid") == 0) {
2569 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2575 /* Start of a profile block, skip if not ours */
2576 if (strcmp(option
, "profile") == 0) {
2578 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2585 /* Skip arping if we have selected a profile but not parsing
2587 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2592 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2595 if (profile
&& !have_profile
) {
2596 free_options(ctx
, ifo
);
2602 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2603 CLEAR_CONFIG_BLOCK(ifo
);
2609 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2610 struct if_options
*ifo
, int argc
, char **argv
)
2613 unsigned long long wait_opts
;
2620 /* Don't apply the command line wait options to each interface,
2621 * only use the dhcpcd.conf entry for that. */
2623 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2624 while ((opt
= getopt_long(argc
, argv
,
2625 ctx
->options
& DHCPCD_PRINT_PIDFILE
? NOERR_IF_OPTS
: IF_OPTS
,
2626 cf_options
, &oi
)) != -1)
2628 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2632 if (ifname
!= NULL
) {
2633 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2634 ifo
->options
|= wait_opts
;
2642 free_options(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
)
2645 #ifdef RT_FREE_ROUTE_TABLE
2646 struct interface
*ifp
;
2649 struct dhcp_opt
*opt
;
2652 struct token
*token
;
2660 while (ifo
->environ
[i
])
2661 free(ifo
->environ
[i
++]);
2666 while (ifo
->config
[i
])
2667 free(ifo
->config
[i
++]);
2671 #ifdef RT_FREE_ROUTE_TABLE
2672 /* Stupidly, we don't know the interface when creating the options.
2673 * As such, make sure each route has one so they can goto the
2675 ifp
= ctx
->ifaces
!= NULL
? TAILQ_FIRST(ctx
->ifaces
) : NULL
;
2677 RB_TREE_FOREACH(rt
, &ifo
->routes
) {
2678 if (rt
->rt_ifp
== NULL
)
2683 rt_headclear0(ctx
, &ifo
->routes
, AF_UNSPEC
);
2686 free(ifo
->blacklist
);
2687 free(ifo
->fallback
);
2689 for (opt
= ifo
->dhcp_override
;
2690 ifo
->dhcp_override_len
> 0;
2691 opt
++, ifo
->dhcp_override_len
--)
2692 free_dhcp_opt_embenc(opt
);
2693 free(ifo
->dhcp_override
);
2694 for (opt
= ifo
->nd_override
;
2695 ifo
->nd_override_len
> 0;
2696 opt
++, ifo
->nd_override_len
--)
2697 free_dhcp_opt_embenc(opt
);
2698 free(ifo
->nd_override
);
2699 for (opt
= ifo
->dhcp6_override
;
2700 ifo
->dhcp6_override_len
> 0;
2701 opt
++, ifo
->dhcp6_override_len
--)
2702 free_dhcp_opt_embenc(opt
);
2703 free(ifo
->dhcp6_override
);
2704 for (vo
= ifo
->vivco
;
2706 vo
++, ifo
->vivco_len
--)
2709 for (opt
= ifo
->vivso_override
;
2710 ifo
->vivso_override_len
> 0;
2711 opt
++, ifo
->vivso_override_len
--)
2712 free_dhcp_opt_embenc(opt
);
2713 free(ifo
->vivso_override
);
2715 #if defined(INET6) && !defined(SMALL)
2716 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2717 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2722 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2723 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2724 if (token
->realm_len
)