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