Update to dhcpcd-9.3.4 with the following changes:
[dragonfly.git] / contrib / dhcpcd / src / if-options.c
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * dhcpcd - DHCP client daemon
4  * Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
5  * All rights reserved
6
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
15  *
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
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/param.h>
30 #include <sys/types.h>
31
32 #include <arpa/inet.h>
33
34 #include <ctype.h>
35 #include <errno.h>
36 #include <getopt.h>
37 #include <grp.h>
38 #include <inttypes.h>
39 #include <limits.h>
40 #include <paths.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <time.h>
46
47 #include "config.h"
48 #include "common.h"
49 #include "dhcp.h"
50 #include "dhcp6.h"
51 #include "dhcpcd-embedded.h"
52 #include "duid.h"
53 #include "if.h"
54 #include "if-options.h"
55 #include "ipv4.h"
56 #include "logerr.h"
57 #include "sa.h"
58
59 #define IN_CONFIG_BLOCK(ifo)    ((ifo)->options & DHCPCD_FORKED)
60 #define SET_CONFIG_BLOCK(ifo)   ((ifo)->options |= DHCPCD_FORKED)
61 #define CLEAR_CONFIG_BLOCK(ifo) ((ifo)->options &= ~DHCPCD_FORKED)
62
63 static unsigned long long default_options;
64
65 const struct option cf_options[] = {
66         {"background",      no_argument,       NULL, 'b'},
67         {"script",          required_argument, NULL, 'c'},
68         {"debug",           no_argument,       NULL, 'd'},
69         {"env",             required_argument, NULL, 'e'},
70         {"config",          required_argument, NULL, 'f'},
71         {"reconfigure",     no_argument,       NULL, 'g'},
72         {"hostname",        optional_argument, NULL, 'h'},
73         {"vendorclassid",   optional_argument, NULL, 'i'},
74         {"logfile",         required_argument, NULL, 'j'},
75         {"release",         no_argument,       NULL, 'k'},
76         {"leasetime",       required_argument, NULL, 'l'},
77         {"metric",          required_argument, NULL, 'm'},
78         {"rebind",          no_argument,       NULL, 'n'},
79         {"option",          required_argument, NULL, 'o'},
80         {"persistent",      no_argument,       NULL, 'p'},
81         {"quiet",           no_argument,       NULL, 'q'},
82         {"request",         optional_argument, NULL, 'r'},
83         {"inform",          optional_argument, NULL, 's'},
84         {"inform6",         optional_argument, NULL, O_INFORM6},
85         {"timeout",         required_argument, NULL, 't'},
86         {"userclass",       required_argument, NULL, 'u'},
87 #ifndef SMALL
88         {"msuserclass",     required_argument, NULL, O_MSUSERCLASS},
89 #endif
90         {"vendor",          required_argument, NULL, 'v'},
91         {"waitip",          optional_argument, NULL, 'w'},
92         {"exit",            no_argument,       NULL, 'x'},
93         {"allowinterfaces", required_argument, NULL, 'z'},
94         {"reboot",          required_argument, NULL, 'y'},
95         {"noarp",           no_argument,       NULL, 'A'},
96         {"nobackground",    no_argument,       NULL, 'B'},
97         {"nohook",          required_argument, NULL, 'C'},
98         {"duid",            optional_argument, NULL, 'D'},
99         {"lastlease",       no_argument,       NULL, 'E'},
100         {"fqdn",            optional_argument, NULL, 'F'},
101         {"nogateway",       no_argument,       NULL, 'G'},
102         {"xidhwaddr",       no_argument,       NULL, 'H'},
103         {"clientid",        optional_argument, NULL, 'I'},
104         {"broadcast",       no_argument,       NULL, 'J'},
105         {"nolink",          no_argument,       NULL, 'K'},
106         {"noipv4ll",        no_argument,       NULL, 'L'},
107         {"master",          no_argument,       NULL, 'M'},
108         {"renew",           no_argument,       NULL, 'N'},
109         {"nooption",        required_argument, NULL, 'O'},
110         {"printpidfile",    no_argument,       NULL, 'P'},
111         {"require",         required_argument, NULL, 'Q'},
112         {"static",          required_argument, NULL, 'S'},
113         {"test",            no_argument,       NULL, 'T'},
114         {"dumplease",       no_argument,       NULL, 'U'},
115         {"variables",       no_argument,       NULL, 'V'},
116         {"whitelist",       required_argument, NULL, 'W'},
117         {"blacklist",       required_argument, NULL, 'X'},
118         {"denyinterfaces",  required_argument, NULL, 'Z'},
119         {"oneshot",         no_argument,       NULL, '1'},
120         {"ipv4only",        no_argument,       NULL, '4'},
121         {"ipv6only",        no_argument,       NULL, '6'},
122         {"anonymous",       no_argument,       NULL, O_ANONYMOUS},
123         {"arping",          required_argument, NULL, O_ARPING},
124         {"destination",     required_argument, NULL, O_DESTINATION},
125         {"fallback",        required_argument, NULL, O_FALLBACK},
126         {"ipv6rs",          no_argument,       NULL, O_IPV6RS},
127         {"noipv6rs",        no_argument,       NULL, O_NOIPV6RS},
128         {"ipv6ra_autoconf", no_argument,       NULL, O_IPV6RA_AUTOCONF},
129         {"ipv6ra_noautoconf", no_argument,     NULL, O_IPV6RA_NOAUTOCONF},
130         {"ipv6ra_fork",     no_argument,       NULL, O_IPV6RA_FORK},
131         {"ipv4",            no_argument,       NULL, O_IPV4},
132         {"noipv4",          no_argument,       NULL, O_NOIPV4},
133         {"ipv6",            no_argument,       NULL, O_IPV6},
134         {"noipv6",          no_argument,       NULL, O_NOIPV6},
135         {"noalias",         no_argument,       NULL, O_NOALIAS},
136         {"iaid",            required_argument, NULL, O_IAID},
137         {"ia_na",           optional_argument, NULL, O_IA_NA},
138         {"ia_ta",           optional_argument, NULL, O_IA_TA},
139         {"ia_pd",           optional_argument, NULL, O_IA_PD},
140         {"hostname_short",  no_argument,       NULL, O_HOSTNAME_SHORT},
141         {"dev",             required_argument, NULL, O_DEV},
142         {"nodev",           no_argument,       NULL, O_NODEV},
143         {"define",          required_argument, NULL, O_DEFINE},
144         {"definend",        required_argument, NULL, O_DEFINEND},
145         {"define6",         required_argument, NULL, O_DEFINE6},
146         {"embed",           required_argument, NULL, O_EMBED},
147         {"encap",           required_argument, NULL, O_ENCAP},
148         {"vendopt",         required_argument, NULL, O_VENDOPT},
149         {"vendclass",       required_argument, NULL, O_VENDCLASS},
150         {"authprotocol",    required_argument, NULL, O_AUTHPROTOCOL},
151         {"authtoken",       required_argument, NULL, O_AUTHTOKEN},
152         {"noauthrequired",  no_argument,       NULL, O_AUTHNOTREQUIRED},
153         {"dhcp",            no_argument,       NULL, O_DHCP},
154         {"nodhcp",          no_argument,       NULL, O_NODHCP},
155         {"dhcp6",           no_argument,       NULL, O_DHCP6},
156         {"nodhcp6",         no_argument,       NULL, O_NODHCP6},
157         {"controlgroup",    required_argument, NULL, O_CONTROLGRP},
158         {"slaac",           required_argument, NULL, O_SLAAC},
159         {"gateway",         no_argument,       NULL, O_GATEWAY},
160         {"reject",          required_argument, NULL, O_REJECT},
161         {"bootp",           no_argument,       NULL, O_BOOTP},
162         {"nodelay",         no_argument,       NULL, O_NODELAY},
163         {"noup",            no_argument,       NULL, O_NOUP},
164         {"lastleaseextend", no_argument,       NULL, O_LASTLEASE_EXTEND},
165         {"inactive",        no_argument,       NULL, O_INACTIVE},
166         {"mudurl",          required_argument, NULL, O_MUDURL},
167         {"link_rcvbuf",     required_argument, NULL, O_LINK_RCVBUF},
168         {"configure",       no_argument,       NULL, O_CONFIGURE},
169         {"noconfigure",     no_argument,       NULL, O_NOCONFIGURE},
170         {NULL,              0,                 NULL, '\0'}
171 };
172
173 static char *
174 add_environ(char ***array, const char *value, int uniq)
175 {
176         char **newlist, **list = *array;
177         size_t i = 0, l, lv;
178         char *match = NULL, *p, *n;
179
180         match = strdup(value);
181         if (match == NULL) {
182                 logerr(__func__);
183                 return NULL;
184         }
185         p = strchr(match, '=');
186         if (p == NULL) {
187                 logerrx("%s: no assignment: %s", __func__, value);
188                 free(match);
189                 return NULL;
190         }
191         *p++ = '\0';
192         l = strlen(match);
193
194         while (list && list[i]) {
195                 if (match && strncmp(list[i], match, l) == 0) {
196                         if (uniq) {
197                                 n = strdup(value);
198                                 if (n == NULL) {
199                                         logerr(__func__);
200                                         free(match);
201                                         return NULL;
202                                 }
203                                 free(list[i]);
204                                 list[i] = n;
205                         } else {
206                                 /* Append a space and the value to it */
207                                 l = strlen(list[i]);
208                                 lv = strlen(p);
209                                 n = realloc(list[i], l + lv + 2);
210                                 if (n == NULL) {
211                                         logerr(__func__);
212                                         free(match);
213                                         return NULL;
214                                 }
215                                 list[i] = n;
216                                 list[i][l] = ' ';
217                                 memcpy(list[i] + l + 1, p, lv);
218                                 list[i][l + lv + 1] = '\0';
219                         }
220                         free(match);
221                         return list[i];
222                 }
223                 i++;
224         }
225
226         free(match);
227         n = strdup(value);
228         if (n == NULL) {
229                 logerr(__func__);
230                 return NULL;
231         }
232         newlist = reallocarray(list, i + 2, sizeof(char *));
233         if (newlist == NULL) {
234                 logerr(__func__);
235                 free(n);
236                 return NULL;
237         }
238         newlist[i] = n;
239         newlist[i + 1] = NULL;
240         *array = newlist;
241         return newlist[i];
242 }
243
244 #define PARSE_STRING            0
245 #define PARSE_STRING_NULL       1
246 #define PARSE_HWADDR            2
247 #define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
248 #define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
249 #define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
250 static ssize_t
251 parse_str(char *sbuf, size_t slen, const char *str, int flags)
252 {
253         size_t l;
254         const char *p, *end;
255         int i;
256         char c[4], cmd;
257
258         end = str + strlen(str);
259         /* If surrounded by quotes then it's a string */
260         if (*str == '"') {
261                 p = end - 1;
262                 if (*p == '"') {
263                         str++;
264                         end = p;
265                 }
266         } else {
267                 l = (size_t)hwaddr_aton(NULL, str);
268                 if ((ssize_t) l != -1 && l > 1) {
269                         if (l > slen) {
270                                 errno = ENOBUFS;
271                                 return -1;
272                         }
273                         hwaddr_aton((uint8_t *)sbuf, str);
274                         return (ssize_t)l;
275                 }
276         }
277
278         /* Process escapes */
279         l = 0;
280         /* If processing a string on the clientid, first byte should be
281          * 0 to indicate a non hardware type */
282         if (flags == PARSE_HWADDR && *str) {
283                 if (sbuf)
284                         *sbuf++ = 0;
285                 l++;
286         }
287         c[3] = '\0';
288         while (str < end) {
289                 if (++l > slen && sbuf) {
290                         errno = ENOBUFS;
291                         return -1;
292                 }
293                 if (*str == '\\') {
294                         str++;
295                         switch((cmd = *str++)) {
296                         case '\0':
297                                 str--;
298                                 break;
299                         case 'b':
300                                 if (sbuf)
301                                         *sbuf++ = '\b';
302                                 break;
303                         case 'n':
304                                 if (sbuf)
305                                         *sbuf++ = '\n';
306                                 break;
307                         case 'r':
308                                 if (sbuf)
309                                         *sbuf++ = '\r';
310                                 break;
311                         case 't':
312                                 if (sbuf)
313                                         *sbuf++ = '\t';
314                                 break;
315                         case 'x':
316                                 /* Grab a hex code */
317                                 c[1] = '\0';
318                                 for (i = 0; i < 2; i++) {
319                                         if (isxdigit((unsigned char)*str) == 0)
320                                                 break;
321                                         c[i] = *str++;
322                                 }
323                                 if (c[1] != '\0' && sbuf) {
324                                         c[2] = '\0';
325                                         *sbuf++ = (char)strtol(c, NULL, 16);
326                                 } else
327                                         l--;
328                                 break;
329                         case '0':
330                                 /* Grab an octal code */
331                                 c[2] = '\0';
332                                 for (i = 0; i < 3; i++) {
333                                         if (*str < '0' || *str > '7')
334                                                 break;
335                                         c[i] = *str++;
336                                 }
337                                 if (c[2] != '\0' && sbuf) {
338                                         i = (int)strtol(c, NULL, 8);
339                                         if (i > 255)
340                                                 i = 255;
341                                         *sbuf ++= (char)i;
342                                 } else
343                                         l--;
344                                 break;
345                         default:
346                                 if (sbuf)
347                                         *sbuf++ = cmd;
348                                 break;
349                         }
350                 } else {
351                         if (sbuf)
352                                 *sbuf++ = *str;
353                         str++;
354                 }
355         }
356         if (flags == PARSE_STRING_NULL) {
357                 l++;
358                 if (sbuf != NULL) {
359                         if (l > slen) {
360                                 errno = ENOBUFS;
361                                 return -1;
362                         }
363                         *sbuf = '\0';
364                 }
365         }
366         return (ssize_t)l;
367 }
368
369 static int
370 parse_iaid1(uint8_t *iaid, const char *arg, size_t len, int n)
371 {
372         int e;
373         uint32_t narg;
374         ssize_t s;
375
376         narg = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
377         if (e == 0) {
378                 if (n)
379                         narg = htonl(narg);
380                 memcpy(iaid, &narg, sizeof(narg));
381                 return 0;
382         }
383
384         if ((s = parse_string((char *)iaid, len, arg)) < 1)
385                 return -1;
386         if (s < 4)
387                 iaid[3] = '\0';
388         if (s < 3)
389                 iaid[2] = '\0';
390         if (s < 2)
391                 iaid[1] = '\0';
392         return 0;
393 }
394
395 static int
396 parse_iaid(uint8_t *iaid, const char *arg, size_t len)
397 {
398
399         return parse_iaid1(iaid, arg, len, 1);
400 }
401
402 #ifdef AUTH
403 static int
404 parse_uint32(uint32_t *i, const char *arg)
405 {
406
407         return parse_iaid1((uint8_t *)i, arg, sizeof(uint32_t), 0);
408 }
409 #endif
410
411 static char **
412 splitv(int *argc, char **argv, const char *arg)
413 {
414         char **n, **v = argv;
415         char *o = strdup(arg), *p, *t, *nt;
416
417         if (o == NULL) {
418                 logerr(__func__);
419                 return v;
420         }
421         p = o;
422         while ((t = strsep(&p, ", "))) {
423                 nt = strdup(t);
424                 if (nt == NULL) {
425                         logerr(__func__);
426                         free(o);
427                         return v;
428                 }
429                 n = reallocarray(v, (size_t)(*argc) + 1, sizeof(char *));
430                 if (n == NULL) {
431                         logerr(__func__);
432                         free(o);
433                         free(nt);
434                         return v;
435                 }
436                 v = n;
437                 v[(*argc)++] = nt;
438         }
439         free(o);
440         return v;
441 }
442
443 #ifdef INET
444 static int
445 parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
446 {
447         char *p;
448
449         if (arg == NULL || *arg == '\0') {
450                 if (addr != NULL)
451                         addr->s_addr = 0;
452                 if (net != NULL)
453                         net->s_addr = 0;
454                 return 0;
455         }
456         if ((p = strchr(arg, '/')) != NULL) {
457                 int e;
458                 intmax_t i;
459
460                 *p++ = '\0';
461                 i = strtoi(p, NULL, 10, 0, 32, &e);
462                 if (e != 0 ||
463                     (net != NULL && inet_cidrtoaddr((int)i, net) != 0))
464                 {
465                         logerrx("invalid CIDR: %s", p);
466                         return -1;
467                 }
468         }
469
470         if (addr != NULL && inet_aton(arg, addr) == 0) {
471                 logerrx("invalid IP address: %s", arg);
472                 return -1;
473         }
474         if (p != NULL)
475                 *--p = '/';
476         else if (net != NULL && addr != NULL)
477                 net->s_addr = ipv4_getnetmask(addr->s_addr);
478         return 0;
479 }
480 #else
481 static int
482 parse_addr(__unused struct in_addr *addr, __unused struct in_addr *net,
483     __unused const char *arg)
484 {
485
486         logerrx("No IPv4 support");
487         return -1;
488 }
489 #endif
490
491 static void
492 set_option_space(struct dhcpcd_ctx *ctx,
493     const char *arg,
494     const struct dhcp_opt **d, size_t *dl,
495     const struct dhcp_opt **od, size_t *odl,
496     struct if_options *ifo,
497     uint8_t *request[], uint8_t *require[], uint8_t *no[], uint8_t *reject[])
498 {
499
500 #if !defined(INET) && !defined(INET6)
501         UNUSED(ctx);
502 #endif
503
504 #ifdef INET6
505         if (strncmp(arg, "nd_", strlen("nd_")) == 0) {
506                 *d = ctx->nd_opts;
507                 *dl = ctx->nd_opts_len;
508                 *od = ifo->nd_override;
509                 *odl = ifo->nd_override_len;
510                 *request = ifo->requestmasknd;
511                 *require = ifo->requiremasknd;
512                 *no = ifo->nomasknd;
513                 *reject = ifo->rejectmasknd;
514                 return;
515         }
516
517 #ifdef DHCP6
518         if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) {
519                 *d = ctx->dhcp6_opts;
520                 *dl = ctx->dhcp6_opts_len;
521                 *od = ifo->dhcp6_override;
522                 *odl = ifo->dhcp6_override_len;
523                 *request = ifo->requestmask6;
524                 *require = ifo->requiremask6;
525                 *no = ifo->nomask6;
526                 *reject = ifo->rejectmask6;
527                 return;
528         }
529 #endif
530 #else
531         UNUSED(arg);
532 #endif
533
534 #ifdef INET
535         *d = ctx->dhcp_opts;
536         *dl = ctx->dhcp_opts_len;
537         *od = ifo->dhcp_override;
538         *odl = ifo->dhcp_override_len;
539 #else
540         *d = NULL;
541         *dl = 0;
542         *od = NULL;
543         *odl = 0;
544 #endif
545         *request = ifo->requestmask;
546         *require = ifo->requiremask;
547         *no = ifo->nomask;
548         *reject = ifo->rejectmask;
549 }
550
551 void
552 free_dhcp_opt_embenc(struct dhcp_opt *opt)
553 {
554         size_t i;
555         struct dhcp_opt *o;
556
557         free(opt->var);
558
559         for (i = 0, o = opt->embopts; i < opt->embopts_len; i++, o++)
560                 free_dhcp_opt_embenc(o);
561         free(opt->embopts);
562         opt->embopts_len = 0;
563         opt->embopts = NULL;
564
565         for (i = 0, o = opt->encopts; i < opt->encopts_len; i++, o++)
566                 free_dhcp_opt_embenc(o);
567         free(opt->encopts);
568         opt->encopts_len = 0;
569         opt->encopts = NULL;
570 }
571
572 static char *
573 strwhite(const char *s)
574 {
575
576         if (s == NULL)
577                 return NULL;
578         while (*s != ' ' && *s != '\t') {
579                 if (*s == '\0')
580                         return NULL;
581                 s++;
582         }
583         return UNCONST(s);
584 }
585
586 static char *
587 strskipwhite(const char *s)
588 {
589
590         if (s == NULL || *s == '\0')
591                 return NULL;
592         while (*s == ' ' || *s == '\t') {
593                 s++;
594                 if (*s == '\0')
595                         return NULL;
596         }
597         return UNCONST(s);
598 }
599
600 #ifdef AUTH
601 /* Find the end pointer of a string. */
602 static char *
603 strend(const char *s)
604 {
605
606         s = strskipwhite(s);
607         if (s == NULL)
608                 return NULL;
609         if (*s != '"')
610                 return strchr(s, ' ');
611         s++;
612         for (; *s != '"' ; s++) {
613                 if (*s == '\0')
614                         return NULL;
615                 if (*s == '\\') {
616                         if (*(++s) == '\0')
617                                 return NULL;
618                 }
619         }
620         return UNCONST(++s);
621 }
622 #endif
623
624 static int
625 parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
626     int opt, const char *arg, struct dhcp_opt **ldop, struct dhcp_opt **edop)
627 {
628         int e, i, t;
629         long l;
630         unsigned long u;
631         char *p = NULL, *bp, *fp, *np;
632         ssize_t s;
633         struct in_addr addr, addr2;
634         in_addr_t *naddr;
635         struct rt *rt;
636         const struct dhcp_opt *d, *od;
637         uint8_t *request, *require, *no, *reject;
638         struct dhcp_opt **dop, *ndop;
639         size_t *dop_len, dl, odl;
640         struct vivco *vivco;
641         struct group *grp;
642 #ifdef AUTH
643         struct token *token;
644 #endif
645 #ifdef _REENTRANT
646         struct group grpbuf;
647 #endif
648 #ifdef DHCP6
649         size_t sl;
650         struct if_ia *ia;
651         uint8_t iaid[4];
652 #ifndef SMALL
653         struct if_sla *sla, *slap;
654 #endif
655 #endif
656
657         dop = NULL;
658         dop_len = NULL;
659 #ifdef INET6
660         i = 0;
661 #endif
662
663 /* Add a guard for static analysers.
664  * This should not be needed really because of the argument_required option
665  * in the options declaration above. */
666 #define ARG_REQUIRED if (arg == NULL) goto arg_required
667
668         switch(opt) {
669         case 'f': /* FALLTHROUGH */
670         case 'g': /* FALLTHROUGH */
671         case 'n': /* FALLTHROUGH */
672         case 'q': /* FALLTHROUGH */
673         case 'x': /* FALLTHROUGH */
674         case 'N': /* FALLTHROUGH */
675         case 'P': /* FALLTHROUGH */
676         case 'T': /* FALLTHROUGH */
677         case 'U': /* FALLTHROUGH */
678         case 'V': /* We need to handle non interface options */
679                 break;
680         case 'b':
681                 ifo->options |= DHCPCD_BACKGROUND;
682                 break;
683         case 'c':
684                 ARG_REQUIRED;
685                 if (IN_CONFIG_BLOCK(ifo)) {
686                         logerrx("%s: per interface scripts"
687                             " are no longer supported",
688                             ifname);
689                         return -1;
690                 }
691                 if (ctx->script != dhcpcd_default_script)
692                         free(ctx->script);
693                 s = parse_nstring(NULL, 0, arg);
694                 if (s == 0) {
695                         ctx->script = NULL;
696                         break;
697                 }
698                 dl = (size_t)s;
699                 if (s == -1 || (ctx->script = malloc(dl)) == NULL) {
700                         ctx->script = NULL;
701                         logerr(__func__);
702                         return -1;
703                 }
704                 s = parse_nstring(ctx->script, dl, arg);
705                 if (s == -1 ||
706                     ctx->script[0] == '\0' ||
707                     strcmp(ctx->script, "/dev/null") == 0)
708                 {
709                         free(ctx->script);
710                         ctx->script = NULL;
711                 }
712                 break;
713         case 'd':
714                 ifo->options |= DHCPCD_DEBUG;
715                 break;
716         case 'e':
717                 ARG_REQUIRED;
718                 add_environ(&ifo->environ, arg, 1);
719                 break;
720         case 'h':
721                 if (!arg) {
722                         ifo->options |= DHCPCD_HOSTNAME;
723                         break;
724                 }
725                 s = parse_nstring(ifo->hostname, sizeof(ifo->hostname), arg);
726                 if (s == -1) {
727                         logerr("%s: hostname", __func__);
728                         return -1;
729                 }
730                 if (s != 0 && ifo->hostname[0] == '.') {
731                         logerrx("hostname cannot begin with .");
732                         return -1;
733                 }
734                 if (ifo->hostname[0] == '\0')
735                         ifo->options &= ~DHCPCD_HOSTNAME;
736                 else
737                         ifo->options |= DHCPCD_HOSTNAME;
738                 break;
739         case 'i':
740                 if (arg)
741                         s = parse_string((char *)ifo->vendorclassid + 1,
742                             VENDORCLASSID_MAX_LEN, arg);
743                 else
744                         s = 0;
745                 if (s == -1) {
746                         logerr("vendorclassid");
747                         return -1;
748                 }
749                 *ifo->vendorclassid = (uint8_t)s;
750                 break;
751         case 'j':
752                 ARG_REQUIRED;
753                 /* per interface logging is not supported
754                  * don't want to overide the commandline */
755                 if (!IN_CONFIG_BLOCK(ifo) && ctx->logfile == NULL) {
756                         logclose();
757                         ctx->logfile = strdup(arg);
758                         logopen(ctx->logfile);
759                 }
760                 break;
761         case 'k':
762                 ifo->options |= DHCPCD_RELEASE;
763                 break;
764         case 'l':
765                 ARG_REQUIRED;
766                 if (strcmp(arg, "-1") == 0) {
767                         ifo->leasetime = DHCP_INFINITE_LIFETIME;
768                         break;
769                 }
770                 ifo->leasetime = (uint32_t)strtou(arg, NULL,
771                     0, 0, UINT32_MAX, &e);
772                 if (e) {
773                         logerrx("failed to convert leasetime %s", arg);
774                         return -1;
775                 }
776                 break;
777         case 'm':
778                 ARG_REQUIRED;
779                 ifo->metric = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
780                 if (e) {
781                         logerrx("failed to convert metric %s", arg);
782                         return -1;
783                 }
784                 break;
785         case 'o':
786                 ARG_REQUIRED;
787                 if (ctx->options & DHCPCD_PRINT_PIDFILE)
788                         break;
789                 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
790                     &request, &require, &no, &reject);
791                 if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
792                     make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
793                     make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
794                 {
795                         logerrx("unknown option: %s", arg);
796                         return -1;
797                 }
798                 break;
799         case O_REJECT:
800                 ARG_REQUIRED;
801                 if (ctx->options & DHCPCD_PRINT_PIDFILE)
802                         break;
803                 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
804                     &request, &require, &no, &reject);
805                 if (make_option_mask(d, dl, od, odl, reject, arg, 1) != 0 ||
806                     make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
807                     make_option_mask(d, dl, od, odl, require, arg, -1) != 0)
808                 {
809                         logerrx("unknown option: %s", arg);
810                         return -1;
811                 }
812                 break;
813         case 'p':
814                 ifo->options |= DHCPCD_PERSISTENT;
815                 break;
816         case 'r':
817                 if (parse_addr(&ifo->req_addr, NULL, arg) != 0)
818                         return -1;
819                 ifo->options |= DHCPCD_REQUEST;
820                 ifo->req_mask.s_addr = 0;
821                 break;
822         case 's':
823                 if (arg && *arg != '\0') {
824                         /* Strip out a broadcast address */
825                         p = strchr(arg, '/');
826                         if (p != NULL) {
827                                 p = strchr(p + 1, '/');
828                                 if (p != NULL)
829                                         *p = '\0';
830                         }
831                         i = parse_addr(&ifo->req_addr, &ifo->req_mask, arg);
832                         if (p != NULL) {
833                                 /* Ensure the original string is preserved */
834                                 *p++ = '/';
835                                 if (i == 0)
836                                         i = parse_addr(&ifo->req_brd, NULL, p);
837                         }
838                         if (i != 0)
839                                 return -1;
840                 } else {
841                         ifo->req_addr.s_addr = 0;
842                         ifo->req_mask.s_addr = 0;
843                 }
844                 ifo->options |= DHCPCD_INFORM | DHCPCD_PERSISTENT;
845                 ifo->options &= ~DHCPCD_STATIC;
846                 break;
847         case O_INFORM6:
848                 ifo->options |= DHCPCD_INFORM6;
849                 break;
850         case 't':
851                 ARG_REQUIRED;
852                 ifo->timeout = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
853                 if (e) {
854                         logerrx("failed to convert timeout %s", arg);
855                         return -1;
856                 }
857                 break;
858         case 'u':
859                 dl = sizeof(ifo->userclass) - ifo->userclass[0] - 1;
860                 s = parse_string((char *)ifo->userclass +
861                     ifo->userclass[0] + 2, dl, arg);
862                 if (s == -1) {
863                         logerr("userclass");
864                         return -1;
865                 }
866                 if (s != 0) {
867                         ifo->userclass[ifo->userclass[0] + 1] = (uint8_t)s;
868                         ifo->userclass[0] = (uint8_t)(ifo->userclass[0] + s +1);
869                 }
870                 break;
871 #ifndef SMALL
872         case O_MSUSERCLASS:
873                 /* Some Microsoft DHCP servers expect userclass to be an
874                  * opaque blob. This is not RFC 3004 compliant. */
875                 s = parse_string((char *)ifo->userclass + 1,
876                     sizeof(ifo->userclass) - 1, arg);
877                 if (s == -1) {
878                         logerr("msuserclass");
879                         return -1;
880                 }
881                 ifo->userclass[0] = (uint8_t)s;
882                 break;
883 #endif
884         case 'v':
885                 ARG_REQUIRED;
886                 p = strchr(arg, ',');
887                 if (!p || !p[1]) {
888                         logerrx("invalid vendor format: %s", arg);
889                         return -1;
890                 }
891
892                 /* If vendor starts with , then it is not encapsulated */
893                 if (p == arg) {
894                         arg++;
895                         s = parse_string((char *)ifo->vendor + 1,
896                             VENDOR_MAX_LEN, arg);
897                         if (s == -1) {
898                                 logerr("vendor");
899                                 return -1;
900                         }
901                         ifo->vendor[0] = (uint8_t)s;
902                         ifo->options |= DHCPCD_VENDORRAW;
903                         break;
904                 }
905
906                 /* Encapsulated vendor options */
907                 if (ifo->options & DHCPCD_VENDORRAW) {
908                         ifo->options &= ~DHCPCD_VENDORRAW;
909                         ifo->vendor[0] = 0;
910                 }
911
912                 /* Strip and preserve the comma */
913                 *p = '\0';
914                 i = (int)strtoi(arg, NULL, 0, 1, 254, &e);
915                 *p = ',';
916                 if (e) {
917                         logerrx("vendor option should be between"
918                             " 1 and 254 inclusive");
919                         return -1;
920                 }
921
922                 arg = p + 1;
923                 s = VENDOR_MAX_LEN - ifo->vendor[0] - 2;
924                 if (inet_aton(arg, &addr) == 1) {
925                         if (s < 6) {
926                                 s = -1;
927                                 errno = ENOBUFS;
928                         } else {
929                                 memcpy(ifo->vendor + ifo->vendor[0] + 3,
930                                     &addr.s_addr, sizeof(addr.s_addr));
931                                 s = sizeof(addr.s_addr);
932                         }
933                 } else {
934                         s = parse_string((char *)ifo->vendor +
935                             ifo->vendor[0] + 3, (size_t)s, arg);
936                 }
937                 if (s == -1) {
938                         logerr("vendor");
939                         return -1;
940                 }
941                 if (s != 0) {
942                         ifo->vendor[ifo->vendor[0] + 1] = (uint8_t)i;
943                         ifo->vendor[ifo->vendor[0] + 2] = (uint8_t)s;
944                         ifo->vendor[0] = (uint8_t)(ifo->vendor[0] + s + 2);
945                 }
946                 break;
947         case 'w':
948                 ifo->options |= DHCPCD_WAITIP;
949                 if (arg != NULL && arg[0] != '\0') {
950                         if (arg[0] == '4' || arg[1] == '4')
951                                 ifo->options |= DHCPCD_WAITIP4;
952                         if (arg[0] == '6' || arg[1] == '6')
953                                 ifo->options |= DHCPCD_WAITIP6;
954                 }
955                 break;
956         case 'y':
957                 ARG_REQUIRED;
958                 ifo->reboot = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
959                 if (e) {
960                         logerr("failed to convert reboot %s", arg);
961                         return -1;
962                 }
963                 break;
964         case 'z':
965                 ARG_REQUIRED;
966                 if (!IN_CONFIG_BLOCK(ifo))
967                         ctx->ifav = splitv(&ctx->ifac, ctx->ifav, arg);
968                 break;
969         case 'A':
970                 ifo->options &= ~DHCPCD_ARP;
971                 /* IPv4LL requires ARP */
972                 ifo->options &= ~DHCPCD_IPV4LL;
973                 break;
974         case 'B':
975                 ifo->options &= ~DHCPCD_DAEMONISE;
976                 break;
977         case 'C':
978                 ARG_REQUIRED;
979                 /* Commas to spaces for shell */
980                 while ((p = strchr(arg, ',')))
981                         *p = ' ';
982                 dl = strlen("skip_hooks=") + strlen(arg) + 1;
983                 p = malloc(sizeof(char) * dl);
984                 if (p == NULL) {
985                         logerr(__func__);
986                         return -1;
987                 }
988                 snprintf(p, dl, "skip_hooks=%s", arg);
989                 add_environ(&ifo->environ, p, 0);
990                 free(p);
991                 break;
992         case 'D':
993                 ifo->options |= DHCPCD_CLIENTID | DHCPCD_DUID;
994                 if (ifname != NULL) /* duid type only a global option */
995                         break;
996                 if (arg == NULL)
997                         ctx->duid_type = DUID_DEFAULT;
998                 else if (strcmp(arg, "ll") == 0)
999                         ctx->duid_type = DUID_LL;
1000                 else if (strcmp(arg, "llt") == 0)
1001                         ctx->duid_type = DUID_LLT;
1002                 else if (strcmp(arg, "uuid") == 0)
1003                         ctx->duid_type = DUID_UUID;
1004                 else {
1005                         dl = hwaddr_aton(NULL, arg);
1006                         if (dl != 0) {
1007                                 no = realloc(ctx->duid, dl);
1008                                 if (no == NULL)
1009                                         logerrx(__func__);
1010                                 else {
1011                                         ctx->duid = no;
1012                                         ctx->duid_len = hwaddr_aton(no, arg);
1013                                 }
1014                         }
1015                 }
1016                 break;
1017         case 'E':
1018                 ifo->options |= DHCPCD_LASTLEASE;
1019                 break;
1020         case 'F':
1021                 if (!arg) {
1022                         ifo->fqdn = FQDN_BOTH;
1023                         break;
1024                 }
1025                 if (strcmp(arg, "none") == 0)
1026                         ifo->fqdn = FQDN_NONE;
1027                 else if (strcmp(arg, "ptr") == 0)
1028                         ifo->fqdn = FQDN_PTR;
1029                 else if (strcmp(arg, "both") == 0)
1030                         ifo->fqdn = FQDN_BOTH;
1031                 else if (strcmp(arg, "disable") == 0)
1032                         ifo->fqdn = FQDN_DISABLE;
1033                 else {
1034                         logerrx("invalid FQDN value: %s", arg);
1035                         return -1;
1036                 }
1037                 break;
1038         case 'G':
1039                 ifo->options &= ~DHCPCD_GATEWAY;
1040                 break;
1041         case 'H':
1042                 ifo->options |= DHCPCD_XID_HWADDR;
1043                 break;
1044         case 'I':
1045                 /* Strings have a type of 0 */;
1046                 ifo->clientid[1] = 0;
1047                 if (arg)
1048                         s = parse_hwaddr((char *)ifo->clientid + 1,
1049                             CLIENTID_MAX_LEN, arg);
1050                 else
1051                         s = 0;
1052                 if (s == -1) {
1053                         logerr("clientid");
1054                         return -1;
1055                 }
1056                 ifo->options |= DHCPCD_CLIENTID;
1057                 ifo->clientid[0] = (uint8_t)s;
1058                 ifo->options &= ~DHCPCD_DUID;
1059                 break;
1060         case 'J':
1061                 ifo->options |= DHCPCD_BROADCAST;
1062                 break;
1063         case 'K':
1064                 ifo->options &= ~DHCPCD_LINK;
1065                 break;
1066         case 'L':
1067                 ifo->options &= ~DHCPCD_IPV4LL;
1068                 break;
1069         case 'M':
1070                 ifo->options |= DHCPCD_MASTER;
1071                 break;
1072         case 'O':
1073                 ARG_REQUIRED;
1074                 if (ctx->options & DHCPCD_PRINT_PIDFILE)
1075                         break;
1076                 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
1077                     &request, &require, &no, &reject);
1078                 if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
1079                     make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
1080                     make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
1081                 {
1082                         logerrx("unknown option: %s", arg);
1083                         return -1;
1084                 }
1085                 break;
1086         case 'Q':
1087                 ARG_REQUIRED;
1088                 if (ctx->options & DHCPCD_PRINT_PIDFILE)
1089                         break;
1090                 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
1091                     &request, &require, &no, &reject);
1092                 if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 ||
1093                     make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
1094                     make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
1095                     make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
1096                 {
1097                         logerrx("unknown option: %s", arg);
1098                         return -1;
1099                 }
1100                 break;
1101         case 'S':
1102                 ARG_REQUIRED;
1103                 p = strchr(arg, '=');
1104                 if (p == NULL) {
1105                         logerrx("static assignment required");
1106                         return -1;
1107                 }
1108                 p++;
1109                 if (strncmp(arg, "ip_address=", strlen("ip_address=")) == 0) {
1110                         if (parse_addr(&ifo->req_addr,
1111                             ifo->req_mask.s_addr == 0 ? &ifo->req_mask : NULL,
1112                             p) != 0)
1113                                 return -1;
1114
1115                         ifo->options |= DHCPCD_STATIC;
1116                         ifo->options &= ~DHCPCD_INFORM;
1117                 } else if (strncmp(arg, "subnet_mask=",
1118                     strlen("subnet_mask=")) == 0)
1119                 {
1120                         if (parse_addr(&ifo->req_mask, NULL, p) != 0)
1121                                 return -1;
1122                 } else if (strncmp(arg, "broadcast_address=",
1123                     strlen("broadcast_address=")) == 0)
1124                 {
1125                         if (parse_addr(&ifo->req_brd, NULL, p) != 0)
1126                                 return -1;
1127                 } else if (strncmp(arg, "routes=", strlen("routes=")) == 0 ||
1128                     strncmp(arg, "static_routes=",
1129                         strlen("static_routes=")) == 0 ||
1130                     strncmp(arg, "classless_static_routes=",
1131                         strlen("classless_static_routes=")) == 0 ||
1132                     strncmp(arg, "ms_classless_static_routes=",
1133                         strlen("ms_classless_static_routes=")) == 0)
1134                 {
1135                         struct in_addr addr3;
1136
1137                         fp = np = strwhite(p);
1138                         if (np == NULL) {
1139                                 logerrx("all routes need a gateway");
1140                                 return -1;
1141                         }
1142                         *np++ = '\0';
1143                         np = strskipwhite(np);
1144                         if (parse_addr(&addr, &addr2, p) == -1 ||
1145                             parse_addr(&addr3, NULL, np) == -1)
1146                         {
1147                                 *fp = ' ';
1148                                 return -1;
1149                         }
1150                         *fp = ' ';
1151                         if ((rt = rt_new0(ctx)) == NULL)
1152                                 return -1;
1153                         sa_in_init(&rt->rt_dest, &addr);
1154                         sa_in_init(&rt->rt_netmask, &addr2);
1155                         sa_in_init(&rt->rt_gateway, &addr3);
1156                         if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
1157                                 add_environ(&ifo->config, arg, 0);
1158                 } else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
1159                         if (parse_addr(&addr, NULL, p) == -1)
1160                                 return -1;
1161                         if ((rt = rt_new0(ctx)) == NULL)
1162                                 return -1;
1163                         addr2.s_addr = INADDR_ANY;
1164                         sa_in_init(&rt->rt_dest, &addr2);
1165                         sa_in_init(&rt->rt_netmask, &addr2);
1166                         sa_in_init(&rt->rt_gateway, &addr);
1167                         if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
1168                                 add_environ(&ifo->config, arg, 0);
1169                 } else if (strncmp(arg, "interface_mtu=",
1170                     strlen("interface_mtu=")) == 0 ||
1171                     strncmp(arg, "mtu=", strlen("mtu=")) == 0)
1172                 {
1173                         ifo->mtu = (unsigned int)strtou(p, NULL, 0,
1174                             MTU_MIN, MTU_MAX, &e);
1175                         if (e) {
1176                                 logerrx("invalid MTU %s", p);
1177                                 return -1;
1178                         }
1179                 } else if (strncmp(arg, "ip6_address=", strlen("ip6_address=")) == 0) {
1180                         np = strchr(p, '/');
1181                         if (np)
1182                                 *np++ = '\0';
1183                         if ((i = inet_pton(AF_INET6, p, &ifo->req_addr6)) == 1) {
1184                                 if (np) {
1185                                         ifo->req_prefix_len = (uint8_t)strtou(np,
1186                                             NULL, 0, 0, 128, &e);
1187                                         if (e) {
1188                                                 logerrx("%s: failed to "
1189                                                     "convert prefix len",
1190                                                     ifname);
1191                                                 return -1;
1192                                         }
1193                                 } else
1194                                         ifo->req_prefix_len = 128;
1195                         }
1196                         if (np)
1197                                 *(--np) = '\0';
1198                         if (i != 1) {
1199                                 logerrx("invalid AF_INET6: %s", p);
1200                                 memset(&ifo->req_addr6, 0,
1201                                     sizeof(ifo->req_addr6));
1202                                 return -1;
1203                         }
1204                 } else
1205                         add_environ(&ifo->config, arg, 1);
1206                 break;
1207         case 'W':
1208                 if (parse_addr(&addr, &addr2, arg) != 0)
1209                         return -1;
1210                 if (strchr(arg, '/') == NULL)
1211                         addr2.s_addr = INADDR_BROADCAST;
1212                 naddr = reallocarray(ifo->whitelist,
1213                     ifo->whitelist_len + 2, sizeof(in_addr_t));
1214                 if (naddr == NULL) {
1215                         logerr(__func__);
1216                         return -1;
1217                 }
1218                 ifo->whitelist = naddr;
1219                 ifo->whitelist[ifo->whitelist_len++] = addr.s_addr;
1220                 ifo->whitelist[ifo->whitelist_len++] = addr2.s_addr;
1221                 break;
1222         case 'X':
1223                 if (parse_addr(&addr, &addr2, arg) != 0)
1224                         return -1;
1225                 if (strchr(arg, '/') == NULL)
1226                         addr2.s_addr = INADDR_BROADCAST;
1227                 naddr = reallocarray(ifo->blacklist,
1228                     ifo->blacklist_len + 2, sizeof(in_addr_t));
1229                 if (naddr == NULL) {
1230                         logerr(__func__);
1231                         return -1;
1232                 }
1233                 ifo->blacklist = naddr;
1234                 ifo->blacklist[ifo->blacklist_len++] = addr.s_addr;
1235                 ifo->blacklist[ifo->blacklist_len++] = addr2.s_addr;
1236                 break;
1237         case 'Z':
1238                 ARG_REQUIRED;
1239                 if (!IN_CONFIG_BLOCK(ifo))
1240                         ctx->ifdv = splitv(&ctx->ifdc, ctx->ifdv, arg);
1241                 break;
1242         case '1':
1243                 ifo->options |= DHCPCD_ONESHOT;
1244                 break;
1245         case '4':
1246 #ifdef INET
1247                 ifo->options &= ~DHCPCD_IPV6;
1248                 ifo->options |= DHCPCD_IPV4;
1249                 break;
1250 #else
1251                 logerrx("INET has been compiled out");
1252                 return -1;
1253 #endif
1254         case '6':
1255 #ifdef INET6
1256                 ifo->options &= ~DHCPCD_IPV4;
1257                 ifo->options |= DHCPCD_IPV6;
1258                 break;
1259 #else
1260                 logerrx("INET6 has been compiled out");
1261                 return -1;
1262 #endif
1263         case O_IPV4:
1264                 ifo->options |= DHCPCD_IPV4;
1265                 break;
1266         case O_NOIPV4:
1267                 ifo->options &= ~DHCPCD_IPV4;
1268                 break;
1269         case O_IPV6:
1270                 ifo->options |= DHCPCD_IPV6;
1271                 break;
1272         case O_NOIPV6:
1273                 ifo->options &= ~DHCPCD_IPV6;
1274                 break;
1275         case O_ANONYMOUS:
1276                 ifo->options |= DHCPCD_ANONYMOUS;
1277                 ifo->options &= ~DHCPCD_HOSTNAME;
1278                 ifo->fqdn = FQDN_DISABLE;
1279
1280                 /* Block everything */
1281                 memset(ifo->nomask, 0xff, sizeof(ifo->nomask));
1282                 memset(ifo->nomask6, 0xff, sizeof(ifo->nomask6));
1283
1284                 /* Allow the bare minimum through */
1285 #ifdef INET
1286                 del_option_mask(ifo->nomask, DHO_SUBNETMASK);
1287                 del_option_mask(ifo->nomask, DHO_CSR);
1288                 del_option_mask(ifo->nomask, DHO_ROUTER);
1289                 del_option_mask(ifo->nomask, DHO_DNSSERVER);
1290                 del_option_mask(ifo->nomask, DHO_DNSDOMAIN);
1291                 del_option_mask(ifo->nomask, DHO_BROADCAST);
1292                 del_option_mask(ifo->nomask, DHO_STATICROUTE);
1293                 del_option_mask(ifo->nomask, DHO_SERVERID);
1294                 del_option_mask(ifo->nomask, DHO_RENEWALTIME);
1295                 del_option_mask(ifo->nomask, DHO_REBINDTIME);
1296                 del_option_mask(ifo->nomask, DHO_DNSSEARCH);
1297 #endif
1298
1299 #ifdef DHCP6
1300                 del_option_mask(ifo->nomask6, D6_OPTION_DNS_SERVERS);
1301                 del_option_mask(ifo->nomask6, D6_OPTION_DOMAIN_LIST);
1302                 del_option_mask(ifo->nomask6, D6_OPTION_SOL_MAX_RT);
1303                 del_option_mask(ifo->nomask6, D6_OPTION_INF_MAX_RT);
1304 #endif
1305
1306                 break;
1307 #ifdef INET
1308         case O_ARPING:
1309                 while (arg != NULL) {
1310                         fp = strwhite(arg);
1311                         if (fp)
1312                                 *fp++ = '\0';
1313                         if (parse_addr(&addr, NULL, arg) != 0)
1314                                 return -1;
1315                         naddr = reallocarray(ifo->arping,
1316                             (size_t)ifo->arping_len + 1, sizeof(in_addr_t));
1317                         if (naddr == NULL) {
1318                                 logerr(__func__);
1319                                 return -1;
1320                         }
1321                         ifo->arping = naddr;
1322                         ifo->arping[ifo->arping_len++] = addr.s_addr;
1323                         arg = strskipwhite(fp);
1324                 }
1325                 break;
1326         case O_DESTINATION:
1327                 ARG_REQUIRED;
1328                 if (ctx->options & DHCPCD_PRINT_PIDFILE)
1329                         break;
1330                 set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
1331                     &request, &require, &no, &reject);
1332                 if (make_option_mask(d, dl, od, odl,
1333                     ifo->dstmask, arg, 2) != 0)
1334                 {
1335                         if (errno == EINVAL)
1336                                 logerrx("option does not take"
1337                                     " an IPv4 address: %s", arg);
1338                         else
1339                                 logerrx("unknown option: %s", arg);
1340                         return -1;
1341                 }
1342                 break;
1343         case O_FALLBACK:
1344                 ARG_REQUIRED;
1345                 free(ifo->fallback);
1346                 ifo->fallback = strdup(arg);
1347                 if (ifo->fallback == NULL) {
1348                         logerrx(__func__);
1349                         return -1;
1350                 }
1351                 break;
1352 #endif
1353         case O_IAID:
1354                 ARG_REQUIRED;
1355                 if (ctx->options & DHCPCD_MASTER && !IN_CONFIG_BLOCK(ifo)) {
1356                         logerrx("IAID must belong in an interface block");
1357                         return -1;
1358                 }
1359                 if (parse_iaid(ifo->iaid, arg, sizeof(ifo->iaid)) == -1) {
1360                         logerrx("invalid IAID %s", arg);
1361                         return -1;
1362                 }
1363                 ifo->options |= DHCPCD_IAID;
1364                 break;
1365         case O_IPV6RS:
1366                 ifo->options |= DHCPCD_IPV6RS;
1367                 break;
1368         case O_NOIPV6RS:
1369                 ifo->options &= ~DHCPCD_IPV6RS;
1370                 break;
1371         case O_IPV6RA_FORK:
1372                 ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS;
1373                 break;
1374         case O_IPV6RA_AUTOCONF:
1375                 ifo->options |= DHCPCD_IPV6RA_AUTOCONF;
1376                 break;
1377         case O_IPV6RA_NOAUTOCONF:
1378                 ifo->options &= ~DHCPCD_IPV6RA_AUTOCONF;
1379                 break;
1380         case O_NOALIAS:
1381                 ifo->options |= DHCPCD_NOALIAS;
1382                 break;
1383 #ifdef DHCP6
1384         case O_IA_NA:
1385                 i = D6_OPTION_IA_NA;
1386                 /* FALLTHROUGH */
1387         case O_IA_TA:
1388                 if (i == 0)
1389                         i = D6_OPTION_IA_TA;
1390                 /* FALLTHROUGH */
1391         case O_IA_PD:
1392                 if (i == 0) {
1393 #ifdef SMALL
1394                         logwarnx("%s: IA_PD not compiled in", ifname);
1395                         return -1;
1396 #else
1397                         if (ctx->options & DHCPCD_MASTER &&
1398                             !IN_CONFIG_BLOCK(ifo))
1399                         {
1400                                 logerrx("IA PD must belong in an "
1401                                     "interface block");
1402                                 return -1;
1403                         }
1404                         i = D6_OPTION_IA_PD;
1405 #endif
1406                 }
1407                 if (ctx->options & DHCPCD_MASTER &&
1408                     !IN_CONFIG_BLOCK(ifo) && arg)
1409                 {
1410                         logerrx("IA with IAID must belong in an "
1411                             "interface block");
1412                         return -1;
1413                 }
1414                 ifo->options |= DHCPCD_IA_FORCED;
1415                 fp = strwhite(arg);
1416                 if (fp) {
1417                         *fp++ = '\0';
1418                         fp = strskipwhite(fp);
1419                 }
1420                 if (arg) {
1421                         p = strchr(arg, '/');
1422                         if (p)
1423                                 *p++ = '\0';
1424                         if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) {
1425                                 logerr("invalid IAID: %s", arg);
1426                                 return -1;
1427                         }
1428                 }
1429                 ia = NULL;
1430                 for (sl = 0; sl < ifo->ia_len; sl++) {
1431                         if ((arg == NULL && !ifo->ia[sl].iaid_set) ||
1432                             (arg != NULL && ifo->ia[sl].iaid_set &&
1433                             ifo->ia[sl].ia_type == (uint16_t)i &&
1434                             ifo->ia[sl].iaid[0] == iaid[0] &&
1435                             ifo->ia[sl].iaid[1] == iaid[1] &&
1436                             ifo->ia[sl].iaid[2] == iaid[2] &&
1437                             ifo->ia[sl].iaid[3] == iaid[3]))
1438                         {
1439                                 ia = &ifo->ia[sl];
1440                                 break;
1441                         }
1442                 }
1443                 if (ia == NULL) {
1444                         ia = reallocarray(ifo->ia,
1445                             ifo->ia_len + 1, sizeof(*ifo->ia));
1446                         if (ia == NULL) {
1447                                 logerr(__func__);
1448                                 return -1;
1449                         }
1450                         ifo->ia = ia;
1451                         ia = &ifo->ia[ifo->ia_len++];
1452                         ia->ia_type = (uint16_t)i;
1453                         if (arg) {
1454                                 ia->iaid[0] = iaid[0];
1455                                 ia->iaid[1] = iaid[1];
1456                                 ia->iaid[2] = iaid[2];
1457                                 ia->iaid[3] = iaid[3];
1458                                 ia->iaid_set = 1;
1459                         } else
1460                                 ia->iaid_set = 0;
1461                         if (!ia->iaid_set ||
1462                             p == NULL ||
1463                             ia->ia_type == D6_OPTION_IA_TA)
1464                         {
1465                                 memset(&ia->addr, 0, sizeof(ia->addr));
1466                                 ia->prefix_len = 0;
1467                         } else {
1468                                 arg = p;
1469                                 p = strchr(arg, '/');
1470                                 if (p)
1471                                         *p++ = '\0';
1472                                 if (inet_pton(AF_INET6, arg, &ia->addr) != 1) {
1473                                         logerrx("invalid AF_INET6: %s", arg);
1474                                         memset(&ia->addr, 0, sizeof(ia->addr));
1475                                 }
1476                                 if (p && ia->ia_type == D6_OPTION_IA_PD) {
1477                                         ia->prefix_len = (uint8_t)strtou(p,
1478                                             NULL, 0, 8, 120, &e);
1479                                         if (e) {
1480                                                 logerrx("%s: failed to convert"
1481                                                     " prefix len",
1482                                                     p);
1483                                                 ia->prefix_len = 0;
1484                                         }
1485                                 }
1486                         }
1487 #ifndef SMALL
1488                         ia->sla_max = 0;
1489                         ia->sla_len = 0;
1490                         ia->sla = NULL;
1491 #endif
1492                 }
1493
1494 #ifdef SMALL
1495                 break;
1496 #else
1497                 if (ia->ia_type != D6_OPTION_IA_PD)
1498                         break;
1499
1500                 for (p = fp; p; p = fp) {
1501                         fp = strwhite(p);
1502                         if (fp) {
1503                                 *fp++ = '\0';
1504                                 fp = strskipwhite(fp);
1505                         }
1506                         sla = reallocarray(ia->sla,
1507                             ia->sla_len + 1, sizeof(*ia->sla));
1508                         if (sla == NULL) {
1509                                 logerr(__func__);
1510                                 return -1;
1511                         }
1512                         ia->sla = sla;
1513                         sla = &ia->sla[ia->sla_len++];
1514                         np = strchr(p, '/');
1515                         if (np)
1516                                 *np++ = '\0';
1517                         if (strlcpy(sla->ifname, p,
1518                             sizeof(sla->ifname)) >= sizeof(sla->ifname))
1519                         {
1520                                 logerrx("%s: interface name too long", arg);
1521                                 goto err_sla;
1522                         }
1523                         sla->sla_set = false;
1524                         sla->prefix_len = 0;
1525                         sla->suffix = 1;
1526                         p = np;
1527                         if (p) {
1528                                 np = strchr(p, '/');
1529                                 if (np)
1530                                         *np++ = '\0';
1531                                 if (*p != '\0') {
1532                                         sla->sla = (uint32_t)strtou(p, NULL,
1533                                             0, 0, UINT32_MAX, &e);
1534                                         sla->sla_set = true;
1535                                         if (e) {
1536                                                 logerrx("%s: failed to convert "
1537                                                     "sla",
1538                                                     ifname);
1539                                                 goto err_sla;
1540                                         }
1541                                 }
1542                                 p = np;
1543                         }
1544                         if (p) {
1545                                 np = strchr(p, '/');
1546                                 if (np)
1547                                         *np++ = '\0';
1548                                 if (*p != '\0') {
1549                                         sla->prefix_len = (uint8_t)strtou(p,
1550                                     NULL, 0, 0, 120, &e);
1551                                         if (e) {
1552                                                 logerrx("%s: failed to "
1553                                                     "convert prefix len",
1554                                                     ifname);
1555                                                 goto err_sla;
1556                                         }
1557                                 }
1558                                 p = np;
1559                         }
1560                         if (p) {
1561                                 np = strchr(p, '/');
1562                                 if (np)
1563                                         *np = '\0';
1564                                 if (*p != '\0') {
1565                                         sla->suffix = (uint64_t)strtou(p, NULL,
1566                                             0, 0, UINT64_MAX, &e);
1567                                         if (e) {
1568                                                 logerrx("%s: failed to "
1569                                                     "convert suffix",
1570                                                     ifname);
1571                                                 goto err_sla;
1572                                         }
1573                                 }
1574                         }
1575                         /* Sanity check */
1576                         for (sl = 0; sl < ia->sla_len - 1; sl++) {
1577                                 slap = &ia->sla[sl];
1578                                 if (slap->sla_set != sla->sla_set) {
1579                                         logerrx("%s: cannot mix automatic "
1580                                             "and fixed SLA",
1581                                             sla->ifname);
1582                                         goto err_sla;
1583                                 }
1584                                 if (ia->prefix_len &&
1585                                     (sla->prefix_len == ia->prefix_len ||
1586                                     slap->prefix_len == ia->prefix_len))
1587                                 {
1588                                         logerrx("%s: cannot delegte the same"
1589                                             "prefix length more than once",
1590                                             sla->ifname);
1591                                         goto err_sla;
1592                                 }
1593                                 if (!sla->sla_set &&
1594                                     strcmp(slap->ifname, sla->ifname) == 0)
1595                                 {
1596                                         logwarnx("%s: cannot specify the "
1597                                             "same interface twice with "
1598                                             "an automatic SLA",
1599                                             sla->ifname);
1600                                         goto err_sla;
1601                                 }
1602                                 if (slap->sla_set && sla->sla_set &&
1603                                     slap->sla == sla->sla)
1604                                 {
1605                                         logerrx("%s: cannot"
1606                                             " assign the same SLA %u"
1607                                             " more than once",
1608                                             sla->ifname, sla->sla);
1609                                         goto err_sla;
1610                                 }
1611                         }
1612                         if (sla->sla_set && sla->sla > ia->sla_max)
1613                                 ia->sla_max = sla->sla;
1614                 }
1615                 break;
1616 err_sla:
1617                 ia->sla_len--;
1618                 return -1;
1619 #endif
1620 #endif
1621         case O_HOSTNAME_SHORT:
1622                 ifo->options |= DHCPCD_HOSTNAME | DHCPCD_HOSTNAME_SHORT;
1623                 break;
1624         case O_DEV:
1625                 ARG_REQUIRED;
1626 #ifdef PLUGIN_DEV
1627                 if (ctx->dev_load)
1628                         free(ctx->dev_load);
1629                 ctx->dev_load = strdup(arg);
1630 #endif
1631                 break;
1632         case O_NODEV:
1633                 ifo->options &= ~DHCPCD_DEV;
1634                 break;
1635         case O_DEFINE:
1636                 dop = &ifo->dhcp_override;
1637                 dop_len = &ifo->dhcp_override_len;
1638                 /* FALLTHROUGH */
1639         case O_DEFINEND:
1640                 if (dop == NULL) {
1641                         dop = &ifo->nd_override;
1642                         dop_len = &ifo->nd_override_len;
1643                 }
1644                 /* FALLTHROUGH */
1645         case O_DEFINE6:
1646                 if (dop == NULL) {
1647                         dop = &ifo->dhcp6_override;
1648                         dop_len = &ifo->dhcp6_override_len;
1649                 }
1650                 /* FALLTHROUGH */
1651         case O_VENDOPT:
1652                 if (dop == NULL) {
1653                         dop = &ifo->vivso_override;
1654                         dop_len = &ifo->vivso_override_len;
1655                 }
1656                 *edop = *ldop = NULL;
1657                 /* FALLTHROUGH */
1658         case O_EMBED:
1659                 if (dop == NULL) {
1660                         if (*edop) {
1661                                 dop = &(*edop)->embopts;
1662                                 dop_len = &(*edop)->embopts_len;
1663                         } else if (ldop) {
1664                                 dop = &(*ldop)->embopts;
1665                                 dop_len = &(*ldop)->embopts_len;
1666                         } else {
1667                                 logerrx("embed must be after a define "
1668                                     "or encap");
1669                                 return -1;
1670                         }
1671                 }
1672                 /* FALLTHROUGH */
1673         case O_ENCAP:
1674                 ARG_REQUIRED;
1675                 if (dop == NULL) {
1676                         if (*ldop == NULL) {
1677                                 logerrx("encap must be after a define");
1678                                 return -1;
1679                         }
1680                         dop = &(*ldop)->encopts;
1681                         dop_len = &(*ldop)->encopts_len;
1682                 }
1683
1684                 /* Shared code for define, define6, embed and encap */
1685
1686                 /* code */
1687                 if (opt == O_EMBED) /* Embedded options don't have codes */
1688                         u = 0;
1689                 else {
1690                         fp = strwhite(arg);
1691                         if (fp == NULL) {
1692                                 logerrx("invalid syntax: %s", arg);
1693                                 return -1;
1694                         }
1695                         *fp++ = '\0';
1696                         u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
1697                         if (e) {
1698                                 logerrx("invalid code: %s", arg);
1699                                 return -1;
1700                         }
1701                         arg = strskipwhite(fp);
1702                         if (arg == NULL) {
1703                                 logerrx("invalid syntax");
1704                                 return -1;
1705                         }
1706                 }
1707                 /* type */
1708                 fp = strwhite(arg);
1709                 if (fp)
1710                         *fp++ = '\0';
1711                 np = strchr(arg, ':');
1712                 /* length */
1713                 if (np) {
1714                         *np++ = '\0';
1715                         bp = NULL; /* No bitflag */
1716                         l = (long)strtou(np, NULL, 0, 0, LONG_MAX, &e);
1717                         if (e) {
1718                                 logerrx("failed to convert length");
1719                                 return -1;
1720                         }
1721                 } else {
1722                         l = 0;
1723                         bp = strchr(arg, '='); /* bitflag assignment */
1724                         if (bp)
1725                                 *bp++ = '\0';
1726                 }
1727                 t = 0;
1728                 if (strcasecmp(arg, "request") == 0) {
1729                         t |= OT_REQUEST;
1730                         arg = strskipwhite(fp);
1731                         fp = strwhite(arg);
1732                         if (fp == NULL) {
1733                                 logerrx("incomplete request type");
1734                                 return -1;
1735                         }
1736                         *fp++ = '\0';
1737                 } else if (strcasecmp(arg, "norequest") == 0) {
1738                         t |= OT_NOREQ;
1739                         arg = strskipwhite(fp);
1740                         fp = strwhite(arg);
1741                         if (fp == NULL) {
1742                                 logerrx("incomplete request type");
1743                                 return -1;
1744                         }
1745                         *fp++ = '\0';
1746                 }
1747                 if (strcasecmp(arg, "optional") == 0) {
1748                         t |= OT_OPTIONAL;
1749                         arg = strskipwhite(fp);
1750                         fp = strwhite(arg);
1751                         if (fp == NULL) {
1752                                 logerrx("incomplete optional type");
1753                                 return -1;
1754                         }
1755                         *fp++ = '\0';
1756                 }
1757                 if (strcasecmp(arg, "index") == 0) {
1758                         t |= OT_INDEX;
1759                         arg = strskipwhite(fp);
1760                         fp = strwhite(arg);
1761                         if (fp == NULL) {
1762                                 logerrx("incomplete index type");
1763                                 return -1;
1764                         }
1765                         *fp++ = '\0';
1766                 }
1767                 if (strcasecmp(arg, "array") == 0) {
1768                         t |= OT_ARRAY;
1769                         arg = strskipwhite(fp);
1770                         fp = strwhite(arg);
1771                         if (fp == NULL) {
1772                                 logerrx("incomplete array type");
1773                                 return -1;
1774                         }
1775                         *fp++ = '\0';
1776                 }
1777                 if (strcasecmp(arg, "ipaddress") == 0)
1778                         t |= OT_ADDRIPV4;
1779                 else if (strcasecmp(arg, "ip6address") == 0)
1780                         t |= OT_ADDRIPV6;
1781                 else if (strcasecmp(arg, "string") == 0)
1782                         t |= OT_STRING;
1783                 else if (strcasecmp(arg, "byte") == 0)
1784                         t |= OT_UINT8;
1785                 else if (strcasecmp(arg, "bitflags") == 0)
1786                         t |= OT_BITFLAG;
1787                 else if (strcasecmp(arg, "uint8") == 0)
1788                         t |= OT_UINT8;
1789                 else if (strcasecmp(arg, "int8") == 0)
1790                         t |= OT_INT8;
1791                 else if (strcasecmp(arg, "uint16") == 0)
1792                         t |= OT_UINT16;
1793                 else if (strcasecmp(arg, "int16") == 0)
1794                         t |= OT_INT16;
1795                 else if (strcasecmp(arg, "uint32") == 0)
1796                         t |= OT_UINT32;
1797                 else if (strcasecmp(arg, "int32") == 0)
1798                         t |= OT_INT32;
1799                 else if (strcasecmp(arg, "flag") == 0)
1800                         t |= OT_FLAG;
1801                 else if (strcasecmp(arg, "raw") == 0)
1802                         t |= OT_STRING | OT_RAW;
1803                 else if (strcasecmp(arg, "ascii") == 0)
1804                         t |= OT_STRING | OT_ASCII;
1805                 else if (strcasecmp(arg, "domain") == 0)
1806                         t |= OT_STRING | OT_DOMAIN | OT_RFC1035;
1807                 else if (strcasecmp(arg, "dname") == 0)
1808                         t |= OT_STRING | OT_DOMAIN;
1809                 else if (strcasecmp(arg, "binhex") == 0)
1810                         t |= OT_STRING | OT_BINHEX;
1811                 else if (strcasecmp(arg, "embed") == 0)
1812                         t |= OT_EMBED;
1813                 else if (strcasecmp(arg, "encap") == 0)
1814                         t |= OT_ENCAP;
1815                 else if (strcasecmp(arg, "rfc3361") ==0)
1816                         t |= OT_STRING | OT_RFC3361;
1817                 else if (strcasecmp(arg, "rfc3442") ==0)
1818                         t |= OT_STRING | OT_RFC3442;
1819                 else if (strcasecmp(arg, "option") == 0)
1820                         t |= OT_OPTION;
1821                 else {
1822                         logerrx("unknown type: %s", arg);
1823                         return -1;
1824                 }
1825                 if (l && !(t & (OT_STRING | OT_BINHEX))) {
1826                         logwarnx("ignoring length for type: %s", arg);
1827                         l = 0;
1828                 }
1829                 if (t & OT_ARRAY && t & (OT_STRING | OT_BINHEX) &&
1830                     !(t & (OT_RFC1035 | OT_DOMAIN)))
1831                 {
1832                         logwarnx("ignoring array for strings");
1833                         t &= ~OT_ARRAY;
1834                 }
1835                 if (t & OT_BITFLAG) {
1836                         if (bp == NULL)
1837                                 logwarnx("missing bitflag assignment");
1838                 }
1839                 /* variable */
1840                 if (!fp) {
1841                         if (!(t & OT_OPTION)) {
1842                                 logerrx("type %s requires a variable name",
1843                                     arg);
1844                                 return -1;
1845                         }
1846                         np = NULL;
1847                 } else {
1848                         arg = strskipwhite(fp);
1849                         fp = strwhite(arg);
1850                         if (fp)
1851                                 *fp++ = '\0';
1852                         if (strcasecmp(arg, "reserved")) {
1853                                 np = strdup(arg);
1854                                 if (np == NULL) {
1855                                         logerr(__func__);
1856                                         return -1;
1857                                 }
1858                         } else {
1859                                 np = NULL;
1860                                 t |= OT_RESERVED;
1861                         }
1862                 }
1863                 if (opt != O_EMBED) {
1864                         for (dl = 0, ndop = *dop; dl < *dop_len; dl++, ndop++)
1865                         {
1866                                 /* type 0 seems freshly malloced struct
1867                                  * for us to use */
1868                                 if (ndop->option == u || ndop->type == 0)
1869                                         break;
1870                         }
1871                         if (dl == *dop_len)
1872                                 ndop = NULL;
1873                 } else
1874                         ndop = NULL;
1875                 if (ndop == NULL) {
1876                         ndop = reallocarray(*dop, *dop_len + 1, sizeof(**dop));
1877                         if (ndop == NULL) {
1878                                 logerr(__func__);
1879                                 free(np);
1880                                 return -1;
1881                         }
1882                         *dop = ndop;
1883                         ndop = &(*dop)[(*dop_len)++];
1884                         ndop->embopts = NULL;
1885                         ndop->embopts_len = 0;
1886                         ndop->encopts = NULL;
1887                         ndop->encopts_len = 0;
1888                 } else
1889                         free_dhcp_opt_embenc(ndop);
1890                 ndop->option = (uint32_t)u; /* could have been 0 */
1891                 ndop->type = t;
1892                 ndop->len = (size_t)l;
1893                 ndop->var = np;
1894                 if (bp) {
1895                         dl = strlen(bp);
1896                         memcpy(ndop->bitflags, bp, dl);
1897                         memset(ndop->bitflags + dl, 0,
1898                             sizeof(ndop->bitflags) - dl);
1899                 } else
1900                         memset(ndop->bitflags, 0, sizeof(ndop->bitflags));
1901                 /* Save the define for embed and encap options */
1902                 switch (opt) {
1903                 case O_DEFINE:
1904                 case O_DEFINEND:
1905                 case O_DEFINE6:
1906                 case O_VENDOPT:
1907                         *ldop = ndop;
1908                         break;
1909                 case O_ENCAP:
1910                         *edop = ndop;
1911                         break;
1912                 }
1913                 break;
1914         case O_VENDCLASS:
1915                 ARG_REQUIRED;
1916                 fp = strwhite(arg);
1917                 if (fp)
1918                         *fp++ = '\0';
1919                 u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
1920                 if (e) {
1921                         logerrx("invalid code: %s", arg);
1922                         return -1;
1923                 }
1924                 fp = strskipwhite(fp);
1925                 if (fp) {
1926                         s = parse_string(NULL, 0, fp);
1927                         if (s == -1) {
1928                                 logerr(__func__);
1929                                 return -1;
1930                         }
1931                         dl = (size_t)s;
1932                         if (dl + (sizeof(uint16_t) * 2) > UINT16_MAX) {
1933                                 logerrx("vendor class is too big");
1934                                 return -1;
1935                         }
1936                         np = malloc(dl);
1937                         if (np == NULL) {
1938                                 logerr(__func__);
1939                                 return -1;
1940                         }
1941                         parse_string(np, dl, fp);
1942                 } else {
1943                         dl = 0;
1944                         np = NULL;
1945                 }
1946                 vivco = reallocarray(ifo->vivco,
1947                     ifo->vivco_len + 1, sizeof(*ifo->vivco));
1948                 if (vivco == NULL) {
1949                         logerr( __func__);
1950                         free(np);
1951                         return -1;
1952                 }
1953                 ifo->vivco = vivco;
1954                 ifo->vivco_en = (uint32_t)u;
1955                 vivco = &ifo->vivco[ifo->vivco_len++];
1956                 vivco->len = dl;
1957                 vivco->data = (uint8_t *)np;
1958                 break;
1959         case O_AUTHPROTOCOL:
1960                 ARG_REQUIRED;
1961 #ifdef AUTH
1962                 fp = strwhite(arg);
1963                 if (fp)
1964                         *fp++ = '\0';
1965                 if (strcasecmp(arg, "token") == 0)
1966                         ifo->auth.protocol = AUTH_PROTO_TOKEN;
1967                 else if (strcasecmp(arg, "delayed") == 0)
1968                         ifo->auth.protocol = AUTH_PROTO_DELAYED;
1969                 else if (strcasecmp(arg, "delayedrealm") == 0)
1970                         ifo->auth.protocol = AUTH_PROTO_DELAYEDREALM;
1971                 else {
1972                         logerrx("%s: unsupported protocol", arg);
1973                         return -1;
1974                 }
1975                 arg = strskipwhite(fp);
1976                 fp = strwhite(arg);
1977                 if (arg == NULL) {
1978                         ifo->auth.options |= DHCPCD_AUTH_SEND;
1979                         if (ifo->auth.protocol == AUTH_PROTO_TOKEN)
1980                                 ifo->auth.protocol = AUTH_ALG_NONE;
1981                         else
1982                                 ifo->auth.algorithm = AUTH_ALG_HMAC_MD5;
1983                         ifo->auth.rdm = AUTH_RDM_MONOTONIC;
1984                         break;
1985                 }
1986                 if (fp)
1987                         *fp++ = '\0';
1988                 if (ifo->auth.protocol == AUTH_PROTO_TOKEN) {
1989                         np = strchr(arg, '/');
1990                         if (np) {
1991                                 if (fp == NULL || np < fp)
1992                                         *np++ = '\0';
1993                                 else
1994                                         np = NULL;
1995                         }
1996                         if (parse_uint32(&ifo->auth.token_snd_secretid,
1997                             arg) == -1)
1998                                 logerrx("%s: not a number", arg);
1999                         else
2000                                 ifo->auth.token_rcv_secretid =
2001                                     ifo->auth.token_snd_secretid;
2002                         if (np &&
2003                             parse_uint32(&ifo->auth.token_rcv_secretid,
2004                             np) == -1)
2005                                 logerrx("%s: not a number", arg);
2006                 } else {
2007                         if (strcasecmp(arg, "hmacmd5") == 0 ||
2008                             strcasecmp(arg, "hmac-md5") == 0)
2009                                 ifo->auth.algorithm = AUTH_ALG_HMAC_MD5;
2010                         else {
2011                                 logerrx("%s: unsupported algorithm", arg);
2012                                 return 1;
2013                         }
2014                 }
2015                 arg = fp;
2016                 if (arg == NULL) {
2017                         ifo->auth.options |= DHCPCD_AUTH_SEND;
2018                         ifo->auth.rdm = AUTH_RDM_MONOTONIC;
2019                         break;
2020                 }
2021                 if (strcasecmp(arg, "monocounter") == 0) {
2022                         ifo->auth.rdm = AUTH_RDM_MONOTONIC;
2023                         ifo->auth.options |= DHCPCD_AUTH_RDM_COUNTER;
2024                 } else if (strcasecmp(arg, "monotonic") ==0 ||
2025                     strcasecmp(arg, "monotime") == 0)
2026                         ifo->auth.rdm = AUTH_RDM_MONOTONIC;
2027                 else {
2028                         logerrx("%s: unsupported RDM", arg);
2029                         return -1;
2030                 }
2031                 ifo->auth.options |= DHCPCD_AUTH_SEND;
2032                 break;
2033 #else
2034                 logerrx("no authentication support");
2035                 return -1;
2036 #endif
2037         case O_AUTHTOKEN:
2038                 ARG_REQUIRED;
2039 #ifdef AUTH
2040                 fp = strwhite(arg);
2041                 if (fp == NULL) {
2042                         logerrx("authtoken requires a realm");
2043                         return -1;
2044                 }
2045                 *fp++ = '\0';
2046                 token = calloc(1, sizeof(*token));
2047                 if (token == NULL) {
2048                         logerr(__func__);
2049                         return -1;
2050                 }
2051                 if (parse_uint32(&token->secretid, arg) == -1) {
2052                         logerrx("%s: not a number", arg);
2053                         goto invalid_token;
2054                 }
2055                 arg = fp;
2056                 fp = strend(arg);
2057                 if (fp == NULL) {
2058                         logerrx("authtoken requies an a key");
2059                         goto invalid_token;
2060                 }
2061                 *fp++ = '\0';
2062                 s = parse_string(NULL, 0, arg);
2063                 if (s == -1) {
2064                         logerr("realm_len");
2065                         goto invalid_token;
2066                 }
2067                 if (s != 0) {
2068                         token->realm_len = (size_t)s;
2069                         token->realm = malloc(token->realm_len);
2070                         if (token->realm == NULL) {
2071                                 logerr(__func__);
2072                                 goto invalid_token;
2073                         }
2074                         parse_string((char *)token->realm, token->realm_len,
2075                             arg);
2076                 }
2077                 arg = fp;
2078                 fp = strend(arg);
2079                 if (fp == NULL) {
2080                         logerrx("authtoken requies an expiry date");
2081                         goto invalid_token;
2082                 }
2083                 *fp++ = '\0';
2084                 if (*arg == '"') {
2085                         arg++;
2086                         np = strchr(arg, '"');
2087                         if (np)
2088                                 *np = '\0';
2089                 }
2090                 if (strcmp(arg, "0") == 0 || strcasecmp(arg, "forever") == 0)
2091                         token->expire =0;
2092                 else {
2093                         struct tm tm;
2094
2095                         memset(&tm, 0, sizeof(tm));
2096                         if (strptime(arg, "%Y-%m-%d %H:%M", &tm) == NULL) {
2097                                 logerrx("%s: invalid date time", arg);
2098                                 goto invalid_token;
2099                         }
2100                         if ((token->expire = mktime(&tm)) == (time_t)-1) {
2101                                 logerr("%s: mktime", __func__);
2102                                 goto invalid_token;
2103                         }
2104                 }
2105                 arg = fp;
2106                 s = parse_string(NULL, 0, arg);
2107                 if (s == -1 || s == 0) {
2108                         if (s == -1)
2109                                 logerr("token_len");
2110                         else
2111                                 logerrx("authtoken needs a key");
2112                         goto invalid_token;
2113                 }
2114                 token->key_len = (size_t)s;
2115                 token->key = malloc(token->key_len);
2116                 if (token->key == NULL) {
2117                         logerr(__func__);
2118                         goto invalid_token;
2119                 }
2120                 parse_string((char *)token->key, token->key_len, arg);
2121                 TAILQ_INSERT_TAIL(&ifo->auth.tokens, token, next);
2122                 break;
2123
2124 invalid_token:
2125                 free(token->realm);
2126                 free(token);
2127 #else
2128                 logerrx("no authentication support");
2129 #endif
2130                 return -1;
2131         case O_AUTHNOTREQUIRED:
2132                 ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
2133                 break;
2134         case O_DHCP:
2135                 ifo->options |= DHCPCD_DHCP | DHCPCD_WANTDHCP | DHCPCD_IPV4;
2136                 break;
2137         case O_NODHCP:
2138                 ifo->options &= ~DHCPCD_DHCP;
2139                 break;
2140         case O_DHCP6:
2141                 ifo->options |= DHCPCD_DHCP6 | DHCPCD_IPV6;
2142                 break;
2143         case O_NODHCP6:
2144                 ifo->options &= ~DHCPCD_DHCP6;
2145                 break;
2146         case O_CONTROLGRP:
2147                 ARG_REQUIRED;
2148 #ifdef PRIVSEP
2149                 /* Control group is already set by this point.
2150                  * We don't need to pledge getpw either with this. */
2151                 if (IN_PRIVSEP(ctx))
2152                         break;
2153 #endif
2154 #ifdef _REENTRANT
2155                 l = sysconf(_SC_GETGR_R_SIZE_MAX);
2156                 if (l == -1)
2157                         dl = 1024;
2158                 else
2159                         dl = (size_t)l;
2160                 p = malloc(dl);
2161                 if (p == NULL) {
2162                         logerr(__func__);
2163                         return -1;
2164                 }
2165                 while ((i = getgrnam_r(arg, &grpbuf, p, dl, &grp)) ==
2166                     ERANGE)
2167                 {
2168                         size_t nl = dl * 2;
2169                         if (nl < dl) {
2170                                 logerrx("control_group: out of buffer");
2171                                 free(p);
2172                                 return -1;
2173                         }
2174                         dl = nl;
2175                         np = realloc(p, dl);
2176                         if (np == NULL) {
2177                                 logerr(__func__);
2178                                 free(p);
2179                                 return -1;
2180                         }
2181                         p = np;
2182                 }
2183                 if (i != 0) {
2184                         errno = i;
2185                         logerr("getgrnam_r");
2186                         free(p);
2187                         return -1;
2188                 }
2189                 if (grp == NULL) {
2190                         if (!ctx->control_group)
2191                                 logerrx("controlgroup: %s: not found", arg);
2192                         free(p);
2193                         return -1;
2194                 }
2195                 ctx->control_group = grp->gr_gid;
2196                 free(p);
2197 #else
2198                 grp = getgrnam(arg);
2199                 if (grp == NULL) {
2200                         if (!ctx->control_group)
2201                                 logerrx("controlgroup: %s: not found", arg);
2202                         return -1;
2203                 }
2204                 ctx->control_group = grp->gr_gid;
2205 #endif
2206                 break;
2207         case O_GATEWAY:
2208                 ifo->options |= DHCPCD_GATEWAY;
2209                 break;
2210         case O_NOUP:
2211                 ifo->options &= ~DHCPCD_IF_UP;
2212                 break;
2213         case O_SLAAC:
2214                 ARG_REQUIRED;
2215                 np = strwhite(arg);
2216                 if (np != NULL) {
2217                         *np++ = '\0';
2218                         np = strskipwhite(np);
2219                 }
2220                 if (strcmp(arg, "private") == 0 ||
2221                     strcmp(arg, "stableprivate") == 0 ||
2222                     strcmp(arg, "stable") == 0)
2223                         ifo->options |= DHCPCD_SLAACPRIVATE;
2224                 else
2225                         ifo->options &= ~DHCPCD_SLAACPRIVATE;
2226                 if (np != NULL &&
2227                     (strcmp(np, "temp") == 0 || strcmp(np, "temporary") == 0))
2228                         ifo->options |= DHCPCD_SLAACTEMP;
2229                 break;
2230         case O_BOOTP:
2231                 ifo->options |= DHCPCD_BOOTP;
2232                 break;
2233         case O_NODELAY:
2234                 ifo->options &= ~DHCPCD_INITIAL_DELAY;
2235                 break;
2236         case O_LASTLEASE_EXTEND:
2237                 ifo->options |= DHCPCD_LASTLEASE | DHCPCD_LASTLEASE_EXTEND;
2238                 break;
2239         case O_INACTIVE:
2240                 ifo->options |= DHCPCD_INACTIVE;
2241                 break;
2242         case O_MUDURL:
2243                 ARG_REQUIRED;
2244                 s = parse_string((char *)ifo->mudurl + 1, MUDURL_MAX_LEN, arg);
2245                 if (s == -1) {
2246                         logerr("mudurl");
2247                         return -1;
2248                 }
2249                 *ifo->mudurl = (uint8_t)s;
2250                 break;
2251         case O_LINK_RCVBUF:
2252 #ifndef SMALL
2253                 ARG_REQUIRED;
2254                 ctx->link_rcvbuf = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
2255                 if (e) {
2256                         logerrx("failed to convert link_rcvbuf %s", arg);
2257                         return -1;
2258                 }
2259 #endif
2260                 break;
2261         case O_CONFIGURE:
2262                 ifo->options |= DHCPCD_CONFIGURE;
2263                 break;
2264         case O_NOCONFIGURE:
2265                 ifo->options &= ~DHCPCD_CONFIGURE;
2266                 break;
2267         default:
2268                 return 0;
2269         }
2270
2271         return 1;
2272
2273 #ifdef ARG_REQUIRED
2274 arg_required:
2275         logerrx("option %d requires an argument", opt);
2276         return -1;
2277 #undef ARG_REQUIRED
2278 #endif
2279 }
2280
2281 static int
2282 parse_config_line(struct dhcpcd_ctx *ctx, const char *ifname,
2283     struct if_options *ifo, const char *opt, char *line,
2284     struct dhcp_opt **ldop, struct dhcp_opt **edop)
2285 {
2286         unsigned int i;
2287
2288         for (i = 0; i < sizeof(cf_options) / sizeof(cf_options[0]); i++) {
2289                 if (!cf_options[i].name ||
2290                     strcmp(cf_options[i].name, opt) != 0)
2291                         continue;
2292
2293                 if (cf_options[i].has_arg == required_argument && !line) {
2294                         logerrx("option requires an argument -- %s", opt);
2295                         return -1;
2296                 }
2297
2298                 return parse_option(ctx, ifname, ifo, cf_options[i].val, line,
2299                     ldop, edop);
2300         }
2301
2302         if (!(ctx->options & DHCPCD_PRINT_PIDFILE))
2303                 logerrx("unknown option: %s", opt);
2304         return -1;
2305 }
2306
2307 static void
2308 finish_config(struct if_options *ifo)
2309 {
2310
2311         /* Terminate the encapsulated options */
2312         if (ifo->vendor[0] && !(ifo->options & DHCPCD_VENDORRAW)) {
2313                 ifo->vendor[0]++;
2314                 ifo->vendor[ifo->vendor[0]] = DHO_END;
2315                 /* We are called twice.
2316                  * This should be fixed, but in the meantime, this
2317                  * guard should suffice */
2318                 ifo->options |= DHCPCD_VENDORRAW;
2319         }
2320
2321         if (!(ifo->options & DHCPCD_ARP) ||
2322             ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
2323                 ifo->options &= ~DHCPCD_IPV4LL;
2324
2325         if (!(ifo->options & DHCPCD_IPV4))
2326                 ifo->options &= ~(DHCPCD_DHCP | DHCPCD_IPV4LL | DHCPCD_WAITIP4);
2327
2328         if (!(ifo->options & DHCPCD_IPV6))
2329                 ifo->options &=
2330                     ~(DHCPCD_IPV6RS | DHCPCD_DHCP6 | DHCPCD_WAITIP6);
2331
2332         if (!(ifo->options & DHCPCD_IPV6RS))
2333                 ifo->options &=
2334                     ~(DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS);
2335 }
2336
2337 struct if_options *
2338 default_config(struct dhcpcd_ctx *ctx)
2339 {
2340         struct if_options *ifo;
2341
2342         /* Seed our default options */
2343         if ((ifo = calloc(1, sizeof(*ifo))) == NULL) {
2344                 logerr(__func__);
2345                 return NULL;
2346         }
2347         ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
2348         ifo->timeout = DEFAULT_TIMEOUT;
2349         ifo->reboot = DEFAULT_REBOOT;
2350         ifo->metric = -1;
2351         ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
2352         rb_tree_init(&ifo->routes, &rt_compare_list_ops);
2353 #ifdef AUTH
2354         TAILQ_INIT(&ifo->auth.tokens);
2355 #endif
2356
2357         /* Inherit some global defaults */
2358         if (ctx->options & DHCPCD_CONFIGURE)
2359                 ifo->options |= DHCPCD_CONFIGURE;
2360         if (ctx->options & DHCPCD_PERSISTENT)
2361                 ifo->options |= DHCPCD_PERSISTENT;
2362         if (ctx->options & DHCPCD_SLAACPRIVATE)
2363                 ifo->options |= DHCPCD_SLAACPRIVATE;
2364
2365         return ifo;
2366 }
2367
2368 struct if_options *
2369 read_config(struct dhcpcd_ctx *ctx,
2370     const char *ifname, const char *ssid, const char *profile)
2371 {
2372         struct if_options *ifo;
2373         char buf[UDPLEN_MAX], *bp; /* 64k max config file size */
2374         char *line, *option, *p;
2375         ssize_t buflen;
2376         size_t vlen;
2377         int skip, have_profile, new_block, had_block;
2378 #if !defined(INET) || !defined(INET6)
2379         size_t i;
2380         struct dhcp_opt *opt;
2381 #endif
2382         struct dhcp_opt *ldop, *edop;
2383
2384         /* Seed our default options */
2385         if ((ifo = default_config(ctx)) == NULL)
2386                 return NULL;
2387         if (default_options == 0) {
2388                 default_options |= DHCPCD_CONFIGURE | DHCPCD_DAEMONISE |
2389                     DHCPCD_GATEWAY;
2390 #ifdef INET
2391                 skip = socket(PF_INET, SOCK_DGRAM, 0);
2392                 if (skip != -1) {
2393                         close(skip);
2394                         default_options |= DHCPCD_IPV4 | DHCPCD_ARP |
2395                             DHCPCD_DHCP | DHCPCD_IPV4LL;
2396                 }
2397 #endif
2398 #ifdef INET6
2399                 skip = socket(PF_INET6, SOCK_DGRAM, 0);
2400                 if (skip != -1) {
2401                         close(skip);
2402                         default_options |= DHCPCD_IPV6 | DHCPCD_IPV6RS |
2403                             DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS |
2404                             DHCPCD_DHCP6;
2405                 }
2406 #endif
2407 #ifdef PLUGIN_DEV
2408                 default_options |= DHCPCD_DEV;
2409 #endif
2410         }
2411         ifo->options |= default_options;
2412
2413         CLEAR_CONFIG_BLOCK(ifo);
2414
2415         vlen = strlcpy((char *)ifo->vendorclassid + 1, ctx->vendor,
2416             sizeof(ifo->vendorclassid) - 1);
2417         ifo->vendorclassid[0] = (uint8_t)(vlen > 255 ? 0 : vlen);
2418
2419         /* Reset route order */
2420         ctx->rt_order = 0;
2421
2422         /* Parse our embedded options file */
2423         if (ifname == NULL && !(ctx->options & DHCPCD_PRINT_PIDFILE)) {
2424                 /* Space for initial estimates */
2425 #if defined(INET) && defined(INITDEFINES)
2426                 ifo->dhcp_override =
2427                     calloc(INITDEFINES, sizeof(*ifo->dhcp_override));
2428                 if (ifo->dhcp_override == NULL)
2429                         logerr(__func__);
2430                 else
2431                         ifo->dhcp_override_len = INITDEFINES;
2432 #endif
2433
2434 #if defined(INET6) && defined(INITDEFINENDS)
2435                 ifo->nd_override =
2436                     calloc(INITDEFINENDS, sizeof(*ifo->nd_override));
2437                 if (ifo->nd_override == NULL)
2438                         logerr(__func__);
2439                 else
2440                         ifo->nd_override_len = INITDEFINENDS;
2441 #endif
2442 #if defined(INET6) && defined(INITDEFINE6S)
2443                 ifo->dhcp6_override =
2444                     calloc(INITDEFINE6S, sizeof(*ifo->dhcp6_override));
2445                 if (ifo->dhcp6_override == NULL)
2446                         logerr(__func__);
2447                 else
2448                         ifo->dhcp6_override_len = INITDEFINE6S;
2449 #endif
2450
2451                 /* Now load our embedded config */
2452 #ifdef EMBEDDED_CONFIG
2453                 buflen = dhcp_readfile(ctx, EMBEDDED_CONFIG, buf, sizeof(buf));
2454                 if (buflen == -1) {
2455                         logerr("%s: %s", __func__, EMBEDDED_CONFIG);
2456                         return ifo;
2457                 }
2458                 if (buf[buflen - 1] != '\0') {
2459                         if ((size_t)buflen < sizeof(buf) - 1)
2460                                 buflen++;
2461                         buf[buflen - 1] = '\0';
2462                 }
2463 #else
2464                 buflen = (ssize_t)strlcpy(buf, dhcpcd_embedded_conf,
2465                     sizeof(buf));
2466                 if ((size_t)buflen >= sizeof(buf)) {
2467                         logerrx("%s: embedded config too big", __func__);
2468                         return ifo;
2469                 }
2470                 /* Our embedded config is NULL terminated */
2471 #endif
2472                 bp = buf;
2473                 while ((line = get_line(&bp, &buflen)) != NULL) {
2474                         option = strsep(&line, " \t");
2475                         if (line)
2476                                 line = strskipwhite(line);
2477                         /* Trim trailing whitespace */
2478                         if (line) {
2479                                 p = line + strlen(line) - 1;
2480                                 while (p != line &&
2481                                     (*p == ' ' || *p == '\t') &&
2482                                     *(p - 1) != '\\')
2483                                         *p-- = '\0';
2484                         }
2485                         parse_config_line(ctx, NULL, ifo, option, line,
2486                             &ldop, &edop);
2487                 }
2488
2489 #ifdef INET
2490                 ctx->dhcp_opts = ifo->dhcp_override;
2491                 ctx->dhcp_opts_len = ifo->dhcp_override_len;
2492 #else
2493                 for (i = 0, opt = ifo->dhcp_override;
2494                     i < ifo->dhcp_override_len;
2495                     i++, opt++)
2496                         free_dhcp_opt_embenc(opt);
2497                 free(ifo->dhcp_override);
2498 #endif
2499                 ifo->dhcp_override = NULL;
2500                 ifo->dhcp_override_len = 0;
2501
2502 #ifdef INET6
2503                 ctx->nd_opts = ifo->nd_override;
2504                 ctx->nd_opts_len = ifo->nd_override_len;
2505 #ifdef DHCP6
2506                 ctx->dhcp6_opts = ifo->dhcp6_override;
2507                 ctx->dhcp6_opts_len = ifo->dhcp6_override_len;
2508 #endif
2509 #else
2510                 for (i = 0, opt = ifo->nd_override;
2511                     i < ifo->nd_override_len;
2512                     i++, opt++)
2513                         free_dhcp_opt_embenc(opt);
2514                 free(ifo->nd_override);
2515                 for (i = 0, opt = ifo->dhcp6_override;
2516                     i < ifo->dhcp6_override_len;
2517                     i++, opt++)
2518                         free_dhcp_opt_embenc(opt);
2519                 free(ifo->dhcp6_override);
2520 #endif
2521                 ifo->nd_override = NULL;
2522                 ifo->nd_override_len = 0;
2523                 ifo->dhcp6_override = NULL;
2524                 ifo->dhcp6_override_len = 0;
2525
2526                 ctx->vivso = ifo->vivso_override;
2527                 ctx->vivso_len = ifo->vivso_override_len;
2528                 ifo->vivso_override = NULL;
2529                 ifo->vivso_override_len = 0;
2530         }
2531
2532         /* Parse our options file */
2533         buflen = dhcp_readfile(ctx, ctx->cffile, buf, sizeof(buf));
2534         if (buflen == -1) {
2535                 /* dhcpcd can continue without it, but no DNS options
2536                  * would be requested ... */
2537                 logerr("%s: %s", __func__, ctx->cffile);
2538                 return ifo;
2539         }
2540         if (buf[buflen - 1] != '\0') {
2541                 if ((size_t)buflen < sizeof(buf) - 1)
2542                         buflen++;
2543                 buf[buflen - 1] = '\0';
2544         }
2545         dhcp_filemtime(ctx, ctx->cffile, &ifo->mtime);
2546
2547         ldop = edop = NULL;
2548         skip = have_profile = new_block = 0;
2549         had_block = ifname == NULL ? 1 : 0;
2550         bp = buf;
2551         while ((line = get_line(&bp, &buflen)) != NULL) {
2552                 option = strsep(&line, " \t");
2553                 if (line)
2554                         line = strskipwhite(line);
2555                 /* Trim trailing whitespace */
2556                 if (line) {
2557                         p = line + strlen(line) - 1;
2558                         while (p != line &&
2559                             (*p == ' ' || *p == '\t') &&
2560                             *(p - 1) != '\\')
2561                                 *p-- = '\0';
2562                 }
2563                 if (skip == 0 && new_block) {
2564                         had_block = 1;
2565                         new_block = 0;
2566                         ifo->options &= ~DHCPCD_WAITOPTS;
2567                         SET_CONFIG_BLOCK(ifo);
2568                 }
2569
2570                 /* Start of an interface block, skip if not ours */
2571                 if (strcmp(option, "interface") == 0) {
2572                         char **n;
2573
2574                         new_block = 1;
2575                         if (line == NULL) {
2576                                 /* No interface given */
2577                                 skip = 1;
2578                                 continue;
2579                         }
2580                         if (ifname && strcmp(line, ifname) == 0)
2581                                 skip = 0;
2582                         else
2583                                 skip = 1;
2584                         if (ifname)
2585                                 continue;
2586
2587                         n = reallocarray(ctx->ifcv,
2588                             (size_t)ctx->ifcc + 1, sizeof(char *));
2589                         if (n == NULL) {
2590                                 logerr(__func__);
2591                                 continue;
2592                         }
2593                         ctx->ifcv = n;
2594                         ctx->ifcv[ctx->ifcc] = strdup(line);
2595                         if (ctx->ifcv[ctx->ifcc] == NULL) {
2596                                 logerr(__func__);
2597                                 continue;
2598                         }
2599                         ctx->ifcc++;
2600                         continue;
2601                 }
2602                 /* Start of an ssid block, skip if not ours */
2603                 if (strcmp(option, "ssid") == 0) {
2604                         new_block = 1;
2605                         if (ssid && line && strcmp(line, ssid) == 0)
2606                                 skip = 0;
2607                         else
2608                                 skip = 1;
2609                         continue;
2610                 }
2611                 /* Start of a profile block, skip if not ours */
2612                 if (strcmp(option, "profile") == 0) {
2613                         new_block = 1;
2614                         if (profile && line && strcmp(line, profile) == 0) {
2615                                 skip = 0;
2616                                 have_profile = 1;
2617                         } else
2618                                 skip = 1;
2619                         continue;
2620                 }
2621                 /* Skip arping if we have selected a profile but not parsing
2622                  * one. */
2623                 if (profile && !have_profile && strcmp(option, "arping") == 0)
2624                         continue;
2625                 if (skip)
2626                         continue;
2627
2628                 parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop);
2629         }
2630
2631         if (profile && !have_profile) {
2632                 free_options(ctx, ifo);
2633                 errno = ENOENT;
2634                 return NULL;
2635         }
2636
2637         if (!had_block)
2638                 ifo->options &= ~DHCPCD_WAITOPTS;
2639         CLEAR_CONFIG_BLOCK(ifo);
2640         finish_config(ifo);
2641         return ifo;
2642 }
2643
2644 int
2645 add_options(struct dhcpcd_ctx *ctx, const char *ifname,
2646     struct if_options *ifo, int argc, char **argv)
2647 {
2648         int oi, opt, r;
2649         unsigned long long wait_opts;
2650
2651         if (argc == 0)
2652                 return 1;
2653
2654         optind = 0;
2655         r = 1;
2656         /* Don't apply the command line wait options to each interface,
2657          * only use the dhcpcd.conf entry for that. */
2658         if (ifname != NULL)
2659                 wait_opts = ifo->options & DHCPCD_WAITOPTS;
2660         while ((opt = getopt_long(argc, argv,
2661             ctx->options & DHCPCD_PRINT_PIDFILE ? NOERR_IF_OPTS : IF_OPTS,
2662             cf_options, &oi)) != -1)
2663         {
2664                 r = parse_option(ctx, ifname, ifo, opt, optarg, NULL, NULL);
2665                 if (r != 1)
2666                         break;
2667         }
2668         if (ifname != NULL) {
2669                 ifo->options &= ~DHCPCD_WAITOPTS;
2670                 ifo->options |= wait_opts;
2671         }
2672
2673         finish_config(ifo);
2674         return r;
2675 }
2676
2677 void
2678 free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo)
2679 {
2680         size_t i;
2681 #ifdef RT_FREE_ROUTE_TABLE
2682         struct interface *ifp;
2683         struct rt *rt;
2684 #endif
2685         struct dhcp_opt *opt;
2686         struct vivco *vo;
2687 #ifdef AUTH
2688         struct token *token;
2689 #endif
2690
2691         if (ifo == NULL)
2692                 return;
2693
2694         if (ifo->environ) {
2695                 i = 0;
2696                 while (ifo->environ[i])
2697                         free(ifo->environ[i++]);
2698                 free(ifo->environ);
2699         }
2700         if (ifo->config) {
2701                 i = 0;
2702                 while (ifo->config[i])
2703                         free(ifo->config[i++]);
2704                 free(ifo->config);
2705         }
2706
2707 #ifdef RT_FREE_ROUTE_TABLE
2708         /* Stupidly, we don't know the interface when creating the options.
2709          * As such, make sure each route has one so they can goto the
2710          * free list. */
2711         ifp = ctx->ifaces != NULL ? TAILQ_FIRST(ctx->ifaces) : NULL;
2712         if (ifp != NULL) {
2713                 RB_TREE_FOREACH(rt, &ifo->routes) {
2714                         if (rt->rt_ifp == NULL)
2715                                 rt->rt_ifp = ifp;
2716                 }
2717         }
2718 #endif
2719         rt_headclear0(ctx, &ifo->routes, AF_UNSPEC);
2720
2721         free(ifo->arping);
2722         free(ifo->blacklist);
2723         free(ifo->fallback);
2724
2725         for (opt = ifo->dhcp_override;
2726             ifo->dhcp_override_len > 0;
2727             opt++, ifo->dhcp_override_len--)
2728                 free_dhcp_opt_embenc(opt);
2729         free(ifo->dhcp_override);
2730         for (opt = ifo->nd_override;
2731             ifo->nd_override_len > 0;
2732             opt++, ifo->nd_override_len--)
2733                 free_dhcp_opt_embenc(opt);
2734         free(ifo->nd_override);
2735         for (opt = ifo->dhcp6_override;
2736             ifo->dhcp6_override_len > 0;
2737             opt++, ifo->dhcp6_override_len--)
2738                 free_dhcp_opt_embenc(opt);
2739         free(ifo->dhcp6_override);
2740         for (vo = ifo->vivco;
2741             ifo->vivco_len > 0;
2742             vo++, ifo->vivco_len--)
2743                 free(vo->data);
2744         free(ifo->vivco);
2745         for (opt = ifo->vivso_override;
2746             ifo->vivso_override_len > 0;
2747             opt++, ifo->vivso_override_len--)
2748                 free_dhcp_opt_embenc(opt);
2749         free(ifo->vivso_override);
2750
2751 #if defined(INET6) && !defined(SMALL)
2752         for (; ifo->ia_len > 0; ifo->ia_len--)
2753                 free(ifo->ia[ifo->ia_len - 1].sla);
2754 #endif
2755         free(ifo->ia);
2756
2757 #ifdef AUTH
2758         while ((token = TAILQ_FIRST(&ifo->auth.tokens))) {
2759                 TAILQ_REMOVE(&ifo->auth.tokens, token, next);
2760                 if (token->realm_len)
2761                         free(token->realm);
2762                 free(token->key);
2763                 free(token);
2764         }
2765 #endif
2766         free(ifo);
2767 }