2 __RCSID("$NetBSD: if-options.c,v 1.27 2015/09/04 12:25:01 roy Exp $");
5 * dhcpcd - DHCP client daemon
6 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #define _WITH_GETLINE /* Stop FreeBSD bitching */
33 #include <sys/param.h>
35 #include <sys/types.h>
37 #include <arpa/inet.h>
56 #include "dhcpcd-embedded.h"
58 #include "if-options.h"
61 /* These options only make sense in the config file, so don't use any
62 valid short options for them */
63 #define O_BASE MAX('z', 'Z') + 1
64 #define O_ARPING O_BASE + 1
65 #define O_FALLBACK O_BASE + 2
66 #define O_DESTINATION O_BASE + 3
67 #define O_IPV6RS O_BASE + 4
68 #define O_NOIPV6RS O_BASE + 5
69 #define O_IPV6RA_FORK O_BASE + 6
70 #define O_IPV6RA_OWN O_BASE + 7
71 #define O_IPV6RA_OWN_D O_BASE + 8
72 #define O_NOALIAS O_BASE + 9
73 #define O_IA_NA O_BASE + 10
74 #define O_IA_TA O_BASE + 11
75 #define O_IA_PD O_BASE + 12
76 #define O_HOSTNAME_SHORT O_BASE + 13
77 #define O_DEV O_BASE + 14
78 #define O_NODEV O_BASE + 15
79 #define O_NOIPV4 O_BASE + 16
80 #define O_NOIPV6 O_BASE + 17
81 #define O_IAID O_BASE + 18
82 #define O_DEFINE O_BASE + 19
83 #define O_DEFINE6 O_BASE + 20
84 #define O_EMBED O_BASE + 21
85 #define O_ENCAP O_BASE + 22
86 #define O_VENDOPT O_BASE + 23
87 #define O_VENDCLASS O_BASE + 24
88 #define O_AUTHPROTOCOL O_BASE + 25
89 #define O_AUTHTOKEN O_BASE + 26
90 #define O_AUTHNOTREQUIRED O_BASE + 27
91 #define O_NODHCP O_BASE + 28
92 #define O_NODHCP6 O_BASE + 29
93 #define O_DHCP O_BASE + 30
94 #define O_DHCP6 O_BASE + 31
95 #define O_IPV4 O_BASE + 32
96 #define O_IPV6 O_BASE + 33
97 #define O_CONTROLGRP O_BASE + 34
98 #define O_SLAAC O_BASE + 35
99 #define O_GATEWAY O_BASE + 36
100 #define O_NOUP O_BASE + 37
101 #define O_IPV6RA_AUTOCONF O_BASE + 38
102 #define O_IPV6RA_NOAUTOCONF O_BASE + 39
103 #define O_REJECT O_BASE + 40
104 #define O_IPV6RA_ACCEPT_NOPUBLIC O_BASE + 41
105 #define O_BOOTP O_BASE + 42
106 #define O_DEFINEND O_BASE + 43
107 #define O_NODELAY O_BASE + 44
109 const struct option cf_options
[] = {
110 {"background", no_argument
, NULL
, 'b'},
111 {"script", required_argument
, NULL
, 'c'},
112 {"debug", no_argument
, NULL
, 'd'},
113 {"env", required_argument
, NULL
, 'e'},
114 {"config", required_argument
, NULL
, 'f'},
115 {"reconfigure", no_argument
, NULL
, 'g'},
116 {"hostname", optional_argument
, NULL
, 'h'},
117 {"vendorclassid", optional_argument
, NULL
, 'i'},
118 {"logfile", required_argument
, NULL
, 'j'},
119 {"release", no_argument
, NULL
, 'k'},
120 {"leasetime", required_argument
, NULL
, 'l'},
121 {"metric", required_argument
, NULL
, 'm'},
122 {"rebind", no_argument
, NULL
, 'n'},
123 {"option", required_argument
, NULL
, 'o'},
124 {"persistent", no_argument
, NULL
, 'p'},
125 {"quiet", no_argument
, NULL
, 'q'},
126 {"request", optional_argument
, NULL
, 'r'},
127 {"inform", optional_argument
, NULL
, 's'},
128 {"timeout", required_argument
, NULL
, 't'},
129 {"userclass", required_argument
, NULL
, 'u'},
130 {"vendor", required_argument
, NULL
, 'v'},
131 {"waitip", optional_argument
, NULL
, 'w'},
132 {"exit", no_argument
, NULL
, 'x'},
133 {"allowinterfaces", required_argument
, NULL
, 'z'},
134 {"reboot", required_argument
, NULL
, 'y'},
135 {"noarp", no_argument
, NULL
, 'A'},
136 {"nobackground", no_argument
, NULL
, 'B'},
137 {"nohook", required_argument
, NULL
, 'C'},
138 {"duid", no_argument
, NULL
, 'D'},
139 {"lastlease", no_argument
, NULL
, 'E'},
140 {"fqdn", optional_argument
, NULL
, 'F'},
141 {"nogateway", no_argument
, NULL
, 'G'},
142 {"xidhwaddr", no_argument
, NULL
, 'H'},
143 {"clientid", optional_argument
, NULL
, 'I'},
144 {"broadcast", no_argument
, NULL
, 'J'},
145 {"nolink", no_argument
, NULL
, 'K'},
146 {"noipv4ll", no_argument
, NULL
, 'L'},
147 {"master", no_argument
, NULL
, 'M'},
148 {"nooption", optional_argument
, NULL
, 'O'},
149 {"require", required_argument
, NULL
, 'Q'},
150 {"static", required_argument
, NULL
, 'S'},
151 {"test", no_argument
, NULL
, 'T'},
152 {"dumplease", no_argument
, NULL
, 'U'},
153 {"variables", no_argument
, NULL
, 'V'},
154 {"whitelist", required_argument
, NULL
, 'W'},
155 {"blacklist", required_argument
, NULL
, 'X'},
156 {"denyinterfaces", required_argument
, NULL
, 'Z'},
157 {"arping", required_argument
, NULL
, O_ARPING
},
158 {"destination", required_argument
, NULL
, O_DESTINATION
},
159 {"fallback", required_argument
, NULL
, O_FALLBACK
},
160 {"ipv6rs", no_argument
, NULL
, O_IPV6RS
},
161 {"noipv6rs", no_argument
, NULL
, O_NOIPV6RS
},
162 {"ipv6ra_autoconf", no_argument
, NULL
, O_IPV6RA_AUTOCONF
},
163 {"ipv6ra_noautoconf", no_argument
, NULL
, O_IPV6RA_NOAUTOCONF
},
164 {"ipv6ra_fork", no_argument
, NULL
, O_IPV6RA_FORK
},
165 {"ipv6ra_own", no_argument
, NULL
, O_IPV6RA_OWN
},
166 {"ipv6ra_own_default", no_argument
, NULL
, O_IPV6RA_OWN_D
},
167 {"ipv6ra_accept_nopublic", no_argument
, NULL
, O_IPV6RA_ACCEPT_NOPUBLIC
},
168 {"ipv4only", no_argument
, NULL
, '4'},
169 {"ipv6only", no_argument
, NULL
, '6'},
170 {"ipv4", no_argument
, NULL
, O_IPV4
},
171 {"noipv4", no_argument
, NULL
, O_NOIPV4
},
172 {"ipv6", no_argument
, NULL
, O_IPV6
},
173 {"noipv6", no_argument
, NULL
, O_NOIPV6
},
174 {"noalias", no_argument
, NULL
, O_NOALIAS
},
175 {"iaid", required_argument
, NULL
, O_IAID
},
176 {"ia_na", no_argument
, NULL
, O_IA_NA
},
177 {"ia_ta", no_argument
, NULL
, O_IA_TA
},
178 {"ia_pd", no_argument
, NULL
, O_IA_PD
},
179 {"hostname_short", no_argument
, NULL
, O_HOSTNAME_SHORT
},
180 {"dev", required_argument
, NULL
, O_DEV
},
181 {"nodev", no_argument
, NULL
, O_NODEV
},
182 {"define", required_argument
, NULL
, O_DEFINE
},
183 {"definend", required_argument
, NULL
, O_DEFINEND
},
184 {"define6", required_argument
, NULL
, O_DEFINE6
},
185 {"embed", required_argument
, NULL
, O_EMBED
},
186 {"encap", required_argument
, NULL
, O_ENCAP
},
187 {"vendopt", required_argument
, NULL
, O_VENDOPT
},
188 {"vendclass", required_argument
, NULL
, O_VENDCLASS
},
189 {"authprotocol", required_argument
, NULL
, O_AUTHPROTOCOL
},
190 {"authtoken", required_argument
, NULL
, O_AUTHTOKEN
},
191 {"noauthrequired", no_argument
, NULL
, O_AUTHNOTREQUIRED
},
192 {"dhcp", no_argument
, NULL
, O_DHCP
},
193 {"nodhcp", no_argument
, NULL
, O_NODHCP
},
194 {"dhcp6", no_argument
, NULL
, O_DHCP6
},
195 {"nodhcp6", no_argument
, NULL
, O_NODHCP6
},
196 {"controlgroup", required_argument
, NULL
, O_CONTROLGRP
},
197 {"slaac", required_argument
, NULL
, O_SLAAC
},
198 {"gateway", no_argument
, NULL
, O_GATEWAY
},
199 {"reject", required_argument
, NULL
, O_REJECT
},
200 {"bootp", no_argument
, NULL
, O_BOOTP
},
201 {"nodelay", no_argument
, NULL
, O_NODELAY
},
202 {"noup", no_argument
, NULL
, O_NOUP
},
203 {NULL
, 0, NULL
, '\0'}
207 add_environ(struct dhcpcd_ctx
*ctx
, struct if_options
*ifo
,
208 const char *value
, int uniq
)
211 char **lst
= ifo
->environ
;
213 char *match
= NULL
, *p
, *n
;
215 match
= strdup(value
);
217 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
220 p
= strchr(match
, '=');
222 logger(ctx
, LOG_ERR
, "%s: no assignment: %s", __func__
, value
);
229 while (lst
&& lst
[i
]) {
230 if (match
&& strncmp(lst
[i
], match
, l
) == 0) {
242 /* Append a space and the value to it */
245 n
= realloc(lst
[i
], l
+ lv
+ 2);
254 memcpy(lst
[i
] + l
+ 1, p
, lv
);
255 lst
[i
][l
+ lv
+ 1] = '\0';
266 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
269 newlist
= realloc(lst
, sizeof(char *) * (i
+ 2));
270 if (newlist
== NULL
) {
271 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
276 newlist
[i
+ 1] = NULL
;
277 ifo
->environ
= newlist
;
281 #define parse_string(buf, len, arg) parse_string_hwaddr(buf, len, arg, 0)
283 parse_string_hwaddr(char *sbuf
, size_t slen
, const char *str
, int clid
)
287 int i
, punt_last
= 0;
290 /* If surrounded by quotes then it's a string */
298 l
= (size_t)hwaddr_aton(NULL
, str
);
299 if ((ssize_t
) l
!= -1 && l
> 1) {
304 hwaddr_aton((uint8_t *)sbuf
, str
);
309 /* Process escapes */
311 /* If processing a string on the clientid, first byte should be
312 * 0 to indicate a non hardware type */
320 if (++l
> slen
&& sbuf
) {
350 /* Grab a hex code */
352 for (i
= 0; i
< 2; i
++) {
353 if (isxdigit((unsigned char)*str
) == 0)
357 if (c
[1] != '\0' && sbuf
) {
359 *sbuf
++ = (char)strtol(c
, NULL
, 16);
364 /* Grab an octal code */
366 for (i
= 0; i
< 3; i
++) {
367 if (*str
< '0' || *str
> '7')
371 if (c
[2] != '\0' && sbuf
) {
372 i
= (int)strtol(c
, NULL
, 8);
400 parse_iaid1(uint8_t *iaid
, const char *arg
, size_t len
, int n
)
406 narg
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
410 memcpy(iaid
, &narg
, sizeof(narg
));
414 if ((s
= parse_string((char *)iaid
, len
, arg
)) < 1)
426 parse_iaid(uint8_t *iaid
, const char *arg
, size_t len
)
429 return parse_iaid1(iaid
, arg
, len
, 1);
433 parse_uint32(uint32_t *i
, const char *arg
)
436 return parse_iaid1((uint8_t *)i
, arg
, sizeof(uint32_t), 0);
440 splitv(struct dhcpcd_ctx
*ctx
, int *argc
, char **argv
, const char *arg
)
442 char **n
, **v
= argv
;
443 char *o
= strdup(arg
), *p
, *t
, *nt
;
446 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
450 while ((t
= strsep(&p
, ", "))) {
453 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
457 n
= realloc(v
, sizeof(char *) * ((size_t)(*argc
) + 1));
459 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
473 parse_addr(struct dhcpcd_ctx
*ctx
,
474 struct in_addr
*addr
, struct in_addr
*net
, const char *arg
)
478 if (arg
== NULL
|| *arg
== '\0') {
485 if ((p
= strchr(arg
, '/')) != NULL
) {
490 i
= strtoi(p
, NULL
, 10, 0, 32, &e
);
492 (net
!= NULL
&& inet_cidrtoaddr((int)i
, net
) != 0))
494 logger(ctx
, LOG_ERR
, "`%s' is not a valid CIDR", p
);
499 if (addr
!= NULL
&& inet_aton(arg
, addr
) == 0) {
500 logger(ctx
, LOG_ERR
, "`%s' is not a valid IP address", arg
);
505 else if (net
!= NULL
&& addr
!= NULL
)
506 net
->s_addr
= ipv4_getnetmask(addr
->s_addr
);
511 parse_addr(struct dhcpcd_ctx
*ctx
,
512 __unused
struct in_addr
*addr
, __unused
struct in_addr
*net
,
513 __unused
const char *arg
)
516 logger(ctx
, LOG_ERR
, "No IPv4 support");
522 set_option_space(struct dhcpcd_ctx
*ctx
,
524 const struct dhcp_opt
**d
, size_t *dl
,
525 const struct dhcp_opt
**od
, size_t *odl
,
526 struct if_options
*ifo
,
527 uint8_t *request
[], uint8_t *require
[], uint8_t *no
[], uint8_t *reject
[])
530 #if !defined(INET) && !defined(INET6)
535 if (strncmp(arg
, "nd_", strlen("nd_")) == 0) {
537 *dl
= ctx
->nd_opts_len
;
538 *od
= ifo
->nd_override
;
539 *odl
= ifo
->nd_override_len
;
540 *request
= ifo
->requestmasknd
;
541 *require
= ifo
->requiremasknd
;
543 *reject
= ifo
->rejectmasknd
;
544 return arg
+ strlen("nd_");
547 if (strncmp(arg
, "dhcp6_", strlen("dhcp6_")) == 0) {
548 *d
= ctx
->dhcp6_opts
;
549 *dl
= ctx
->dhcp6_opts_len
;
550 *od
= ifo
->dhcp6_override
;
551 *odl
= ifo
->dhcp6_override_len
;
552 *request
= ifo
->requestmask6
;
553 *require
= ifo
->requiremask6
;
555 *reject
= ifo
->rejectmask6
;
556 return arg
+ strlen("dhcp6_");
562 *dl
= ctx
->dhcp_opts_len
;
563 *od
= ifo
->dhcp_override
;
564 *odl
= ifo
->dhcp_override_len
;
571 *request
= ifo
->requestmask
;
572 *require
= ifo
->requiremask
;
574 *reject
= ifo
->rejectmask
;
579 free_dhcp_opt_embenc(struct dhcp_opt
*opt
)
586 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
587 free_dhcp_opt_embenc(o
);
589 opt
->embopts_len
= 0;
592 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)
593 free_dhcp_opt_embenc(o
);
595 opt
->encopts_len
= 0;
600 strwhite(const char *s
)
605 while (*s
!= ' ' && *s
!= '\t') {
614 strskipwhite(const char *s
)
619 while (*s
== ' ' || *s
== '\t') {
627 /* Find the end pointer of a string. */
629 strend(const char *s
)
636 return strchr(s
, ' ');
638 for (; *s
!= '"' ; s
++) {
650 parse_option(struct dhcpcd_ctx
*ctx
, const char *ifname
, struct if_options
*ifo
,
651 int opt
, const char *arg
, struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
656 char *p
= NULL
, *bp
, *fp
, *np
, **nconf
;
658 struct in_addr addr
, addr2
;
661 const struct dhcp_opt
*d
, *od
;
662 uint8_t *request
, *require
, *no
, *reject
;
663 struct dhcp_opt
**dop
, *ndop
;
664 size_t *dop_len
, dl
, odl
;
675 struct if_sla
*sla
, *slap
;
684 case 'f': /* FALLTHROUGH */
685 case 'g': /* FALLTHROUGH */
686 case 'n': /* FALLTHROUGH */
687 case 'x': /* FALLTHROUGH */
688 case 'T': /* FALLTHROUGH */
689 case 'U': /* FALLTHROUGH */
690 case 'V': /* We need to handle non interface options */
693 ifo
->options
|= DHCPCD_BACKGROUND
;
697 ifo
->script
= strdup(arg
);
698 if (ifo
->script
== NULL
)
699 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
702 ifo
->options
|= DHCPCD_DEBUG
;
705 add_environ(ctx
, ifo
, arg
, 1);
709 ifo
->options
|= DHCPCD_HOSTNAME
;
712 s
= parse_string(ifo
->hostname
, HOSTNAME_MAX_LEN
, arg
);
714 logger(ctx
, LOG_ERR
, "hostname: %m");
717 if (s
!= 0 && ifo
->hostname
[0] == '.') {
718 logger(ctx
, LOG_ERR
, "hostname cannot begin with .");
721 ifo
->hostname
[s
] = '\0';
722 if (ifo
->hostname
[0] == '\0')
723 ifo
->options
&= ~DHCPCD_HOSTNAME
;
725 ifo
->options
|= DHCPCD_HOSTNAME
;
729 s
= parse_string((char *)ifo
->vendorclassid
+ 1,
730 VENDORCLASSID_MAX_LEN
, arg
);
734 logger(ctx
, LOG_ERR
, "vendorclassid: %m");
737 *ifo
->vendorclassid
= (uint8_t)s
;
740 /* per interface logging is not supported
741 * don't want to overide the commandline */
742 if (ifname
== NULL
&& ctx
->logfile
== NULL
) {
744 ctx
->logfile
= strdup(arg
);
749 ifo
->options
|= DHCPCD_RELEASE
;
752 ifo
->leasetime
= (uint32_t)strtou(arg
, NULL
,
753 0, 0, UINT32_MAX
, &e
);
755 logger(ctx
, LOG_ERR
, "failed to convert leasetime %s", arg
);
760 ifo
->metric
= (int)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
762 logger(ctx
, LOG_ERR
, "failed to convert metric %s", arg
);
767 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
768 &request
, &require
, &no
, &reject
);
769 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
770 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
771 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
773 logger(ctx
, LOG_ERR
, "unknown option `%s'", arg
);
778 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
779 &request
, &require
, &no
, &reject
);
780 if (make_option_mask(d
, dl
, od
, odl
, reject
, arg
, 1) != 0 ||
781 make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
782 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0)
784 logger(ctx
, LOG_ERR
, "unknown option `%s'", arg
);
789 ifo
->options
|= DHCPCD_PERSISTENT
;
792 ifo
->options
|= DHCPCD_QUIET
;
795 if (parse_addr(ctx
, &ifo
->req_addr
, NULL
, arg
) != 0)
797 ifo
->options
|= DHCPCD_REQUEST
;
798 ifo
->req_mask
.s_addr
= 0;
801 if (ifo
->options
& DHCPCD_IPV6
&&
802 !(ifo
->options
& DHCPCD_IPV4
))
804 ifo
->options
|= DHCPCD_INFORM
;
807 if (arg
&& *arg
!= '\0') {
809 &ifo
->req_addr
, &ifo
->req_mask
, arg
) != 0)
812 ifo
->req_addr
.s_addr
= 0;
813 ifo
->req_mask
.s_addr
= 0;
815 ifo
->options
|= DHCPCD_INFORM
| DHCPCD_PERSISTENT
;
816 ifo
->options
&= ~DHCPCD_STATIC
;
819 ifo
->timeout
= (time_t)strtoi(arg
, NULL
, 0, 0, INT32_MAX
, &e
);
821 logger(ctx
, LOG_ERR
, "failed to convert timeout");
826 s
= USERCLASS_MAX_LEN
- ifo
->userclass
[0] - 1;
827 s
= parse_string((char *)ifo
->userclass
+
828 ifo
->userclass
[0] + 2, (size_t)s
, arg
);
830 logger(ctx
, LOG_ERR
, "userclass: %m");
834 ifo
->userclass
[ifo
->userclass
[0] + 1] = (uint8_t)s
;
835 ifo
->userclass
[0] = (uint8_t)(ifo
->userclass
[0] + s
+1);
839 p
= strchr(arg
, ',');
841 logger(ctx
, LOG_ERR
, "invalid vendor format: %s", arg
);
845 /* If vendor starts with , then it is not encapsulated */
848 s
= parse_string((char *)ifo
->vendor
+ 1,
849 VENDOR_MAX_LEN
, arg
);
851 logger(ctx
, LOG_ERR
, "vendor: %m");
854 ifo
->vendor
[0] = (uint8_t)s
;
855 ifo
->options
|= DHCPCD_VENDORRAW
;
859 /* Encapsulated vendor options */
860 if (ifo
->options
& DHCPCD_VENDORRAW
) {
861 ifo
->options
&= ~DHCPCD_VENDORRAW
;
865 /* Strip and preserve the comma */
867 i
= (int)strtoi(arg
, NULL
, 0, 1, 254, &e
);
870 logger(ctx
, LOG_ERR
, "vendor option should be between"
871 " 1 and 254 inclusive");
876 s
= VENDOR_MAX_LEN
- ifo
->vendor
[0] - 2;
877 if (inet_aton(arg
, &addr
) == 1) {
882 memcpy(ifo
->vendor
+ ifo
->vendor
[0] + 3,
883 &addr
.s_addr
, sizeof(addr
.s_addr
));
884 s
= sizeof(addr
.s_addr
);
887 s
= parse_string((char *)ifo
->vendor
+
888 ifo
->vendor
[0] + 3, (size_t)s
, arg
);
891 logger(ctx
, LOG_ERR
, "vendor: %m");
895 ifo
->vendor
[ifo
->vendor
[0] + 1] = (uint8_t)i
;
896 ifo
->vendor
[ifo
->vendor
[0] + 2] = (uint8_t)s
;
897 ifo
->vendor
[0] = (uint8_t)(ifo
->vendor
[0] + s
+ 2);
901 ifo
->options
|= DHCPCD_WAITIP
;
902 if (arg
!= NULL
&& arg
[0] != '\0') {
903 if (arg
[0] == '4' || arg
[1] == '4')
904 ifo
->options
|= DHCPCD_WAITIP4
;
905 if (arg
[0] == '6' || arg
[1] == '6')
906 ifo
->options
|= DHCPCD_WAITIP6
;
910 ifo
->reboot
= (time_t)strtoi(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
912 logger(ctx
, LOG_ERR
, "failed to convert reboot %s", arg
);
918 ctx
->ifav
= splitv(ctx
, &ctx
->ifac
, ctx
->ifav
, arg
);
921 ifo
->options
&= ~DHCPCD_ARP
;
922 /* IPv4LL requires ARP */
923 ifo
->options
&= ~DHCPCD_IPV4LL
;
926 ifo
->options
&= ~DHCPCD_DAEMONISE
;
929 /* Commas to spaces for shell */
930 while ((p
= strchr(arg
, ',')))
932 dl
= strlen("skip_hooks=") + strlen(arg
) + 1;
933 p
= malloc(sizeof(char) * dl
);
935 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
938 snprintf(p
, dl
, "skip_hooks=%s", arg
);
939 add_environ(ctx
, ifo
, p
, 0);
943 ifo
->options
|= DHCPCD_CLIENTID
| DHCPCD_DUID
;
946 ifo
->options
|= DHCPCD_LASTLEASE
;
950 ifo
->fqdn
= FQDN_BOTH
;
953 if (strcmp(arg
, "none") == 0)
954 ifo
->fqdn
= FQDN_NONE
;
955 else if (strcmp(arg
, "ptr") == 0)
956 ifo
->fqdn
= FQDN_PTR
;
957 else if (strcmp(arg
, "both") == 0)
958 ifo
->fqdn
= FQDN_BOTH
;
959 else if (strcmp(arg
, "disable") == 0)
960 ifo
->fqdn
= FQDN_DISABLE
;
962 logger(ctx
, LOG_ERR
, "invalid value `%s' for FQDN", arg
);
967 ifo
->options
&= ~DHCPCD_GATEWAY
;
970 ifo
->options
|= DHCPCD_XID_HWADDR
;
973 /* Strings have a type of 0 */;
974 ifo
->clientid
[1] = 0;
976 s
= parse_string_hwaddr((char *)ifo
->clientid
+ 1,
977 CLIENTID_MAX_LEN
, arg
, 1);
981 logger(ctx
, LOG_ERR
, "clientid: %m");
984 ifo
->options
|= DHCPCD_CLIENTID
;
985 ifo
->clientid
[0] = (uint8_t)s
;
988 ifo
->options
|= DHCPCD_BROADCAST
;
991 ifo
->options
&= ~DHCPCD_LINK
;
994 ifo
->options
&= ~DHCPCD_IPV4LL
;
997 ifo
->options
|= DHCPCD_MASTER
;
1000 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1001 &request
, &require
, &no
, &reject
);
1002 if (make_option_mask(d
, dl
, od
, odl
, request
, arg
, -1) != 0 ||
1003 make_option_mask(d
, dl
, od
, odl
, require
, arg
, -1) != 0 ||
1004 make_option_mask(d
, dl
, od
, odl
, no
, arg
, 1) != 0)
1006 logger(ctx
, LOG_ERR
, "unknown option `%s'", arg
);
1011 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1012 &request
, &require
, &no
, &reject
);
1013 if (make_option_mask(d
, dl
, od
, odl
, require
, arg
, 1) != 0 ||
1014 make_option_mask(d
, dl
, od
, odl
, request
, arg
, 1) != 0 ||
1015 make_option_mask(d
, dl
, od
, odl
, no
, arg
, -1) != 0 ||
1016 make_option_mask(d
, dl
, od
, odl
, reject
, arg
, -1) != 0)
1018 logger(ctx
, LOG_ERR
, "unknown option `%s'", arg
);
1023 p
= strchr(arg
, '=');
1025 logger(ctx
, LOG_ERR
, "static assignment required");
1029 if (strncmp(arg
, "ip_address=", strlen("ip_address=")) == 0) {
1030 if (parse_addr(ctx
, &ifo
->req_addr
,
1031 ifo
->req_mask
.s_addr
== 0 ? &ifo
->req_mask
: NULL
,
1035 ifo
->options
|= DHCPCD_STATIC
;
1036 ifo
->options
&= ~DHCPCD_INFORM
;
1037 } else if (strncmp(arg
, "subnet_mask=",
1038 strlen("subnet_mask=")) == 0)
1040 if (parse_addr(ctx
, &ifo
->req_mask
, NULL
, p
) != 0)
1042 } else if (strncmp(arg
, "routes=", strlen("routes=")) == 0 ||
1043 strncmp(arg
, "static_routes=",
1044 strlen("static_routes=")) == 0 ||
1045 strncmp(arg
, "classless_static_routes=",
1046 strlen("classless_static_routes=")) == 0 ||
1047 strncmp(arg
, "ms_classless_static_routes=",
1048 strlen("ms_classless_static_routes=")) == 0)
1050 fp
= np
= strwhite(p
);
1052 logger(ctx
, LOG_ERR
,
1053 "all routes need a gateway");
1057 np
= strskipwhite(np
);
1058 if (ifo
->routes
== NULL
) {
1059 ifo
->routes
= malloc(sizeof(*ifo
->routes
));
1060 if (ifo
->routes
== NULL
) {
1061 logger(ctx
, LOG_ERR
,
1062 "%s: %m", __func__
);
1065 TAILQ_INIT(ifo
->routes
);
1067 rt
= calloc(1, sizeof(*rt
));
1069 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1073 if (parse_addr(ctx
, &rt
->dest
, &rt
->net
, p
) == -1 ||
1074 parse_addr(ctx
, &rt
->gate
, NULL
, np
) == -1)
1080 TAILQ_INSERT_TAIL(ifo
->routes
, rt
, next
);
1082 } else if (strncmp(arg
, "routers=", strlen("routers=")) == 0) {
1083 if (ifo
->routes
== NULL
) {
1084 ifo
->routes
= malloc(sizeof(*ifo
->routes
));
1085 if (ifo
->routes
== NULL
) {
1086 logger(ctx
, LOG_ERR
,
1087 "%s: %m", __func__
);
1090 TAILQ_INIT(ifo
->routes
);
1092 rt
= calloc(1, sizeof(*rt
));
1094 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1097 rt
->dest
.s_addr
= INADDR_ANY
;
1098 rt
->net
.s_addr
= INADDR_ANY
;
1099 if (parse_addr(ctx
, &rt
->gate
, NULL
, p
) == -1) {
1103 TAILQ_INSERT_TAIL(ifo
->routes
, rt
, next
);
1104 } else if (strncmp(arg
, "interface_mtu=",
1105 strlen("interface_mtu=")) == 0 ||
1106 strncmp(arg
, "mtu=", strlen("mtu=")) == 0)
1108 ifo
->mtu
= (unsigned int)strtou(p
, NULL
, 0,
1109 MTU_MIN
, MTU_MAX
, &e
);
1111 logger(ctx
, LOG_ERR
, "invalid MTU %s", p
);
1116 if (ifo
->config
!= NULL
) {
1117 while (ifo
->config
[dl
] != NULL
) {
1118 if (strncmp(ifo
->config
[dl
], arg
,
1119 (size_t)(p
- arg
)) == 0)
1123 logger(ctx
, LOG_ERR
,
1124 "%s: %m", __func__
);
1127 free(ifo
->config
[dl
]);
1128 ifo
->config
[dl
] = p
;
1136 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1139 nconf
= realloc(ifo
->config
, sizeof(char *) * (dl
+ 2));
1140 if (nconf
== NULL
) {
1141 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1144 ifo
->config
= nconf
;
1145 ifo
->config
[dl
] = p
;
1146 ifo
->config
[dl
+ 1] = NULL
;
1150 if (parse_addr(ctx
, &addr
, &addr2
, arg
) != 0)
1152 if (strchr(arg
, '/') == NULL
)
1153 addr2
.s_addr
= INADDR_BROADCAST
;
1154 naddr
= realloc(ifo
->whitelist
,
1155 sizeof(in_addr_t
) * (ifo
->whitelist_len
+ 2));
1156 if (naddr
== NULL
) {
1157 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1160 ifo
->whitelist
= naddr
;
1161 ifo
->whitelist
[ifo
->whitelist_len
++] = addr
.s_addr
;
1162 ifo
->whitelist
[ifo
->whitelist_len
++] = addr2
.s_addr
;
1165 if (parse_addr(ctx
, &addr
, &addr2
, arg
) != 0)
1167 if (strchr(arg
, '/') == NULL
)
1168 addr2
.s_addr
= INADDR_BROADCAST
;
1169 naddr
= realloc(ifo
->blacklist
,
1170 sizeof(in_addr_t
) * (ifo
->blacklist_len
+ 2));
1171 if (naddr
== NULL
) {
1172 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1175 ifo
->blacklist
= naddr
;
1176 ifo
->blacklist
[ifo
->blacklist_len
++] = addr
.s_addr
;
1177 ifo
->blacklist
[ifo
->blacklist_len
++] = addr2
.s_addr
;
1181 ctx
->ifdv
= splitv(ctx
, &ctx
->ifdc
, ctx
->ifdv
, arg
);
1184 ifo
->options
&= ~DHCPCD_IPV6
;
1185 ifo
->options
|= DHCPCD_IPV4
;
1188 ifo
->options
&= ~DHCPCD_IPV4
;
1189 ifo
->options
|= DHCPCD_IPV6
;
1192 ifo
->options
|= DHCPCD_IPV4
;
1195 ifo
->options
&= ~DHCPCD_IPV4
;
1198 ifo
->options
|= DHCPCD_IPV6
;
1201 ifo
->options
&= ~DHCPCD_IPV6
;
1205 while (arg
&& *arg
!= '\0') {
1209 if (parse_addr(ctx
, &addr
, NULL
, arg
) != 0)
1211 naddr
= realloc(ifo
->arping
,
1212 sizeof(in_addr_t
) * (ifo
->arping_len
+ 1));
1213 if (naddr
== NULL
) {
1214 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1217 ifo
->arping
= naddr
;
1218 ifo
->arping
[ifo
->arping_len
++] = addr
.s_addr
;
1219 arg
= strskipwhite(fp
);
1223 arg
= set_option_space(ctx
, arg
, &d
, &dl
, &od
, &odl
, ifo
,
1224 &request
, &require
, &no
, &reject
);
1225 if (make_option_mask(d
, dl
, od
, odl
,
1226 ifo
->dstmask
, arg
, 2) != 0)
1228 if (errno
== EINVAL
)
1229 logger(ctx
, LOG_ERR
, "option `%s' does not take"
1230 " an IPv4 address", arg
);
1232 logger(ctx
, LOG_ERR
, "unknown option `%s'", arg
);
1237 free(ifo
->fallback
);
1238 ifo
->fallback
= strdup(arg
);
1239 if (ifo
->fallback
== NULL
) {
1240 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1246 if (ifname
== NULL
) {
1247 logger(ctx
, LOG_ERR
,
1248 "IAID must belong in an interface block");
1251 if (parse_iaid(ifo
->iaid
, arg
, sizeof(ifo
->iaid
)) == -1) {
1252 logger(ctx
, LOG_ERR
, "invalid IAID %s", arg
);
1255 ifo
->options
|= DHCPCD_IAID
;
1258 ifo
->options
|= DHCPCD_IPV6RS
;
1261 ifo
->options
&= ~DHCPCD_IPV6RS
;
1264 ifo
->options
&= ~DHCPCD_IPV6RA_REQRDNSS
;
1267 ifo
->options
|= DHCPCD_IPV6RA_OWN
;
1269 case O_IPV6RA_OWN_D
:
1270 ifo
->options
|= DHCPCD_IPV6RA_OWN_DEFAULT
;
1272 case O_IPV6RA_ACCEPT_NOPUBLIC
:
1273 ifo
->options
|= DHCPCD_IPV6RA_ACCEPT_NOPUBLIC
;
1275 case O_IPV6RA_AUTOCONF
:
1276 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
;
1278 case O_IPV6RA_NOAUTOCONF
:
1279 ifo
->options
&= ~DHCPCD_IPV6RA_AUTOCONF
;
1282 ifo
->options
|= DHCPCD_NOALIAS
;
1286 i
= D6_OPTION_IA_NA
;
1290 i
= D6_OPTION_IA_TA
;
1294 if (ifname
== NULL
) {
1295 logger(ctx
, LOG_ERR
,
1296 "IA PD must belong in an interface block");
1299 i
= D6_OPTION_IA_PD
;
1301 if (ifname
== NULL
&& arg
) {
1302 logger(ctx
, LOG_ERR
,
1303 "IA with IAID must belong in an interface block");
1306 ifo
->options
|= DHCPCD_IA_FORCED
;
1310 fp
= strskipwhite(fp
);
1313 p
= strchr(arg
, '/');
1316 if (parse_iaid(iaid
, arg
, sizeof(iaid
)) == -1) {
1317 logger(ctx
, LOG_ERR
, "invalid IAID: %s", arg
);
1322 for (sl
= 0; sl
< ifo
->ia_len
; sl
++) {
1323 if ((arg
== NULL
&& !ifo
->ia
[sl
].iaid_set
) ||
1324 (ifo
->ia
[sl
].iaid_set
&&
1325 ifo
->ia
[sl
].iaid
[0] == iaid
[0] &&
1326 ifo
->ia
[sl
].iaid
[1] == iaid
[1] &&
1327 ifo
->ia
[sl
].iaid
[2] == iaid
[2] &&
1328 ifo
->ia
[sl
].iaid
[3] == iaid
[3]))
1334 if (ia
&& ia
->ia_type
!= (uint16_t)i
) {
1335 logger(ctx
, LOG_ERR
, "Cannot mix IA for the same IAID");
1339 ia
= realloc(ifo
->ia
,
1340 sizeof(*ifo
->ia
) * (ifo
->ia_len
+ 1));
1342 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1346 ia
= &ifo
->ia
[ifo
->ia_len
++];
1347 ia
->ia_type
= (uint16_t)i
;
1349 ia
->iaid
[0] = iaid
[0];
1350 ia
->iaid
[1] = iaid
[1];
1351 ia
->iaid
[2] = iaid
[2];
1352 ia
->iaid
[3] = iaid
[3];
1356 if (!ia
->iaid_set
||
1358 ia
->ia_type
== D6_OPTION_IA_TA
)
1360 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1364 p
= strchr(arg
, '/');
1367 if (inet_pton(AF_INET6
, arg
, &ia
->addr
) == -1) {
1368 logger(ctx
, LOG_ERR
, "%s: %m", arg
);
1369 memset(&ia
->addr
, 0, sizeof(ia
->addr
));
1371 if (p
&& ia
->ia_type
== D6_OPTION_IA_PD
) {
1372 i
= (int)strtoi(p
, NULL
, 0, 8, 120, &e
);
1374 logger(ctx
, LOG_ERR
,
1375 "%s: failed to convert"
1380 ia
->prefix_len
= (uint8_t)i
;
1387 if (ia
->ia_type
!= D6_OPTION_IA_PD
)
1389 for (p
= fp
; p
; p
= fp
) {
1393 fp
= strskipwhite(fp
);
1395 sla
= realloc(ia
->sla
,
1396 sizeof(*ia
->sla
) * (ia
->sla_len
+ 1));
1398 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1402 sla
= &ia
->sla
[ia
->sla_len
++];
1403 np
= strchr(p
, '/');
1406 if (strlcpy(sla
->ifname
, p
,
1407 sizeof(sla
->ifname
)) >= sizeof(sla
->ifname
))
1409 logger(ctx
, LOG_ERR
, "%s: interface name too long",
1415 np
= strchr(p
, '/');
1421 sla
->sla
= (uint32_t)strtou(p
, NULL
,
1422 0, 0, UINT32_MAX
, &e
);
1425 logger(ctx
, LOG_ERR
,
1426 "%s: failed to convert sla",
1432 sla
->prefix_len
= (uint8_t)strtoi(np
,
1433 NULL
, 0, 0, 128, &e
);
1435 logger(ctx
, LOG_ERR
, "%s: failed to "
1436 "convert prefix len",
1441 sla
->prefix_len
= 0;
1444 sla
->prefix_len
= 0;
1447 for (sl
= 0; sl
< ia
->sla_len
- 1; sl
++) {
1448 slap
= &ia
->sla
[sl
];
1449 if (slap
->sla_set
!= sla
->sla_set
) {
1450 logger(ctx
, LOG_WARNING
,
1451 "%s: cannot mix automatic "
1456 if (sla
->sla_set
== 0 &&
1457 strcmp(slap
->ifname
, sla
->ifname
) == 0)
1459 logger(ctx
, LOG_WARNING
,
1460 "%s: cannot specify the "
1461 "same interface twice with "
1466 if (slap
->sla
== 0 || sla
->sla
== 0) {
1467 logger(ctx
, LOG_ERR
, "%s: cannot"
1468 " assign multiple prefixes"
1474 if (sla
->sla_set
&& sla
->sla
> ia
->sla_max
)
1475 ia
->sla_max
= sla
->sla
;
1482 case O_HOSTNAME_SHORT
:
1483 ifo
->options
|= DHCPCD_HOSTNAME
| DHCPCD_HOSTNAME_SHORT
;
1488 free(ctx
->dev_load
);
1489 ctx
->dev_load
= strdup(arg
);
1493 ifo
->options
&= ~DHCPCD_DEV
;
1496 dop
= &ifo
->dhcp_override
;
1497 dop_len
= &ifo
->dhcp_override_len
;
1501 dop
= &ifo
->nd_override
;
1502 dop_len
= &ifo
->nd_override_len
;
1507 dop
= &ifo
->dhcp6_override
;
1508 dop_len
= &ifo
->dhcp6_override_len
;
1513 dop
= &ifo
->vivso_override
;
1514 dop_len
= &ifo
->vivso_override_len
;
1516 *edop
= *ldop
= NULL
;
1521 dop
= &(*edop
)->embopts
;
1522 dop_len
= &(*edop
)->embopts_len
;
1524 dop
= &(*ldop
)->embopts
;
1525 dop_len
= &(*ldop
)->embopts_len
;
1527 logger(ctx
, LOG_ERR
,
1528 "embed must be after a define or encap");
1535 if (*ldop
== NULL
) {
1536 logger(ctx
, LOG_ERR
, "encap must be after a define");
1539 dop
= &(*ldop
)->encopts
;
1540 dop_len
= &(*ldop
)->encopts_len
;
1543 /* Shared code for define, define6, embed and encap */
1546 if (opt
== O_EMBED
) /* Embedded options don't have codes */
1551 logger(ctx
, LOG_ERR
, "invalid syntax: %s", arg
);
1555 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1557 logger(ctx
, LOG_ERR
, "invalid code: %s", arg
);
1560 arg
= strskipwhite(fp
);
1562 logger(ctx
, LOG_ERR
, "invalid syntax");
1570 np
= strchr(arg
, ':');
1574 bp
= NULL
; /* No bitflag */
1575 l
= (long)strtou(np
, NULL
, 0, 0, LONG_MAX
, &e
);
1577 logger(ctx
,LOG_ERR
, "failed to convert length");
1582 bp
= strchr(arg
, '='); /* bitflag assignment */
1587 if (strcasecmp(arg
, "request") == 0) {
1589 arg
= strskipwhite(fp
);
1592 logger(ctx
, LOG_ERR
, "incomplete request type");
1596 } else if (strcasecmp(arg
, "norequest") == 0) {
1598 arg
= strskipwhite(fp
);
1601 logger(ctx
, LOG_ERR
, "incomplete request type");
1606 if (strcasecmp(arg
, "index") == 0) {
1608 arg
= strskipwhite(fp
);
1611 logger(ctx
, LOG_ERR
, "incomplete index type");
1616 if (strcasecmp(arg
, "array") == 0) {
1618 arg
= strskipwhite(fp
);
1621 logger(ctx
, LOG_ERR
, "incomplete array type");
1626 if (strcasecmp(arg
, "ipaddress") == 0)
1628 else if (strcasecmp(arg
, "ip6address") == 0)
1630 else if (strcasecmp(arg
, "string") == 0)
1632 else if (strcasecmp(arg
, "byte") == 0)
1634 else if (strcasecmp(arg
, "bitflags") == 0)
1636 else if (strcasecmp(arg
, "uint16") == 0)
1638 else if (strcasecmp(arg
, "int16") == 0)
1640 else if (strcasecmp(arg
, "uint32") == 0)
1642 else if (strcasecmp(arg
, "int32") == 0)
1644 else if (strcasecmp(arg
, "flag") == 0)
1646 else if (strcasecmp(arg
, "raw") == 0)
1648 else if (strcasecmp(arg
, "ascii") == 0)
1649 t
|= STRING
| ASCII
;
1650 else if (strcasecmp(arg
, "domain") == 0)
1651 t
|= STRING
| DOMAIN
| RFC1035
;
1652 else if (strcasecmp(arg
, "dname") == 0)
1653 t
|= STRING
| DOMAIN
;
1654 else if (strcasecmp(arg
, "binhex") == 0)
1655 t
|= STRING
| BINHEX
;
1656 else if (strcasecmp(arg
, "embed") == 0)
1658 else if (strcasecmp(arg
, "encap") == 0)
1660 else if (strcasecmp(arg
, "rfc3361") ==0)
1661 t
|= STRING
| RFC3361
;
1662 else if (strcasecmp(arg
, "rfc3442") ==0)
1663 t
|= STRING
| RFC3442
;
1664 else if (strcasecmp(arg
, "rfc5969") == 0)
1665 t
|= STRING
| RFC5969
;
1666 else if (strcasecmp(arg
, "option") == 0)
1669 logger(ctx
, LOG_ERR
, "unknown type: %s", arg
);
1672 if (l
&& !(t
& (STRING
| BINHEX
))) {
1673 logger(ctx
, LOG_WARNING
,
1674 "ignoring length for type `%s'", arg
);
1677 if (t
& ARRAY
&& t
& (STRING
| BINHEX
) &&
1678 !(t
& (RFC1035
| DOMAIN
)))
1680 logger(ctx
, LOG_WARNING
, "ignoring array for strings");
1685 logger(ctx
, LOG_WARNING
,
1686 "missing bitflag assignment");
1690 if (!(t
& OPTION
)) {
1691 logger(ctx
, LOG_ERR
,
1692 "type %s requires a variable name", arg
);
1697 arg
= strskipwhite(fp
);
1701 if (strcasecmp(arg
, "reserved")) {
1704 logger(ctx
, LOG_ERR
,
1705 "%s: %m", __func__
);
1713 if (opt
!= O_EMBED
) {
1714 for (dl
= 0, ndop
= *dop
; dl
< *dop_len
; dl
++, ndop
++)
1716 /* type 0 seems freshly malloced struct
1718 if (ndop
->option
== u
|| ndop
->type
== 0)
1726 if ((ndop
= realloc(*dop
,
1727 sizeof(**dop
) * ((*dop_len
) + 1))) == NULL
)
1729 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1734 ndop
= &(*dop
)[(*dop_len
)++];
1735 ndop
->embopts
= NULL
;
1736 ndop
->embopts_len
= 0;
1737 ndop
->encopts
= NULL
;
1738 ndop
->encopts_len
= 0;
1740 free_dhcp_opt_embenc(ndop
);
1741 ndop
->option
= (uint32_t)u
; /* could have been 0 */
1743 ndop
->len
= (size_t)l
;
1747 memcpy(ndop
->bitflags
, bp
, dl
);
1748 memset(ndop
->bitflags
+ dl
, 0,
1749 sizeof(ndop
->bitflags
) - dl
);
1751 memset(ndop
->bitflags
, 0, sizeof(ndop
->bitflags
));
1752 /* Save the define for embed and encap options */
1769 u
= (uint32_t)strtou(arg
, NULL
, 0, 0, UINT32_MAX
, &e
);
1771 logger(ctx
, LOG_ERR
, "invalid code: %s", arg
);
1775 s
= parse_string(NULL
, 0, fp
);
1777 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1781 if (dl
+ (sizeof(uint16_t) * 2) > UINT16_MAX
) {
1782 logger(ctx
, LOG_ERR
, "vendor class is too big");
1787 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1790 parse_string(np
, dl
, fp
);
1795 vivco
= realloc(ifo
->vivco
, sizeof(*ifo
->vivco
) *
1796 (ifo
->vivco_len
+ 1));
1797 if (vivco
== NULL
) {
1798 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1802 ifo
->vivco_en
= (uint32_t)u
;
1803 vivco
= &ifo
->vivco
[ifo
->vivco_len
++];
1805 vivco
->data
= (uint8_t *)np
;
1807 case O_AUTHPROTOCOL
:
1811 if (strcasecmp(arg
, "token") == 0)
1812 ifo
->auth
.protocol
= AUTH_PROTO_TOKEN
;
1813 else if (strcasecmp(arg
, "delayed") == 0)
1814 ifo
->auth
.protocol
= AUTH_PROTO_DELAYED
;
1815 else if (strcasecmp(arg
, "delayedrealm") == 0)
1816 ifo
->auth
.protocol
= AUTH_PROTO_DELAYEDREALM
;
1818 logger(ctx
, LOG_ERR
, "%s: unsupported protocol", arg
);
1821 arg
= strskipwhite(fp
);
1824 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1825 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1826 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1831 if (strcasecmp(arg
, "hmacmd5") == 0 ||
1832 strcasecmp(arg
, "hmac-md5") == 0)
1833 ifo
->auth
.algorithm
= AUTH_ALG_HMAC_MD5
;
1835 logger(ctx
, LOG_ERR
, "%s: unsupported algorithm", arg
);
1840 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1841 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1844 if (strcasecmp(arg
, "monocounter") == 0) {
1845 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1846 ifo
->auth
.options
|= DHCPCD_AUTH_RDM_COUNTER
;
1847 } else if (strcasecmp(arg
, "monotonic") ==0 ||
1848 strcasecmp(arg
, "monotime") == 0)
1849 ifo
->auth
.rdm
= AUTH_RDM_MONOTONIC
;
1851 logger(ctx
, LOG_ERR
, "%s: unsupported RDM", arg
);
1854 ifo
->auth
.options
|= DHCPCD_AUTH_SEND
;
1859 logger(ctx
, LOG_ERR
, "authtoken requires a realm");
1863 token
= malloc(sizeof(*token
));
1864 if (token
== NULL
) {
1865 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1869 if (parse_uint32(&token
->secretid
, arg
) == -1) {
1870 logger(ctx
, LOG_ERR
, "%s: not a number", arg
);
1877 logger(ctx
, LOG_ERR
, "authtoken requies an a key");
1882 s
= parse_string(NULL
, 0, arg
);
1884 logger(ctx
, LOG_ERR
, "realm_len: %m");
1889 token
->realm_len
= (size_t)s
;
1890 token
->realm
= malloc(token
->realm_len
);
1891 if (token
->realm
== NULL
) {
1893 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
1896 parse_string((char *)token
->realm
, token
->realm_len
,
1899 token
->realm_len
= 0;
1900 token
->realm
= NULL
;
1905 logger(ctx
, LOG_ERR
, "authtoken requies an an expiry date");
1913 np
= strchr(arg
, '"');
1917 if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "forever") == 0)
1922 memset(&tm
, 0, sizeof(tm
));
1923 if (strptime(arg
, "%Y-%m-%d %H:%M", &tm
) == NULL
) {
1924 logger(ctx
, LOG_ERR
, "%s: invalid date time", arg
);
1929 if ((token
->expire
= mktime(&tm
)) == (time_t)-1) {
1930 logger(ctx
, LOG_ERR
, "%s: mktime: %m", __func__
);
1937 s
= parse_string(NULL
, 0, arg
);
1938 if (s
== -1 || s
== 0) {
1939 logger(ctx
, LOG_ERR
, s
== -1 ? "token_len: %m" :
1940 "authtoken needs a key");
1945 token
->key_len
= (size_t)s
;
1946 token
->key
= malloc(token
->key_len
);
1947 parse_string((char *)token
->key
, token
->key_len
, arg
);
1948 TAILQ_INSERT_TAIL(&ifo
->auth
.tokens
, token
, next
);
1950 case O_AUTHNOTREQUIRED
:
1951 ifo
->auth
.options
&= ~DHCPCD_AUTH_REQUIRE
;
1954 ifo
->options
|= DHCPCD_DHCP
| DHCPCD_IPV4
;
1957 ifo
->options
&= ~DHCPCD_DHCP
;
1960 ifo
->options
|= DHCPCD_DHCP6
| DHCPCD_IPV6
;
1963 ifo
->options
&= ~DHCPCD_DHCP6
;
1967 l
= sysconf(_SC_GETGR_R_SIZE_MAX
);
1974 logger(ctx
, LOG_ERR
, "%s: malloc: %m", __func__
);
1977 while ((i
= getgrnam_r(arg
, &grpbuf
, p
, (size_t)l
, &grp
)) ==
1982 logger(ctx
, LOG_ERR
, "control_group: out of buffer");
1987 np
= realloc(p
, dl
);
1989 logger(ctx
, LOG_ERR
, "control_group: realloc: %m");
1997 logger(ctx
, LOG_ERR
, "getgrnam_r: %m");
2002 logger(ctx
, LOG_ERR
, "controlgroup: %s: not found", arg
);
2006 ctx
->control_group
= grp
->gr_gid
;
2009 grp
= getgrnam(arg
);
2011 logger(ctx
, LOG_ERR
, "controlgroup: %s: not found", arg
);
2014 ctx
->control_group
= grp
->gr_gid
;
2018 ifo
->options
|= DHCPCD_GATEWAY
;
2021 ifo
->options
&= ~DHCPCD_IF_UP
;
2024 if (strcmp(arg
, "private") == 0 ||
2025 strcmp(arg
, "stableprivate") == 0 ||
2026 strcmp(arg
, "stable") == 0)
2027 ifo
->options
|= DHCPCD_SLAACPRIVATE
;
2029 ifo
->options
&= ~DHCPCD_SLAACPRIVATE
;
2032 ifo
->options
|= DHCPCD_BOOTP
;
2035 ifo
->options
&= ~DHCPCD_INITIAL_DELAY
;
2045 parse_config_line(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2046 struct if_options
*ifo
, const char *opt
, char *line
,
2047 struct dhcp_opt
**ldop
, struct dhcp_opt
**edop
)
2051 for (i
= 0; i
< sizeof(cf_options
) / sizeof(cf_options
[0]); i
++) {
2052 if (!cf_options
[i
].name
||
2053 strcmp(cf_options
[i
].name
, opt
) != 0)
2056 if (cf_options
[i
].has_arg
== required_argument
&& !line
) {
2058 PACKAGE
": option requires an argument -- %s\n",
2063 return parse_option(ctx
, ifname
, ifo
, cf_options
[i
].val
, line
,
2067 logger(ctx
, LOG_ERR
, "unknown option: %s", opt
);
2072 finish_config(struct if_options
*ifo
)
2075 /* Terminate the encapsulated options */
2076 if (ifo
->vendor
[0] && !(ifo
->options
& DHCPCD_VENDORRAW
)) {
2078 ifo
->vendor
[ifo
->vendor
[0]] = DHO_END
;
2079 /* We are called twice.
2080 * This should be fixed, but in the meantime, this
2081 * guard should suffice */
2082 ifo
->options
|= DHCPCD_VENDORRAW
;
2086 /* Handy routine to read very long lines in text files.
2087 * This means we read the whole line and avoid any nasty buffer overflows.
2088 * We strip leading space and avoid comment lines, making the code that calls
2091 get_line(char ** __restrict buf
, size_t * __restrict buflen
,
2092 FILE * __restrict fp
)
2098 bytes
= getline(buf
, buflen
, fp
);
2101 for (p
= *buf
; *p
== ' ' || *p
== '\t'; p
++)
2103 } while (*p
== '\0' || *p
== '\n' || *p
== '#' || *p
== ';');
2104 if ((*buf
)[--bytes
] == '\n')
2105 (*buf
)[bytes
] = '\0';
2110 read_config(struct dhcpcd_ctx
*ctx
,
2111 const char *ifname
, const char *ssid
, const char *profile
)
2113 struct if_options
*ifo
;
2116 char *line
, *buf
, *option
, *p
;
2119 int skip
, have_profile
, new_block
, had_block
;
2120 #ifndef EMBEDDED_CONFIG
2121 const char * const *e
;
2124 #if !defined(INET) || !defined(INET6)
2126 struct dhcp_opt
*opt
;
2128 struct dhcp_opt
*ldop
, *edop
;
2130 /* Seed our default options */
2131 ifo
= calloc(1, sizeof(*ifo
));
2133 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2136 ifo
->options
|= DHCPCD_DAEMONISE
| DHCPCD_LINK
| DHCPCD_INITIAL_DELAY
;
2137 ifo
->options
|= DHCPCD_IF_UP
;
2139 ifo
->options
|= DHCPCD_DEV
;
2142 ifo
->options
|= DHCPCD_IPV4
| DHCPCD_DHCP
| DHCPCD_IPV4LL
;
2143 ifo
->options
|= DHCPCD_GATEWAY
| DHCPCD_ARP
;
2146 ifo
->options
|= DHCPCD_IPV6
| DHCPCD_IPV6RS
;
2147 ifo
->options
|= DHCPCD_IPV6RA_AUTOCONF
| DHCPCD_IPV6RA_REQRDNSS
;
2148 ifo
->options
|= DHCPCD_DHCP6
;
2150 ifo
->timeout
= DEFAULT_TIMEOUT
;
2151 ifo
->reboot
= DEFAULT_REBOOT
;
2153 ifo
->auth
.options
|= DHCPCD_AUTH_REQUIRE
;
2154 TAILQ_INIT(&ifo
->auth
.tokens
);
2156 vlen
= dhcp_vendor((char *)ifo
->vendorclassid
+ 1,
2157 sizeof(ifo
->vendorclassid
) - 1);
2158 ifo
->vendorclassid
[0] = (uint8_t)(vlen
== -1 ? 0 : vlen
);
2163 /* Parse our embedded options file */
2164 if (ifname
== NULL
) {
2165 /* Space for initial estimates */
2166 #if defined(INET) && defined(INITDEFINES)
2167 ifo
->dhcp_override
=
2168 calloc(INITDEFINES
, sizeof(*ifo
->dhcp_override
));
2169 if (ifo
->dhcp_override
== NULL
)
2170 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2172 ifo
->dhcp_override_len
= INITDEFINES
;
2175 #if defined(INET6) && defined(INITDEFINENDS)
2177 calloc(INITDEFINENDS
, sizeof(*ifo
->nd_override
));
2178 if (ifo
->nd_override
== NULL
)
2179 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2181 ifo
->nd_override_len
= INITDEFINENDS
;
2183 #if defined(INET6) && defined(INITDEFINE6S)
2184 ifo
->dhcp6_override
=
2185 calloc(INITDEFINE6S
, sizeof(*ifo
->dhcp6_override
));
2186 if (ifo
->dhcp6_override
== NULL
)
2187 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2189 ifo
->dhcp6_override_len
= INITDEFINE6S
;
2192 /* Now load our embedded config */
2193 #ifdef EMBEDDED_CONFIG
2194 fp
= fopen(EMBEDDED_CONFIG
, "r");
2196 logger(ctx
, LOG_ERR
, "fopen `%s': %m", EMBEDDED_CONFIG
);
2198 while (fp
&& (line
= get_line(&buf
, &buflen
, fp
))) {
2201 buf
= malloc(buflen
);
2203 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2207 for (e
= dhcpcd_embedded_conf
; *e
; e
++) {
2208 ol
= strlen(*e
) + 1;
2211 buf
= realloc(buf
, buflen
);
2213 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2218 memcpy(buf
, *e
, ol
);
2221 option
= strsep(&line
, " \t");
2223 line
= strskipwhite(line
);
2224 /* Trim trailing whitespace */
2225 if (line
&& *line
) {
2226 p
= line
+ strlen(line
) - 1;
2228 (*p
== ' ' || *p
== '\t') &&
2232 parse_config_line(ctx
, NULL
, ifo
, option
, line
,
2237 #ifdef EMBEDDED_CONFIG
2242 ctx
->dhcp_opts
= ifo
->dhcp_override
;
2243 ctx
->dhcp_opts_len
= ifo
->dhcp_override_len
;
2245 for (i
= 0, opt
= ifo
->dhcp_override
;
2246 i
< ifo
->dhcp_override_len
;
2248 free_dhcp_opt_embenc(opt
);
2249 free(ifo
->dhcp_override
);
2251 ifo
->dhcp_override
= NULL
;
2252 ifo
->dhcp_override_len
= 0;
2255 ctx
->nd_opts
= ifo
->nd_override
;
2256 ctx
->nd_opts_len
= ifo
->nd_override_len
;
2257 ctx
->dhcp6_opts
= ifo
->dhcp6_override
;
2258 ctx
->dhcp6_opts_len
= ifo
->dhcp6_override_len
;
2260 for (i
= 0, opt
= ifo
->nd_override
;
2261 i
< ifo
->nd_override_len
;
2263 free_dhcp_opt_embenc(opt
);
2264 free(ifo
->nd_override
);
2265 for (i
= 0, opt
= ifo
->dhcp6_override
;
2266 i
< ifo
->dhcp6_override_len
;
2268 free_dhcp_opt_embenc(opt
);
2269 free(ifo
->dhcp6_override
);
2271 ifo
->nd_override
= NULL
;
2272 ifo
->nd_override_len
= 0;
2273 ifo
->dhcp6_override
= NULL
;
2274 ifo
->dhcp6_override_len
= 0;
2276 ctx
->vivso
= ifo
->vivso_override
;
2277 ctx
->vivso_len
= ifo
->vivso_override_len
;
2278 ifo
->vivso_override
= NULL
;
2279 ifo
->vivso_override_len
= 0;
2282 /* Parse our options file */
2283 fp
= fopen(ctx
->cffile
, "r");
2285 if (strcmp(ctx
->cffile
, CONFIG
))
2286 logger(ctx
, LOG_ERR
, "fopen `%s': %m", ctx
->cffile
);
2290 if (stat(ctx
->cffile
, &sb
) == 0)
2291 ifo
->mtime
= sb
.st_mtime
;
2294 skip
= have_profile
= new_block
= 0;
2295 had_block
= ifname
== NULL
? 1 : 0;
2296 while ((line
= get_line(&buf
, &buflen
, fp
))) {
2297 option
= strsep(&line
, " \t");
2299 line
= strskipwhite(line
);
2300 /* Trim trailing whitespace */
2301 if (line
&& *line
) {
2302 p
= line
+ strlen(line
) - 1;
2304 (*p
== ' ' || *p
== '\t') &&
2308 if (skip
== 0 && new_block
) {
2311 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2313 /* Start of an interface block, skip if not ours */
2314 if (strcmp(option
, "interface") == 0) {
2318 if (ifname
&& line
&& strcmp(line
, ifname
) == 0)
2325 n
= realloc(ctx
->ifcv
,
2326 sizeof(char *) * ((size_t)ctx
->ifcc
+ 1));
2328 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2332 ctx
->ifcv
[ctx
->ifcc
] = strdup(line
);
2333 if (ctx
->ifcv
[ctx
->ifcc
] == NULL
) {
2334 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
2338 logger(ctx
, LOG_DEBUG
, "allowing interface %s",
2339 ctx
->ifcv
[ctx
->ifcc
- 1]);
2342 /* Start of an ssid block, skip if not ours */
2343 if (strcmp(option
, "ssid") == 0) {
2345 if (ssid
&& line
&& strcmp(line
, ssid
) == 0)
2351 /* Start of a profile block, skip if not ours */
2352 if (strcmp(option
, "profile") == 0) {
2354 if (profile
&& line
&& strcmp(line
, profile
) == 0) {
2361 /* Skip arping if we have selected a profile but not parsing
2363 if (profile
&& !have_profile
&& strcmp(option
, "arping") == 0)
2367 parse_config_line(ctx
, ifname
, ifo
, option
, line
, &ldop
, &edop
);
2372 if (profile
&& !have_profile
) {
2379 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2385 add_options(struct dhcpcd_ctx
*ctx
, const char *ifname
,
2386 struct if_options
*ifo
, int argc
, char **argv
)
2389 unsigned long long wait_opts
;
2396 /* Don't apply the command line wait options to each interface,
2397 * only use the dhcpcd.conf entry for that. */
2399 wait_opts
= ifo
->options
& DHCPCD_WAITOPTS
;
2400 while ((opt
= getopt_long(argc
, argv
, IF_OPTS
, cf_options
, &oi
)) != -1)
2402 r
= parse_option(ctx
, ifname
, ifo
, opt
, optarg
, NULL
, NULL
);
2406 if (ifname
!= NULL
) {
2407 ifo
->options
&= ~DHCPCD_WAITOPTS
;
2408 ifo
->options
|= wait_opts
;
2416 free_options(struct if_options
*ifo
)
2419 struct dhcp_opt
*opt
;
2421 struct token
*token
;
2426 while (ifo
->environ
[i
])
2427 free(ifo
->environ
[i
++]);
2432 while (ifo
->config
[i
])
2433 free(ifo
->config
[i
++]);
2436 ipv4_freeroutes(ifo
->routes
);
2439 free(ifo
->blacklist
);
2440 free(ifo
->fallback
);
2442 for (opt
= ifo
->dhcp_override
;
2443 ifo
->dhcp_override_len
> 0;
2444 opt
++, ifo
->dhcp_override_len
--)
2445 free_dhcp_opt_embenc(opt
);
2446 free(ifo
->dhcp_override
);
2447 for (opt
= ifo
->nd_override
;
2448 ifo
->nd_override_len
> 0;
2449 opt
++, ifo
->nd_override_len
--)
2450 free_dhcp_opt_embenc(opt
);
2451 free(ifo
->nd_override
);
2452 for (opt
= ifo
->dhcp6_override
;
2453 ifo
->dhcp6_override_len
> 0;
2454 opt
++, ifo
->dhcp6_override_len
--)
2455 free_dhcp_opt_embenc(opt
);
2456 free(ifo
->dhcp6_override
);
2457 for (vo
= ifo
->vivco
;
2459 vo
++, ifo
->vivco_len
--)
2462 for (opt
= ifo
->vivso_override
;
2463 ifo
->vivso_override_len
> 0;
2464 opt
++, ifo
->vivso_override_len
--)
2465 free_dhcp_opt_embenc(opt
);
2466 free(ifo
->vivso_override
);
2469 for (; ifo
->ia_len
> 0; ifo
->ia_len
--)
2470 free(ifo
->ia
[ifo
->ia_len
- 1].sla
);
2474 while ((token
= TAILQ_FIRST(&ifo
->auth
.tokens
))) {
2475 TAILQ_REMOVE(&ifo
->auth
.tokens
, token
, next
);
2476 if (token
->realm_len
)