1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2019 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>
31 #include <sys/types.h>
33 #include <arpa/inet.h>
52 #include "dhcpcd-embedded.h"
54 #include "if-options.h"
59 /* These options only make sense in the config file, so don't use any
60 valid short options for them */
61 #define O_BASE MAX('z', 'Z') + 1
62 #define O_ARPING O_BASE + 1
63 #define O_FALLBACK O_BASE + 2
64 #define O_DESTINATION O_BASE + 3
65 #define O_IPV6RS O_BASE + 4
66 #define O_NOIPV6RS O_BASE + 5
67 #define O_IPV6RA_FORK O_BASE + 6
68 #define O_LINK_RCVBUF O_BASE + 7
70 #define O_NOALIAS O_BASE + 9
71 #define O_IA_NA O_BASE + 10
72 #define O_IA_TA O_BASE + 11
73 #define O_IA_PD O_BASE + 12
74 #define O_HOSTNAME_SHORT O_BASE + 13
75 #define O_DEV O_BASE + 14
76 #define O_NODEV O_BASE + 15
77 #define O_NOIPV4 O_BASE + 16
78 #define O_NOIPV6 O_BASE + 17
79 #define O_IAID O_BASE + 18
80 #define O_DEFINE O_BASE + 19
81 #define O_DEFINE6 O_BASE + 20
82 #define O_EMBED O_BASE + 21
83 #define O_ENCAP O_BASE + 22
84 #define O_VENDOPT O_BASE + 23
85 #define O_VENDCLASS O_BASE + 24
86 #define O_AUTHPROTOCOL O_BASE + 25
87 #define O_AUTHTOKEN O_BASE + 26
88 #define O_AUTHNOTREQUIRED O_BASE + 27
89 #define O_NODHCP O_BASE + 28
90 #define O_NODHCP6 O_BASE + 29
91 #define O_DHCP O_BASE + 30
92 #define O_DHCP6 O_BASE + 31
93 #define O_IPV4 O_BASE + 32
94 #define O_IPV6 O_BASE + 33
95 #define O_CONTROLGRP O_BASE + 34
96 #define O_SLAAC O_BASE + 35
97 #define O_GATEWAY O_BASE + 36
98 #define O_NOUP O_BASE + 37
99 #define O_IPV6RA_AUTOCONF O_BASE + 38
100 #define O_IPV6RA_NOAUTOCONF O_BASE + 39
101 #define O_REJECT O_BASE + 40
102 #define O_BOOTP O_BASE + 42
103 #define O_DEFINEND O_BASE + 43
104 #define O_NODELAY O_BASE + 44
105 #define O_INFORM6 O_BASE + 45
106 #define O_LASTLEASE_EXTEND O_BASE + 46
107 #define O_INACTIVE O_BASE + 47
108 #define O_MUDURL O_BASE + 48
110 const struct option cf_options
[] = {
111 {"background", no_argument
, NULL
, 'b'},
112 {"script", required_argument
, NULL
, 'c'},
113 {"debug", no_argument
, NULL
, 'd'},
114 {"env", required_argument
, NULL
, 'e'},
115 {"config", required_argument
, NULL
, 'f'},
116 {"reconfigure", no_argument
, NULL
, 'g'},
117 {"hostname", optional_argument
, NULL
, 'h'},
118 {"vendorclassid", optional_argument
, NULL
, 'i'},
119 {"logfile", required_argument
, NULL
, 'j'},
120 {"release", no_argument
, NULL
, 'k'},
121 {"leasetime", required_argument
, NULL
, 'l'},
122 {"metric", required_argument
, NULL
, 'm'},
123 {"rebind", no_argument
, NULL
, 'n'},
124 {"option", required_argument
, NULL
, 'o'},
125 {"persistent", no_argument
, NULL
, 'p'},
126 {"quiet", no_argument
, NULL
, 'q'},
127 {"request", optional_argument
, NULL
, 'r'},
128 {"inform", optional_argument
, NULL
, 's'},
129 {"inform6", optional_argument
, NULL
, O_INFORM6
},
130 {"timeout", required_argument
, NULL
, 't'},
131 {"userclass", required_argument
, NULL
, 'u'},
132 {"vendor", required_argument
, NULL
, 'v'},
133 {"waitip", optional_argument
, NULL
, 'w'},
134 {"exit", no_argument
, NULL
, 'x'},
135 {"allowinterfaces", required_argument
, NULL
, 'z'},
136 {"reboot", required_argument
, NULL
, 'y'},
137 {"noarp", no_argument
, NULL
, 'A'},
138 {"nobackground", no_argument
, NULL
, 'B'},
139 {"nohook", required_argument
, NULL
, 'C'},
140 {"duid", no_argument
, NULL
, 'D'},
141 {"lastlease", no_argument
, NULL
, 'E'},
142 {"fqdn", optional_argument
, NULL
, 'F'},
143 {"nogateway", no_argument
, NULL
, 'G'},
144 {"xidhwaddr", no_argument
, NULL
, 'H'},
145 {"clientid", optional_argument
, NULL
, 'I'},
146 {"broadcast", no_argument
, NULL
, 'J'},
147 {"nolink", no_argument
, NULL
, 'K'},
148 {"noipv4ll", no_argument
, NULL
, 'L'},
149 {"master", no_argument
, NULL
, 'M'},
150 {"renew", no_argument
, NULL
, 'N'},
151 {"nooption", required_argument
, NULL
, 'O'},
152 {"printpidfile", no_argument
, NULL
, 'P'},
153 {"require", required_argument
, NULL
, 'Q'},
154 {"static", required_argument
, NULL
, 'S'},
155 {"test", no_argument
, NULL
, 'T'},
156 {"dumplease", no_argument
, NULL
, 'U'},
157 {"variables", no_argument
, NULL
, 'V'},
158 {"whitelist", required_argument
, NULL
, 'W'},
159 {"blacklist", required_argument
, NULL
, 'X'},
160 {"denyinterfaces", required_argument
, NULL
, 'Z'},
161 {"oneshot", no_argument
, NULL
, '1'},
162 {"ipv4only", no_argument
, NULL
, '4'},
163 {"ipv6only", no_argument
, NULL
, '6'},
164 {"arping", required_argument
, NULL
, O_ARPING
},
165 {"destination", required_argument
, NULL
, O_DESTINATION
},
166 {"fallback", required_argument
, NULL
, O_FALLBACK
},
167 {"ipv6rs", no_argument
, NULL
, O_IPV6RS
},
168 {"noipv6rs", no_argument
, NULL
, O_NOIPV6RS
},
169 {"ipv6ra_autoconf", no_argument
, NULL
, O_IPV6RA_AUTOCONF
},
170 {"ipv6ra_noautoconf", no_argument
, NULL
, O_IPV6RA_NOAUTOCONF
},
171 {"ipv6ra_fork", no_argument
, NULL
, O_IPV6RA_FORK
},
172 {"ipv4", no_argument
, NULL
, O_IPV4
},
173 {"noipv4", no_argument
, NULL
, O_NOIPV4
},
174 {"ipv6", no_argument
, NULL
, O_IPV6
},
175 {"noipv6", no_argument
, NULL
, O_NOIPV6
},
176 {"noalias", no_argument
, NULL
, O_NOALIAS
},
177 {"iaid", required_argument
, NULL
, O_IAID
},
178 {"ia_na", no_argument
, NULL
, O_IA_NA
},
179 {"ia_ta", no_argument
, NULL
, O_IA_TA
},
180 {"ia_pd", no_argument
, NULL
, O_IA_PD
},
181 {"hostname_short", no_argument
, NULL
, O_HOSTNAME_SHORT
},
182 {"dev", required_argument
, NULL
, O_DEV
},
183 {"nodev", no_argument
, NULL
, O_NODEV
},
184 {"define", required_argument
, NULL
, O_DEFINE
},
185 {"definend", required_argument
, NULL
, O_DEFINEND
},
186 {"define6", required_argument
, NULL
, O_DEFINE6
},
187 {"embed", required_argument
, NULL
, O_EMBED
},
188 {"encap", required_argument
, NULL
, O_ENCAP
},
189 {"vendopt", required_argument
, NULL
, O_VENDOPT
},
190 {"vendclass", required_argument
, NULL
, O_VENDCLASS
},
191 {"authprotocol", required_argument
, NULL
, O_AUTHPROTOCOL
},
192 {"authtoken", required_argument
, NULL
, O_AUTHTOKEN
},
193 {"noauthrequired", no_argument
, NULL
, O_AUTHNOTREQUIRED
},
194 {"dhcp", no_argument
, NULL
, O_DHCP
},
195 {"nodhcp", no_argument
, NULL
, O_NODHCP
},
196 {"dhcp6", no_argument
, NULL
, O_DHCP6
},
197 {"nodhcp6", no_argument
, NULL
, O_NODHCP6
},
198 {"controlgroup", required_argument
, NULL
, O_CONTROLGRP
},
199 {"slaac", required_argument
, NULL
, O_SLAAC
},
200 {"gateway", no_argument
, NULL
, O_GATEWAY
},
201 {"reject", required_argument
, NULL
, O_REJECT
},
202 {"bootp", no_argument
, NULL
, O_BOOTP
},
203 {"nodelay", no_argument
, NULL
, O_NODELAY
},
204 {"noup", no_argument
, NULL
, O_NOUP
},
205 {"lastleaseextend", no_argument
, NULL
, O_LASTLEASE_EXTEND
},
206 {"inactive", no_argument
, NULL
, O_INACTIVE
},
207 {"mudurl", required_argument
, NULL
, O_MUDURL
},
208 {"link_rcvbuf", required_argument
, NULL
, O_LINK_RCVBUF
},
209 {NULL
, 0, NULL
, '\0'}
212 static const char *default_script
= SCRIPT
;
215 add_environ(char ***array
, const char *value
, int uniq
)
217 char **newlist
, **list
= *array
;
219 char *match
= NULL
, *p
, *n
;
221 match
= strdup(value
);
226 p
= strchr(match
, '=');
228 logerrx("%s: no assignment: %s", __func__
, value
);
235 while (list
&& list
[i
]) {
236 if (match
&& strncmp(list
[i
], match
, l
) == 0) {
247 /* Append a space and the value to it */
250 n
= realloc(list
[i
], l
+ lv
+ 2);
258 memcpy(list
[i
] + l
+ 1, p
, lv
);
259 list
[i
][l
+ lv
+ 1] = '\0';
273 newlist
= reallocarray(list
, i
+ 2, sizeof(char *));
274 if (newlist
== NULL
) {
280 newlist
[i
+ 1] = NULL
;
285 #define PARSE_STRING 0
286 #define PARSE_STRING_NULL 1
287 #define PARSE_HWADDR 2
288 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
289 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
291 parse_str(char *sbuf
, size_t slen
, const char *str
, int flags
)
298 end
= str
+ strlen(str
);
299 /* If surrounded by quotes then it's a string */
307 l
= (size_t)hwaddr_aton(NULL
, str
);
308 if ((ssize_t
) l
!= -1 && l
> 1) {
313 hwaddr_aton((uint8_t *)sbuf
, str
);
318 /* Process escapes */
320 /* If processing a string on the clientid, first byte should be
321 * 0 to indicate a non hardware type */
322 if (flags
== PARSE_HWADDR
&& *str
) {
329 if (++l
> slen
&& sbuf
) {
335 switch((cmd
= *str
++)) {
356 /* Grab a hex code */
358 for (i
= 0; i
< 2; i
++) {
359 if (isxdigit((unsigned char)*str
) == 0)
363 if (c
[1] != '\0' && sbuf
) {
365 *sbuf
++ = (char)strtol(c
, NULL
, 16);
370 /* Grab an octal code */
372 for (i
= 0; i
< 3; i
++) {
373 if (*str
< '0' || *str
> '7')
377 if (c
[2] != '\0' && sbuf
) {
378 i
= (int)strtol(c
, NULL
, 8);
396 if (flags
== PARSE_STRING_NULL
&& sbuf
)
402 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
408 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
412 memcpy(iaid
, &narg
, sizeof(narg
));
416 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
428 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
431 return parse_iaid1(iaid
, arg
, len
, 1);
436 parse_uint32(uint32_t *i
, const char *arg
)
439 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
444 splitv(int *argc
, char **argv
, const char *arg
)
446 char **n
, **v
= argv
;
447 char *o
= strdup(arg
), *p
, *t
, *nt
;
454 while ((t
= strsep(&p
, ", "))) {
461 n
= reallocarray(v
, (size_t)(*argc
) + 1, sizeof(char *));
477 parse_addr(struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
481 if (arg
== NULL
|| *arg
== '\0') {
488 if ((p
= strchr(arg
, '/')) != NULL
) {
493 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
495 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
497 logerrx("`%s' is not a valid CIDR", p
);
502 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
503 logerrx("`%s' is not a valid IP address", arg
);
508 else if (net
!= NULL
&& addr
!= NULL
)
509 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
514 parse_addr(__unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
515 __unused
const char *arg
)
518 logerrx("No IPv4 support");
524 set_option_space(struct dhcpcd_ctx
*ctx
,
526 const struct dhcp_opt
**d
, size_t *dl
,
527 const struct dhcp_opt
**od
, size_t *odl
,
528 struct if_options
*ifo
,
529 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
532 #if !defined(INET) && !defined(INET6)
537 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
539 *dl
= ctx
->nd_opts_len
;
540 *od
= ifo
->nd_override
;
541 *odl
= ifo
->nd_override_len
;
542 *request
= ifo
->requestmasknd
;
543 *require
= ifo
->requiremasknd
;
545 *reject
= ifo
->rejectmasknd
;
546 return arg
+ strlen("nd_");
550 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
551 *d
= ctx
->dhcp6_opts
;
552 *dl
= ctx
->dhcp6_opts_len
;
553 *od
= ifo
->dhcp6_override
;
554 *odl
= ifo
->dhcp6_override_len
;
555 *request
= ifo
->requestmask6
;
556 *require
= ifo
->requiremask6
;
558 *reject
= ifo
->rejectmask6
;
559 return arg
+ strlen("dhcp6_");
566 *dl
= ctx
->dhcp_opts_len
;
567 *od
= ifo
->dhcp_override
;
568 *odl
= ifo
->dhcp_override_len
;
575 *request
= ifo
->requestmask
;
576 *require
= ifo
->requiremask
;
578 *reject
= ifo
->rejectmask
;
583 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
590 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
591 free_dhcp_opt_embenc(o
);
593 opt
->embopts_len
= 0;
596 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
597 free_dhcp_opt_embenc(o
);
599 opt
->encopts_len
= 0;
604 strwhite(const char *s
)
609 while (*s
!= ' ' && *s
!= '\t') {
618 strskipwhite(const char *s
)
621 if (s
== NULL
|| *s
== '\0')
623 while (*s
== ' ' || *s
== '\t') {
632 /* Find the end pointer of a string. */
634 strend(const char *s
)
641 return strchr(s
, ' ');
643 for (; *s
!= '"' ; s
++) {
656 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
657 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
662 char *p
= NULL
, *bp
, *fp
, *np
;
664 struct in_addr addr
, addr2
;
667 const struct dhcp_opt
*d
, *od
;
668 uint8_t *request
, *require
, *no
, *reject
;
669 struct dhcp_opt
**dop
, *ndop
;
670 size_t *dop_len
, dl
, odl
;
684 struct if_sla
*sla
, *slap
;
694 /* Add a guard for static analysers.
695 * This should not be needed really because of the argument_required option
696 * in the options declaration above. */
697 #define ARG_REQUIRED if (arg == NULL) goto arg_required
700 case 'f': /* FALLTHROUGH */
701 case 'g': /* FALLTHROUGH */
702 case 'n': /* FALLTHROUGH */
703 case 'q': /* FALLTHROUGH */
704 case 'x': /* FALLTHROUGH */
705 case 'N': /* FALLTHROUGH */
706 case 'P': /* FALLTHROUGH */
707 case 'T': /* FALLTHROUGH */
708 case 'U': /* FALLTHROUGH */
709 case 'V': /* We need to handle non interface options */
712 ifo
->options
|= DHCPCD_BACKGROUND
;
716 if (ifo
->script
!= default_script
)
718 s
= parse_str(NULL
, 0, arg
, PARSE_STRING_NULL
);
724 if (s
== -1 || (ifo
->script
= malloc(dl
)) == NULL
) {
729 s
= parse_str(ifo
->script
, dl
, arg
, PARSE_STRING_NULL
);
731 ifo
->script
[0] == '\0' ||
732 strcmp(ifo
->script
, "/dev/null") == 0)
739 ifo
->options
|= DHCPCD_DEBUG
;
743 add_environ(&ifo
->environ
, arg
, 1);
747 ifo
->options
|= DHCPCD_HOSTNAME
;
750 s
= parse_string(ifo
->hostname
, HOSTNAME_MAX_LEN
, arg
);
752 logerr("%s: hostname", __func__
);
755 if (s
!= 0 && ifo
->hostname
[0] == '.') {
756 logerrx("hostname cannot begin with .");
759 ifo
->hostname
[s
] = '\0';
760 if (ifo
->hostname
[0] == '\0')
761 ifo
->options
&= ~DHCPCD_HOSTNAME
;
763 ifo
->options
|= DHCPCD_HOSTNAME
;
767 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
768 VENDORCLASSID_MAX_LEN
, arg
);
772 logerr("vendorclassid");
775 *ifo
->vendorclassid
= (uint8_t)s
;
779 /* per interface logging is not supported
780 * don't want to overide the commandline */
781 if (ifname
== NULL
&& ctx
->logfile
== NULL
) {
783 ctx
->logfile
= strdup(arg
);
784 logopen(ctx
->logfile
);
788 ifo
->options
|= DHCPCD_RELEASE
;
792 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
793 0, 0, UINT32_MAX
, &e
);
795 logerrx("failed to convert leasetime %s", arg
);
801 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
803 logerrx("failed to convert metric %s", arg
);
809 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
810 &request
, &require
, &no
, &reject
);
811 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
812 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
813 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
815 logerrx("unknown option `%s'", arg
);
821 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
822 &request
, &require
, &no
, &reject
);
823 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
824 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
825 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
827 logerrx("unknown option `%s'", arg
);
832 ifo
->options
|= DHCPCD_PERSISTENT
;
835 if (parse_addr(&ifo
->req_addr
, NULL
, arg
) != 0)
837 ifo
->options
|= DHCPCD_REQUEST
;
838 ifo
->req_mask
.s_addr
= 0;
841 if (arg
&& *arg
!= '\0') {
842 /* Strip out a broadcast address */
843 p
= strchr(arg
, '/');
845 p
= strchr(p
+ 1, '/');
849 i
= parse_addr(&ifo
->req_addr
, &ifo
->req_mask
, arg
);
851 /* Ensure the original string is preserved */
854 i
= parse_addr(&ifo
->req_brd
, NULL
, p
);
859 ifo
->req_addr
.s_addr
= 0;
860 ifo
->req_mask
.s_addr
= 0;
862 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
863 ifo
->options
&= ~DHCPCD_STATIC
;
866 ifo
->options
|= DHCPCD_INFORM6
;
870 ifo
->timeout
= (time_t)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
872 logerrx("failed to convert timeout %s", arg
);
877 s
= USERCLASS_MAX_LEN
- ifo
->userclass
[0] - 1;
878 s
= parse_string((char *)ifo
->userclass
+
879 ifo
->userclass
[0] + 2, (size_t)s
, arg
);
885 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
886 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
891 p
= strchr(arg
, ',');
893 logerrx("invalid vendor format: %s", arg
);
897 /* If vendor starts with , then it is not encapsulated */
900 s
= parse_string((char *)ifo
->vendor
+ 1,
901 VENDOR_MAX_LEN
, arg
);
906 ifo
->vendor
[0] = (uint8_t)s
;
907 ifo
->options
|= DHCPCD_VENDORRAW
;
911 /* Encapsulated vendor options */
912 if (ifo
->options
& DHCPCD_VENDORRAW
) {
913 ifo
->options
&= ~DHCPCD_VENDORRAW
;
917 /* Strip and preserve the comma */
919 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
922 logerrx("vendor option should be between"
923 " 1 and 254 inclusive");
928 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
929 if (inet_aton(arg
, &addr
) == 1) {
934 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
935 &addr
.s_addr
, sizeof(addr
.s_addr
));
936 s
= sizeof(addr
.s_addr
);
939 s
= parse_string((char *)ifo
->vendor
+
940 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
947 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
948 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
949 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
953 ifo
->options
|= DHCPCD_WAITIP
;
954 if (arg
!= NULL
&& arg
[0] != '\0') {
955 if (arg
[0] == '4' || arg
[1] == '4')
956 ifo
->options
|= DHCPCD_WAITIP4
;
957 if (arg
[0] == '6' || arg
[1] == '6')
958 ifo
->options
|= DHCPCD_WAITIP6
;
963 ifo
->reboot
= (time_t)strtoi(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
965 logerr("failed to convert reboot %s", arg
);
972 ctx
->ifav
= splitv(&ctx
->ifac
, ctx
->ifav
, arg
);
975 ifo
->options
&= ~DHCPCD_ARP
;
976 /* IPv4LL requires ARP */
977 ifo
->options
&= ~DHCPCD_IPV4LL
;
980 ifo
->options
&= ~DHCPCD_DAEMONISE
;
984 /* Commas to spaces for shell */
985 while ((p
= strchr(arg
, ',')))
987 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
988 p
= malloc(sizeof(char) * dl
);
993 snprintf(p
, dl
, "skip_hooks=%s", arg
);
994 add_environ(&ifo
->environ
, p
, 0);
998 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
1001 ifo
->options
|= DHCPCD_LASTLEASE
;
1005 ifo
->fqdn
= FQDN_BOTH
;
1008 if (strcmp(arg
, "none") == 0)
1009 ifo
->fqdn
= FQDN_NONE
;
1010 else if (strcmp(arg
, "ptr") == 0)
1011 ifo
->fqdn
= FQDN_PTR
;
1012 else if (strcmp(arg
, "both") == 0)
1013 ifo
->fqdn
= FQDN_BOTH
;
1014 else if (strcmp(arg
, "disable") == 0)
1015 ifo
->fqdn
= FQDN_DISABLE
;
1017 logerrx("invalid value `%s' for FQDN", arg
);
1022 ifo
->options
&= ~DHCPCD_GATEWAY
;
1025 ifo
->options
|= DHCPCD_XID_HWADDR
;
1028 /* Strings have a type of 0 */;
1029 ifo
->clientid
[1] = 0;
1031 s
= parse_hwaddr((char *)ifo
->clientid
+ 1,
1032 CLIENTID_MAX_LEN
, arg
);
1039 ifo
->options
|= DHCPCD_CLIENTID
;
1040 ifo
->clientid
[0] = (uint8_t)s
;
1043 ifo
->options
|= DHCPCD_BROADCAST
;
1046 ifo
->options
&= ~DHCPCD_LINK
;
1049 ifo
->options
&= ~DHCPCD_IPV4LL
;
1052 ifo
->options
|= DHCPCD_MASTER
;
1056 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1057 &request
, &require
, &no
, &reject
);
1058 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
1059 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1060 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1062 logerrx("unknown option `%s'", arg
);
1068 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1069 &request
, &require
, &no
, &reject
);
1070 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1071 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1072 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1073 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1075 logerrx("unknown option `%s'", arg
);
1081 p
= strchr(arg
, '=');
1083 logerrx("static assignment required");
1087 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1088 if (parse_addr(&ifo
->req_addr
,
1089 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1093 ifo
->options
|= DHCPCD_STATIC
;
1094 ifo
->options
&= ~DHCPCD_INFORM
;
1095 } else if (strncmp(arg
, "subnet_mask=",
1096 strlen("subnet_mask=")) == 0)
1098 if (parse_addr(&ifo
->req_mask
, NULL
, p
) != 0)
1100 } else if (strncmp(arg
, "broadcast_address=",
1101 strlen("broadcast_address=")) == 0)
1103 if (parse_addr(&ifo
->req_brd
, NULL
, p
) != 0)
1105 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1106 strncmp(arg
, "static_routes=",
1107 strlen("static_routes=")) == 0 ||
1108 strncmp(arg
, "classless_static_routes=",
1109 strlen("classless_static_routes=")) == 0 ||
1110 strncmp(arg
, "ms_classless_static_routes=",
1111 strlen("ms_classless_static_routes=")) == 0)
1113 struct in_addr addr3
;
1115 fp
= np
= strwhite(p
);
1117 logerrx("all routes need a gateway");
1121 np
= strskipwhite(np
);
1122 if (parse_addr(&addr
, &addr2
, p
) == -1 ||
1123 parse_addr(&addr3
, NULL
, np
) == -1)
1129 if ((rt
= rt_new0(ctx
)) == NULL
)
1131 sa_in_init(&rt
->rt_dest
, &addr
);
1132 sa_in_init(&rt
->rt_netmask
, &addr2
);
1133 sa_in_init(&rt
->rt_gateway
, &addr3
);
1134 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1135 add_environ(&ifo
->config
, arg
, 0);
1136 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1137 if (parse_addr(&addr
, NULL
, p
) == -1)
1139 if ((rt
= rt_new0(ctx
)) == NULL
)
1141 addr2
.s_addr
= INADDR_ANY
;
1142 sa_in_init(&rt
->rt_dest
, &addr2
);
1143 sa_in_init(&rt
->rt_netmask
, &addr2
);
1144 sa_in_init(&rt
->rt_gateway
, &addr
);
1145 if (rt_proto_add_ctx(&ifo
->routes
, rt
, ctx
))
1146 add_environ(&ifo
->config
, arg
, 0);
1147 } else if (strncmp(arg
, "interface_mtu=",
1148 strlen("interface_mtu=")) == 0 ||
1149 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1151 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1152 MTU_MIN
, MTU_MAX
, &e
);
1154 logerrx("invalid MTU %s", p
);
1157 } else if (strncmp(arg
, "ip6_address=", strlen("ip6_address=")) == 0) {
1158 np
= strchr(p
, '/');
1161 if (inet_pton(AF_INET6
, p
, &ifo
->req_addr6
) == 1) {
1163 ifo
->req_prefix_len
= (uint8_t)strtou(np
,
1164 NULL
, 0, 0, 128, &e
);
1166 logerrx("%s: failed to "
1167 "convert prefix len",
1172 ifo
->req_prefix_len
= 128;
1175 add_environ(&ifo
->config
, arg
, 1);
1178 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1180 if (strchr(arg
, '/') == NULL
)
1181 addr2
.s_addr
= INADDR_BROADCAST
;
1182 naddr
= reallocarray(ifo
->whitelist
,
1183 ifo
->whitelist_len
+ 2, sizeof(in_addr_t
));
1184 if (naddr
== NULL
) {
1188 ifo
->whitelist
= naddr
;
1189 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1190 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1193 if (parse_addr(&addr
, &addr2
, arg
) != 0)
1195 if (strchr(arg
, '/') == NULL
)
1196 addr2
.s_addr
= INADDR_BROADCAST
;
1197 naddr
= reallocarray(ifo
->blacklist
,
1198 ifo
->blacklist_len
+ 2, sizeof(in_addr_t
));
1199 if (naddr
== NULL
) {
1203 ifo
->blacklist
= naddr
;
1204 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1205 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1210 ctx
->ifdv
= splitv(&ctx
->ifdc
, ctx
->ifdv
, arg
);
1213 ifo
->options
|= DHCPCD_ONESHOT
;
1216 ifo
->options
&= ~DHCPCD_IPV6
;
1217 ifo
->options
|= DHCPCD_IPV4
;
1220 ifo
->options
&= ~DHCPCD_IPV4
;
1221 ifo
->options
|= DHCPCD_IPV6
;
1224 ifo
->options
|= DHCPCD_IPV4
;
1227 ifo
->options
&= ~DHCPCD_IPV4
;
1230 ifo
->options
|= DHCPCD_IPV6
;
1233 ifo
->options
&= ~DHCPCD_IPV6
;
1237 while (arg
!= NULL
) {
1241 if (parse_addr(&addr
, NULL
, arg
) != 0)
1243 naddr
= reallocarray(ifo
->arping
,
1244 (size_t)ifo
->arping_len
+ 1, sizeof(in_addr_t
));
1245 if (naddr
== NULL
) {
1249 ifo
->arping
= naddr
;
1250 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1251 arg
= strskipwhite(fp
);
1256 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1257 &request
, &require
, &no
, &reject
);
1258 if (make_option_mask(d
, dl
, od
, odl
,
1259 ifo
->dstmask
, arg
, 2) != 0)
1261 if (errno
== EINVAL
)
1262 logerrx("option `%s' does not take"
1263 " an IPv4 address", arg
);
1265 logerrx("unknown option `%s'", arg
);
1271 free(ifo
->fallback
);
1272 ifo
->fallback
= strdup(arg
);
1273 if (ifo
->fallback
== NULL
) {
1281 if (ifname
== NULL
) {
1282 logerrx("IAID must belong in an interface block");
1285 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1286 logerrx("invalid IAID %s", arg
);
1289 ifo
->options
|= DHCPCD_IAID
;
1292 ifo
->options
|= DHCPCD_IPV6RS
;
1295 ifo
->options
&= ~DHCPCD_IPV6RS
;
1298 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1300 case O_IPV6RA_AUTOCONF
:
1301 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1303 case O_IPV6RA_NOAUTOCONF
:
1304 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1307 ifo
->options
|= DHCPCD_NOALIAS
;
1311 i
= D6_OPTION_IA_NA
;
1315 i
= D6_OPTION_IA_TA
;
1320 logwarnx("%s: IA_PD not compiled in", ifname
);
1323 if (ifname
== NULL
) {
1324 logerrx("IA PD must belong in an "
1328 i
= D6_OPTION_IA_PD
;
1331 if (ifname
== NULL
&& arg
) {
1332 logerrx("IA with IAID must belong in an "
1336 ifo
->options
|= DHCPCD_IA_FORCED
;
1340 fp
= strskipwhite(fp
);
1343 p
= strchr(arg
, '/');
1346 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1347 logerr("invalid IAID: %s", arg
);
1352 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1353 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1354 (arg
!= NULL
&& ifo
->ia
[sl
].iaid_set
&&
1355 ifo
->ia
[sl
].ia_type
== (uint16_t)i
&&
1356 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1357 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1358 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1359 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1366 ia
= reallocarray(ifo
->ia
,
1367 ifo
->ia_len
+ 1, sizeof(*ifo
->ia
));
1373 ia
= &ifo
->ia
[ifo
->ia_len
++];
1374 ia
->ia_type
= (uint16_t)i
;
1376 ia
->iaid
[0] = iaid
[0];
1377 ia
->iaid
[1] = iaid
[1];
1378 ia
->iaid
[2] = iaid
[2];
1379 ia
->iaid
[3] = iaid
[3];
1383 if (!ia
->iaid_set
||
1385 ia
->ia_type
== D6_OPTION_IA_TA
)
1387 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1391 p
= strchr(arg
, '/');
1394 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) == -1) {
1396 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1398 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1399 ia
->prefix_len
= (uint8_t)strtou(p
,
1400 NULL
, 0, 8, 120, &e
);
1402 logerrx("%s: failed to convert"
1419 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1422 for (p
= fp
; p
; p
= fp
) {
1426 fp
= strskipwhite(fp
);
1428 sla
= reallocarray(ia
->sla
,
1429 ia
->sla_len
+ 1, sizeof(*ia
->sla
));
1435 sla
= &ia
->sla
[ia
->sla_len
++];
1436 np
= strchr(p
, '/');
1439 if (strlcpy(sla
->ifname
, p
,
1440 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1442 logerrx("%s: interface name too long", arg
);
1446 sla
->prefix_len
= 0;
1450 np
= strchr(p
, '/');
1454 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1455 0, 0, UINT32_MAX
, &e
);
1458 logerrx("%s: failed to convert "
1467 np
= strchr(p
, '/');
1471 sla
->prefix_len
= (uint8_t)strtou(p
,
1472 NULL
, 0, 0, 120, &e
);
1474 logerrx("%s: failed to "
1475 "convert prefix len",
1483 np
= strchr(p
, '/');
1487 sla
->suffix
= (uint64_t)strtou(p
, NULL
,
1488 0, 0, UINT64_MAX
, &e
);
1490 logerrx("%s: failed to "
1498 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1499 slap
= &ia
->sla
[sl
];
1500 if (slap
->sla_set
!= sla
->sla_set
) {
1501 logerrx("%s: cannot mix automatic "
1506 if (ia
->prefix_len
&&
1507 (sla
->prefix_len
== ia
->prefix_len
||
1508 slap
->prefix_len
== ia
->prefix_len
))
1510 logerrx("%s: cannot delegte the same"
1511 "prefix length more than once",
1515 if (sla
->sla_set
== 0 &&
1516 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1518 logwarnx("%s: cannot specify the "
1519 "same interface twice with "
1524 if (slap
->sla_set
&& sla
->sla_set
&&
1525 slap
->sla
== sla
->sla
)
1527 logerrx("%s: cannot"
1528 " assign the same SLA %u"
1530 sla
->ifname
, sla
->sla
);
1534 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1535 ia
->sla_max
= sla
->sla
;
1543 case O_HOSTNAME_SHORT
:
1544 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1550 free(ctx
->dev_load
);
1551 ctx
->dev_load
= strdup(arg
);
1555 ifo
->options
&= ~DHCPCD_DEV
;
1558 dop
= &ifo
->dhcp_override
;
1559 dop_len
= &ifo
->dhcp_override_len
;
1563 dop
= &ifo
->nd_override
;
1564 dop_len
= &ifo
->nd_override_len
;
1569 dop
= &ifo
->dhcp6_override
;
1570 dop_len
= &ifo
->dhcp6_override_len
;
1575 dop
= &ifo
->vivso_override
;
1576 dop_len
= &ifo
->vivso_override_len
;
1578 *edop
= *ldop
= NULL
;
1583 dop
= &(*edop
)->embopts
;
1584 dop_len
= &(*edop
)->embopts_len
;
1586 dop
= &(*ldop
)->embopts
;
1587 dop_len
= &(*ldop
)->embopts_len
;
1589 logerrx("embed must be after a define "
1598 if (*ldop
== NULL
) {
1599 logerrx("encap must be after a define");
1602 dop
= &(*ldop
)->encopts
;
1603 dop_len
= &(*ldop
)->encopts_len
;
1606 /* Shared code for define, define6, embed and encap */
1609 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1614 logerrx("invalid syntax: %s", arg
);
1618 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1620 logerrx("invalid code: %s", arg
);
1623 arg
= strskipwhite(fp
);
1625 logerrx("invalid syntax");
1633 np
= strchr(arg
, ':');
1637 bp
= NULL
; /* No bitflag */
1638 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1640 logerrx("failed to convert length");
1645 bp
= strchr(arg
, '='); /* bitflag assignment */
1650 if (strcasecmp(arg
, "request") == 0) {
1652 arg
= strskipwhite(fp
);
1655 logerrx("incomplete request type");
1659 } else if (strcasecmp(arg
, "norequest") == 0) {
1661 arg
= strskipwhite(fp
);
1664 logerrx("incomplete request type");
1669 if (strcasecmp(arg
, "optional") == 0) {
1671 arg
= strskipwhite(fp
);
1674 logerrx("incomplete optional type");
1679 if (strcasecmp(arg
, "index") == 0) {
1681 arg
= strskipwhite(fp
);
1684 logerrx("incomplete index type");
1689 if (strcasecmp(arg
, "array") == 0) {
1691 arg
= strskipwhite(fp
);
1694 logerrx("incomplete array type");
1699 if (strcasecmp(arg
, "ipaddress") == 0)
1701 else if (strcasecmp(arg
, "ip6address") == 0)
1703 else if (strcasecmp(arg
, "string") == 0)
1705 else if (strcasecmp(arg
, "byte") == 0)
1707 else if (strcasecmp(arg
, "bitflags") == 0)
1709 else if (strcasecmp(arg
, "uint8") == 0)
1711 else if (strcasecmp(arg
, "int8") == 0)
1713 else if (strcasecmp(arg
, "uint16") == 0)
1715 else if (strcasecmp(arg
, "int16") == 0)
1717 else if (strcasecmp(arg
, "uint32") == 0)
1719 else if (strcasecmp(arg
, "int32") == 0)
1721 else if (strcasecmp(arg
, "flag") == 0)
1723 else if (strcasecmp(arg
, "raw") == 0)
1724 t
|= OT_STRING
| OT_RAW
;
1725 else if (strcasecmp(arg
, "ascii") == 0)
1726 t
|= OT_STRING
| OT_ASCII
;
1727 else if (strcasecmp(arg
, "domain") == 0)
1728 t
|= OT_STRING
| OT_DOMAIN
| OT_RFC1035
;
1729 else if (strcasecmp(arg
, "dname") == 0)
1730 t
|= OT_STRING
| OT_DOMAIN
;
1731 else if (strcasecmp(arg
, "binhex") == 0)
1732 t
|= OT_STRING
| OT_BINHEX
;
1733 else if (strcasecmp(arg
, "embed") == 0)
1735 else if (strcasecmp(arg
, "encap") == 0)
1737 else if (strcasecmp(arg
, "rfc3361") ==0)
1738 t
|= OT_STRING
| OT_RFC3361
;
1739 else if (strcasecmp(arg
, "rfc3442") ==0)
1740 t
|= OT_STRING
| OT_RFC3442
;
1741 else if (strcasecmp(arg
, "option") == 0)
1744 logerrx("unknown type: %s", arg
);
1747 if (l
&& !(t
& (OT_STRING
| OT_BINHEX
))) {
1748 logwarnx("ignoring length for type `%s'", arg
);
1751 if (t
& OT_ARRAY
&& t
& (OT_STRING
| OT_BINHEX
) &&
1752 !(t
& (OT_RFC1035
| OT_DOMAIN
)))
1754 logwarnx("ignoring array for strings");
1757 if (t
& OT_BITFLAG
) {
1759 logwarnx("missing bitflag assignment");
1763 if (!(t
& OT_OPTION
)) {
1764 logerrx("type %s requires a variable name",
1770 arg
= strskipwhite(fp
);
1774 if (strcasecmp(arg
, "reserved")) {
1785 if (opt
!= O_EMBED
) {
1786 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1788 /* type 0 seems freshly malloced struct
1790 if (ndop
->option
== u
|| ndop
->type
== 0)
1798 ndop
= reallocarray(*dop
, *dop_len
+ 1, sizeof(**dop
));
1805 ndop
= &(*dop
)[(*dop_len
)++];
1806 ndop
->embopts
= NULL
;
1807 ndop
->embopts_len
= 0;
1808 ndop
->encopts
= NULL
;
1809 ndop
->encopts_len
= 0;
1811 free_dhcp_opt_embenc(ndop
);
1812 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1814 ndop
->len
= (size_t)l
;
1818 memcpy(ndop
->bitflags
, bp
, dl
);
1819 memset(ndop
->bitflags
+ dl
, 0,
1820 sizeof(ndop
->bitflags
) - dl
);
1822 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1823 /* Save the define for embed and encap options */
1841 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1843 logerrx("invalid code: %s", arg
);
1846 fp
= strskipwhite(fp
);
1848 s
= parse_string(NULL
, 0, fp
);
1854 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1855 logerrx("vendor class is too big");
1863 parse_string(np
, dl
, fp
);
1868 vivco
= reallocarray(ifo
->vivco
,
1869 ifo
->vivco_len
+ 1, sizeof(*ifo
->vivco
));
1870 if (vivco
== NULL
) {
1876 ifo
->vivco_en
= (uint32_t)u
;
1877 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
1879 vivco
->data
= (uint8_t *)np
;
1881 case O_AUTHPROTOCOL
:
1887 if (strcasecmp(arg
, "token") == 0)
1888 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
1889 else if (strcasecmp(arg
, "delayed") == 0)
1890 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
1891 else if (strcasecmp(arg
, "delayedrealm") == 0)
1892 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
1894 logerrx("%s: unsupported protocol", arg
);
1897 arg
= strskipwhite(fp
);
1900 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1901 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
)
1902 ifo
->auth
.protocol
= AUTH_ALG_NONE
;
1904 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1905 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1910 if (ifo
->auth
.protocol
== AUTH_PROTO_TOKEN
) {
1911 np
= strchr(arg
, '/');
1913 if (fp
== NULL
|| np
< fp
)
1918 if (parse_uint32(&ifo
->auth
.token_snd_secretid
,
1920 logerrx("%s: not a number", arg
);
1922 ifo
->auth
.token_rcv_secretid
=
1923 ifo
->auth
.token_snd_secretid
;
1925 parse_uint32(&ifo
->auth
.token_rcv_secretid
,
1927 logerrx("%s: not a number", arg
);
1929 if (strcasecmp(arg
, "hmacmd5") == 0 ||
1930 strcasecmp(arg
, "hmac-md5") == 0)
1931 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1933 logerrx("%s: unsupported algorithm", arg
);
1939 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1940 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1943 if (strcasecmp(arg
, "monocounter") == 0) {
1944 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1945 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
1946 } else if (strcasecmp(arg
, "monotonic") ==0 ||
1947 strcasecmp(arg
, "monotime") == 0)
1948 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1950 logerrx("%s: unsupported RDM", arg
);
1953 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1956 logerrx("no authentication support");
1964 logerrx("authtoken requires a realm");
1968 token
= malloc(sizeof(*token
));
1969 if (token
== NULL
) {
1974 if (parse_uint32(&token
->secretid
, arg
) == -1) {
1975 logerrx("%s: not a number", arg
);
1982 logerrx("authtoken requies an a key");
1987 s
= parse_string(NULL
, 0, arg
);
1989 logerr("realm_len");
1994 token
->realm_len
= (size_t)s
;
1995 token
->realm
= malloc(token
->realm_len
);
1996 if (token
->realm
== NULL
) {
2001 parse_string((char *)token
->realm
, token
->realm_len
,
2004 token
->realm_len
= 0;
2005 token
->realm
= NULL
;
2010 logerrx("authtoken requies an expiry date");
2018 np
= strchr(arg
, '"');
2022 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
2027 memset(&tm
, 0, sizeof(tm
));
2028 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
2029 logerrx("%s: invalid date time", arg
);
2034 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
2035 logerr("%s: mktime", __func__
);
2042 s
= parse_string(NULL
, 0, arg
);
2043 if (s
== -1 || s
== 0) {
2045 logerr("token_len");
2047 logerrx("authtoken needs a key");
2052 token
->key_len
= (size_t)s
;
2053 token
->key
= malloc(token
->key_len
);
2054 parse_string((char *)token
->key
, token
->key_len
, arg
);
2055 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
2057 logerrx("no authentication support");
2061 case O_AUTHNOTREQUIRED
:
2062 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
2065 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_WANTDHCP
| DHCPCD_IPV4
;
2068 ifo
->options
&= ~DHCPCD_DHCP
;
2071 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
2074 ifo
->options
&= ~DHCPCD_DHCP6
;
2079 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
2089 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, (size_t)l
, &grp
)) ==
2094 logerrx("control_group: out of buffer");
2099 np
= realloc(p
, dl
);
2109 logerr("getgrnam_r");
2114 logerrx("controlgroup: %s: not found", arg
);
2118 ctx
->control_group
= grp
->gr_gid
;
2121 grp
= getgrnam(arg
);
2123 logerrx("controlgroup: %s: not found", arg
);
2126 ctx
->control_group
= grp
->gr_gid
;
2130 ifo
->options
|= DHCPCD_GATEWAY
;
2133 ifo
->options
&= ~DHCPCD_IF_UP
;
2137 if (strcmp(arg
, "private") == 0 ||
2138 strcmp(arg
, "stableprivate") == 0 ||
2139 strcmp(arg
, "stable") == 0)
2140 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2142 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2145 ifo
->options
|= DHCPCD_BOOTP
;
2148 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2150 case O_LASTLEASE_EXTEND
:
2151 ifo
->options
|= DHCPCD_LASTLEASE
| DHCPCD_LASTLEASE_EXTEND
;
2154 ifo
->options
|= DHCPCD_INACTIVE
;
2158 s
= parse_string((char *)ifo
->mudurl
+ 1, MUDURL_MAX_LEN
, arg
);
2163 *ifo
->mudurl
= (uint8_t)s
;
2168 ctx
->link_rcvbuf
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
2170 logerrx("failed to convert link_rcvbuf %s", arg
);
2183 logerrx("option %d requires an argument", opt
);
2190 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2191 struct if_options
*ifo
, const char *opt
, char *line
,
2192 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2196 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2197 if (!cf_options
[i
].name
||
2198 strcmp(cf_options
[i
].name
, opt
) != 0)
2201 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2202 logerrx("option requires an argument -- %s", opt
);
2206 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2210 logerrx("unknown option: %s", opt
);
2215 finish_config(struct if_options
*ifo
)
2218 /* Terminate the encapsulated options */
2219 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2221 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2222 /* We are called twice.
2223 * This should be fixed, but in the meantime, this
2224 * guard should suffice */
2225 ifo
->options
|= DHCPCD_VENDORRAW
;
2229 /* Handy routine to read very long lines in text files.
2230 * This means we read the whole line and avoid any nasty buffer overflows.
2231 * We strip leading space and avoid comment lines, making the code that calls
2234 get_line(char ** __restrict buf
, size_t * __restrict buflen
,
2235 FILE * __restrict fp
)
2242 bytes
= getline(buf
, buflen
, fp
);
2245 for (p
= *buf
; *p
== ' ' || *p
== '\t'; p
++)
2247 } while (*p
== '\0' || *p
== '\n' || *p
== '#' || *p
== ';');
2248 if ((*buf
)[--bytes
] == '\n')
2249 (*buf
)[bytes
] = '\0';
2251 /* Strip embedded comments unless in a quoted string or escaped */
2253 for (c
= p
; *c
!= '\0'; c
++) {
2260 else if (*c
== '#' && !quoted
) {
2269 default_config(struct dhcpcd_ctx
*ctx
)
2271 struct if_options
*ifo
;
2273 /* Seed our default options */
2274 if ((ifo
= calloc(1, sizeof(*ifo
))) == NULL
) {
2278 ifo
->options
|= DHCPCD_IF_UP
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2279 ifo
->timeout
= DEFAULT_TIMEOUT
;
2280 ifo
->reboot
= DEFAULT_REBOOT
;
2281 ifo
->script
= UNCONST(default_script
);
2283 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2284 rb_tree_init(&ifo
->routes
, &rt_compare_list_ops
);
2286 TAILQ_INIT(&ifo
->auth
.tokens
);
2289 /* Inherit some global defaults */
2290 if (ctx
->options
& DHCPCD_PERSISTENT
)
2291 ifo
->options
|= DHCPCD_PERSISTENT
;
2292 if (ctx
->options
& DHCPCD_SLAACPRIVATE
)
2293 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2299 read_config(struct dhcpcd_ctx
*ctx
,
2300 const char *ifname
, const char *ssid
, const char *profile
)
2302 struct if_options
*ifo
;
2305 char *line
, *buf
, *option
, *p
;
2308 int skip
, have_profile
, new_block
, had_block
;
2309 #ifndef EMBEDDED_CONFIG
2310 const char * const *e
;
2313 #if !defined(INET) || !defined(INET6)
2315 struct dhcp_opt
*opt
;
2317 struct dhcp_opt
*ldop
, *edop
;
2319 /* Seed our default options */
2320 if ((ifo
= default_config(ctx
)) == NULL
)
2322 ifo
->options
|= DHCPCD_DAEMONISE
| DHCPCD_GATEWAY
;
2324 ifo
->options
|= DHCPCD_DEV
;
2327 ifo
->options
|= DHCPCD_IPV4
| DHCPCD_ARP
| DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2330 ifo
->options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
;
2331 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
;
2332 ifo
->options
|= DHCPCD_DHCP6
;
2335 vlen
= dhcp_vendor((char *)ifo
->vendorclassid
+ 1,
2336 sizeof(ifo
->vendorclassid
) - 1);
2337 ifo
->vendorclassid
[0] = (uint8_t)(vlen
== -1 ? 0 : vlen
);
2342 /* Reset route order */
2345 /* Parse our embedded options file */
2346 if (ifname
== NULL
&& !(ctx
->options
& DHCPCD_PRINT_PIDFILE
)) {
2347 /* Space for initial estimates */
2348 #if defined(INET) && defined(INITDEFINES)
2349 ifo
->dhcp_override
=
2350 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2351 if (ifo
->dhcp_override
== NULL
)
2354 ifo
->dhcp_override_len
= INITDEFINES
;
2357 #if defined(INET6) && defined(INITDEFINENDS)
2359 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2360 if (ifo
->nd_override
== NULL
)
2363 ifo
->nd_override_len
= INITDEFINENDS
;
2365 #if defined(INET6) && defined(INITDEFINE6S)
2366 ifo
->dhcp6_override
=
2367 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2368 if (ifo
->dhcp6_override
== NULL
)
2371 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2374 /* Now load our embedded config */
2375 #ifdef EMBEDDED_CONFIG
2376 fp
= fopen(EMBEDDED_CONFIG
, "r");
2378 logerr("%s: fopen `%s'", __func__
, EMBEDDED_CONFIG
);
2380 while (fp
&& (line
= get_line(&buf
, &buflen
, fp
))) {
2383 buf
= malloc(buflen
);
2386 free_options(ctx
, ifo
);
2390 for (e
= dhcpcd_embedded_conf
; *e
; e
++) {
2391 ol
= strlen(*e
) + 1;
2396 nbuf
= realloc(buf
, buflen
);
2400 free_options(ctx
, ifo
);
2405 memcpy(buf
, *e
, ol
);
2408 option
= strsep(&line
, " \t");
2410 line
= strskipwhite(line
);
2411 /* Trim trailing whitespace */
2413 p
= line
+ strlen(line
) - 1;
2415 (*p
== ' ' || *p
== '\t') &&
2419 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2424 #ifdef EMBEDDED_CONFIG
2429 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2430 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2432 for (i
= 0, opt
= ifo
->dhcp_override
;
2433 i
< ifo
->dhcp_override_len
;
2435 free_dhcp_opt_embenc(opt
);
2436 free(ifo
->dhcp_override
);
2438 ifo
->dhcp_override
= NULL
;
2439 ifo
->dhcp_override_len
= 0;
2442 ctx
->nd_opts
= ifo
->nd_override
;
2443 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2445 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2446 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2449 for (i
= 0, opt
= ifo
->nd_override
;
2450 i
< ifo
->nd_override_len
;
2452 free_dhcp_opt_embenc(opt
);
2453 free(ifo
->nd_override
);
2454 for (i
= 0, opt
= ifo
->dhcp6_override
;
2455 i
< ifo
->dhcp6_override_len
;
2457 free_dhcp_opt_embenc(opt
);
2458 free(ifo
->dhcp6_override
);
2460 ifo
->nd_override
= NULL
;
2461 ifo
->nd_override_len
= 0;
2462 ifo
->dhcp6_override
= NULL
;
2463 ifo
->dhcp6_override_len
= 0;
2465 ctx
->vivso
= ifo
->vivso_override
;
2466 ctx
->vivso_len
= ifo
->vivso_override_len
;
2467 ifo
->vivso_override
= NULL
;
2468 ifo
->vivso_override_len
= 0;
2471 /* Parse our options file */
2472 fp
= fopen(ctx
->cffile
, "r");
2474 /* dhcpcd can continue without it, but no DNS options
2475 * would be requested ... */
2476 logwarn("%s: fopen `%s'", __func__
, ctx
->cffile
);
2480 if (stat(ctx
->cffile
, &sb
) == 0)
2481 ifo
->mtime
= sb
.st_mtime
;
2484 skip
= have_profile
= new_block
= 0;
2485 had_block
= ifname
== NULL
? 1 : 0;
2486 while ((line
= get_line(&buf
, &buflen
, fp
))) {
2487 option
= strsep(&line
, " \t");
2489 line
= strskipwhite(line
);
2490 /* Trim trailing whitespace */
2492 p
= line
+ strlen(line
) - 1;
2494 (*p
== ' ' || *p
== '\t') &&
2498 if (skip
== 0 && new_block
) {
2501 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2503 /* Start of an interface block, skip if not ours */
2504 if (strcmp(option
, "interface") == 0) {
2509 /* No interface given */
2513 if (ifname
&& strcmp(line
, ifname
) == 0)
2520 n
= reallocarray(ctx
->ifcv
,
2521 (size_t)ctx
->ifcc
+ 1, sizeof(char *));
2527 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2528 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2535 /* Start of an ssid block, skip if not ours */
2536 if (strcmp(option
, "ssid") == 0) {
2538 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2544 /* Start of a profile block, skip if not ours */
2545 if (strcmp(option
, "profile") == 0) {
2547 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2554 /* Skip arping if we have selected a profile but not parsing
2556 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2560 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2565 if (profile
&& !have_profile
) {
2566 free_options(ctx
, ifo
);
2572 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2578 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2579 struct if_options
*ifo
, int argc
, char **argv
)
2582 unsigned long long wait_opts
;
2589 /* Don't apply the command line wait options to each interface,
2590 * only use the dhcpcd.conf entry for that. */
2592 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2593 while ((opt
= getopt_long(argc
, argv
,
2594 ctx
->options
& DHCPCD_PRINT_PIDFILE
? NOERR_IF_OPTS
: IF_OPTS
,
2595 cf_options
, &oi
)) != -1)
2597 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2601 if (ifname
!= NULL
) {
2602 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2603 ifo
->options
|= wait_opts
;
2611 free_options(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
)
2614 #ifdef RT_FREE_ROUTE_TABLE
2615 struct interface
*ifp
;
2618 struct dhcp_opt
*opt
;
2621 struct token
*token
;
2629 while (ifo
->environ
[i
])
2630 free(ifo
->environ
[i
++]);
2635 while (ifo
->config
[i
])
2636 free(ifo
->config
[i
++]);
2640 #ifdef RT_FREE_ROUTE_TABLE
2641 /* Stupidly, we don't know the interface when creating the options.
2642 * As such, make sure each route has one so they can goto the
2644 ifp
= ctx
->ifaces
!= NULL
? TAILQ_FIRST(ctx
->ifaces
) : NULL
;
2646 RB_TREE_FOREACH(rt
, &ifo
->routes
) {
2647 if (rt
->rt_ifp
== NULL
)
2652 rt_headclear0(ctx
, &ifo
->routes
, AF_UNSPEC
);
2654 if (ifo
->script
!= default_script
)
2657 free(ifo
->blacklist
);
2658 free(ifo
->fallback
);
2660 for (opt
= ifo
->dhcp_override
;
2661 ifo
->dhcp_override_len
> 0;
2662 opt
++, ifo
->dhcp_override_len
--)
2663 free_dhcp_opt_embenc(opt
);
2664 free(ifo
->dhcp_override
);
2665 for (opt
= ifo
->nd_override
;
2666 ifo
->nd_override_len
> 0;
2667 opt
++, ifo
->nd_override_len
--)
2668 free_dhcp_opt_embenc(opt
);
2669 free(ifo
->nd_override
);
2670 for (opt
= ifo
->dhcp6_override
;
2671 ifo
->dhcp6_override_len
> 0;
2672 opt
++, ifo
->dhcp6_override_len
--)
2673 free_dhcp_opt_embenc(opt
);
2674 free(ifo
->dhcp6_override
);
2675 for (vo
= ifo
->vivco
;
2677 vo
++, ifo
->vivco_len
--)
2680 for (opt
= ifo
->vivso_override
;
2681 ifo
->vivso_override_len
> 0;
2682 opt
++, ifo
->vivso_override_len
--)
2683 free_dhcp_opt_embenc(opt
);
2684 free(ifo
->vivso_override
);
2686 #if defined(INET6) && !defined(SMALL)
2687 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2688 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2693 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2694 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2695 if (token
->realm_len
)