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