Home | History | Annotate | Download | only in dhcpcd
      1 /*
      2  * dhcpcd - DHCP client daemon
      3  * Copyright (c) 2006-2012 Roy Marples <roy (at) marples.name>
      4  * All rights reserved
      5 
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/types.h>
     29 #include <sys/utsname.h>
     30 
     31 #include <arpa/inet.h>
     32 
     33 #include <ctype.h>
     34 #include <errno.h>
     35 #include <getopt.h>
     36 #include <paths.h>
     37 #include <stdio.h>
     38 #include <stdlib.h>
     39 #include <string.h>
     40 #include <syslog.h>
     41 #include <unistd.h>
     42 #include <time.h>
     43 
     44 #include "config.h"
     45 #include "common.h"
     46 #include "if-options.h"
     47 #include "net.h"
     48 #include "platform.h"
     49 
     50 /* These options only make sense in the config file, so don't use any
     51    valid short options for them */
     52 #define O_BASE		MAX('z', 'Z') + 1
     53 #define O_ARPING	O_BASE + 1
     54 #define O_FALLBACK	O_BASE + 2
     55 #define O_DESTINATION	O_BASE + 3
     56 #define O_NOIPV6RS	O_BASE + 4
     57 #define O_IPV6_RA_FORK	O_BASE + 5
     58 
     59 const struct option cf_options[] = {
     60 	{"background",      no_argument,       NULL, 'b'},
     61 	{"script",          required_argument, NULL, 'c'},
     62 	{"debug",           no_argument,       NULL, 'd'},
     63 	{"env",             required_argument, NULL, 'e'},
     64 	{"config",          required_argument, NULL, 'f'},
     65 	{"reconfigure",     no_argument,       NULL, 'g'},
     66 	{"hostname",        optional_argument, NULL, 'h'},
     67 	{"vendorclassid",   optional_argument, NULL, 'i'},
     68 	{"release",         no_argument,       NULL, 'k'},
     69 	{"leasetime",       required_argument, NULL, 'l'},
     70 	{"metric",          required_argument, NULL, 'm'},
     71 	{"rebind",          no_argument,       NULL, 'n'},
     72 	{"option",          required_argument, NULL, 'o'},
     73 	{"persistent",      no_argument,       NULL, 'p'},
     74 	{"quiet",           no_argument,       NULL, 'q'},
     75 	{"request",         optional_argument, NULL, 'r'},
     76 	{"inform",          optional_argument, NULL, 's'},
     77 	{"timeout",         required_argument, NULL, 't'},
     78 	{"userclass",       required_argument, NULL, 'u'},
     79 	{"vendor",          required_argument, NULL, 'v'},
     80 	{"waitip",          no_argument,       NULL, 'w'},
     81 	{"exit",            no_argument,       NULL, 'x'},
     82 	{"allowinterfaces", required_argument, NULL, 'z'},
     83 	{"reboot",          required_argument, NULL, 'y'},
     84 	{"noarp",           no_argument,       NULL, 'A'},
     85 	{"nobackground",    no_argument,       NULL, 'B'},
     86 	{"nohook",          required_argument, NULL, 'C'},
     87 	{"duid",            no_argument,       NULL, 'D'},
     88 	{"lastlease",       no_argument,       NULL, 'E'},
     89 	{"fqdn",            optional_argument, NULL, 'F'},
     90 	{"nogateway",       no_argument,       NULL, 'G'},
     91 	{"xidhwaddr",       no_argument,       NULL, 'H'},
     92 	{"clientid",        optional_argument, NULL, 'I'},
     93 	{"broadcast",       no_argument,       NULL, 'J'},
     94 	{"nolink",          no_argument,       NULL, 'K'},
     95 	{"noipv4ll",        no_argument,       NULL, 'L'},
     96 	{"nooption",        optional_argument, NULL, 'O'},
     97 	{"require",         required_argument, NULL, 'Q'},
     98 	{"static",          required_argument, NULL, 'S'},
     99 	{"test",            no_argument,       NULL, 'T'},
    100 	{"dumplease",       no_argument,       NULL, 'U'},
    101 	{"variables",       no_argument,       NULL, 'V'},
    102 	{"whitelist",       required_argument, NULL, 'W'},
    103 	{"blacklist",       required_argument, NULL, 'X'},
    104 	{"denyinterfaces",  required_argument, NULL, 'Z'},
    105 	{"arping",          required_argument, NULL, O_ARPING},
    106 	{"destination",     required_argument, NULL, O_DESTINATION},
    107 	{"fallback",        required_argument, NULL, O_FALLBACK},
    108 	{"noipv6rs",        no_argument,       NULL, O_NOIPV6RS},
    109 	{"ipv6ra_fork",     no_argument,       NULL, O_IPV6_RA_FORK},
    110 	{NULL,              0,                 NULL, '\0'}
    111 };
    112 
    113 static int
    114 atoint(const char *s)
    115 {
    116 	char *t;
    117 	long n;
    118 
    119 	errno = 0;
    120 	n = strtol(s, &t, 0);
    121 	if ((errno != 0 && n == 0) || s == t ||
    122 	    (errno == ERANGE && (n == LONG_MAX || n == LONG_MIN)))
    123 	{
    124 		syslog(LOG_ERR, "`%s' out of range", s);
    125 		return -1;
    126 	}
    127 
    128 	return (int)n;
    129 }
    130 
    131 static char *
    132 add_environ(struct if_options *ifo, const char *value, int uniq)
    133 {
    134 	char **newlist;
    135 	char **lst = ifo->environ;
    136 	size_t i = 0, l, lv;
    137 	char *match = NULL, *p;
    138 
    139 	match = xstrdup(value);
    140 	p = strchr(match, '=');
    141 	if (p)
    142 		*p++ = '\0';
    143 	l = strlen(match);
    144 
    145 	while (lst && lst[i]) {
    146 		if (match && strncmp(lst[i], match, l) == 0) {
    147 			if (uniq) {
    148 				free(lst[i]);
    149 				lst[i] = xstrdup(value);
    150 			} else {
    151 				/* Append a space and the value to it */
    152 				l = strlen(lst[i]);
    153 				lv = strlen(p);
    154 				lst[i] = xrealloc(lst[i], l + lv + 2);
    155 				lst[i][l] = ' ';
    156 				memcpy(lst[i] + l + 1, p, lv);
    157 				lst[i][l + lv + 1] = '\0';
    158 			}
    159 			free(match);
    160 			return lst[i];
    161 		}
    162 		i++;
    163 	}
    164 
    165 	newlist = xrealloc(lst, sizeof(char *) * (i + 2));
    166 	newlist[i] = xstrdup(value);
    167 	newlist[i + 1] = NULL;
    168 	ifo->environ = newlist;
    169 	free(match);
    170 	return newlist[i];
    171 }
    172 
    173 #define parse_string(buf, len, arg) parse_string_hwaddr(buf, len, arg, 0)
    174 static ssize_t
    175 parse_string_hwaddr(char *sbuf, ssize_t slen, const char *str, int clid)
    176 {
    177 	ssize_t l;
    178 	const char *p;
    179 	int i, punt_last = 0;
    180 	char c[4];
    181 
    182 	/* If surrounded by quotes then it's a string */
    183 	if (*str == '"') {
    184 		str++;
    185 		l = strlen(str);
    186 		p = str + l - 1;
    187 		if (*p == '"')
    188 			punt_last = 1;
    189 	} else {
    190 		l = hwaddr_aton(NULL, str);
    191 		if (l > 1) {
    192 			if (l > slen) {
    193 				errno = ENOBUFS;
    194 				return -1;
    195 			}
    196 			hwaddr_aton((uint8_t *)sbuf, str);
    197 			return l;
    198 		}
    199 	}
    200 
    201 	/* Process escapes */
    202 	l = 0;
    203 	/* If processing a string on the clientid, first byte should be
    204 	 * 0 to indicate a non hardware type */
    205 	if (clid && *str) {
    206 		*sbuf++ = 0;
    207 		l++;
    208 	}
    209 	c[3] = '\0';
    210 	while (*str) {
    211 		if (++l > slen) {
    212 			errno = ENOBUFS;
    213 			return -1;
    214 		}
    215 		if (*str == '\\') {
    216 			str++;
    217 			switch(*str) {
    218 			case '\0':
    219 				break;
    220 			case 'b':
    221 				*sbuf++ = '\b';
    222 				str++;
    223 				break;
    224 			case 'n':
    225 				*sbuf++ = '\n';
    226 				str++;
    227 				break;
    228 			case 'r':
    229 				*sbuf++ = '\r';
    230 				str++;
    231 				break;
    232 			case 't':
    233 				*sbuf++ = '\t';
    234 				str++;
    235 				break;
    236 			case 'x':
    237 				/* Grab a hex code */
    238 				c[1] = '\0';
    239 				for (i = 0; i < 2; i++) {
    240 					if (isxdigit((unsigned char)*str) == 0)
    241 						break;
    242 					c[i] = *str++;
    243 				}
    244 				if (c[1] != '\0') {
    245 					c[2] = '\0';
    246 					*sbuf++ = strtol(c, NULL, 16);
    247 				} else
    248 					l--;
    249 				break;
    250 			case '0':
    251 				/* Grab an octal code */
    252 				c[2] = '\0';
    253 				for (i = 0; i < 3; i++) {
    254 					if (*str < '0' || *str > '7')
    255 						break;
    256 					c[i] = *str++;
    257 				}
    258 				if (c[2] != '\0') {
    259 					i = strtol(c, NULL, 8);
    260 					if (i > 255)
    261 						i = 255;
    262 					*sbuf ++= i;
    263 				} else
    264 					l--;
    265 				break;
    266 			default:
    267 				*sbuf++ = *str++;
    268 			}
    269 		} else
    270 			*sbuf++ = *str++;
    271 	}
    272 	if (punt_last) {
    273 		*--sbuf = '\0';
    274 		l--;
    275 	}
    276 	return l;
    277 }
    278 
    279 static char **
    280 splitv(int *argc, char **argv, const char *arg)
    281 {
    282 	char **v = argv;
    283 	char *o = xstrdup(arg), *p, *t;
    284 
    285 	p = o;
    286 	while ((t = strsep(&p, ", "))) {
    287 		(*argc)++;
    288 		v = xrealloc(v, sizeof(char *) * ((*argc)));
    289 		v[(*argc) - 1] = xstrdup(t);
    290 	}
    291 	free(o);
    292 	return v;
    293 }
    294 
    295 static int
    296 parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
    297 {
    298 	char *p;
    299 	int i;
    300 
    301 	if (arg == NULL || *arg == '\0') {
    302 		if (addr != NULL)
    303 			addr->s_addr = 0;
    304 		if (net != NULL)
    305 			net->s_addr = 0;
    306 		return 0;
    307 	}
    308 	if ((p = strchr(arg, '/')) != NULL) {
    309 		*p++ = '\0';
    310 		if (net != NULL &&
    311 		    (sscanf(p, "%d", &i) != 1 ||
    312 			inet_cidrtoaddr(i, net) != 0))
    313 		{
    314 			syslog(LOG_ERR, "`%s' is not a valid CIDR", p);
    315 			return -1;
    316 		}
    317 	}
    318 
    319 	if (addr != NULL && inet_aton(arg, addr) == 0) {
    320 		syslog(LOG_ERR, "`%s' is not a valid IP address", arg);
    321 		return -1;
    322 	}
    323 	if (p != NULL)
    324 		*--p = '/';
    325 	else if (net != NULL)
    326 		net->s_addr = get_netmask(addr->s_addr);
    327 	return 0;
    328 }
    329 
    330 static int
    331 parse_option(struct if_options *ifo, int opt, const char *arg)
    332 {
    333 	int i;
    334 	char *p = NULL, *np;
    335 	ssize_t s;
    336 	struct in_addr addr, addr2;
    337 	struct rt *rt;
    338 
    339 	switch(opt) {
    340 	case 'a': /* FALLTHROUGH */
    341 	case 'f': /* FALLTHROUGH */
    342 	case 'g': /* FALLTHROUGH */
    343 	case 'n': /* FALLTHROUGH */
    344 	case 'x': /* FALLTHROUGH */
    345 	case 'T': /* FALLTHROUGH */
    346 	case 'U': /* We need to handle non interface options */
    347 		break;
    348 	case 'b':
    349 		ifo->options |= DHCPCD_BACKGROUND;
    350 		break;
    351 	case 'c':
    352 		strlcpy(ifo->script, arg, sizeof(ifo->script));
    353 		break;
    354 	case 'd':
    355 		ifo->options |= DHCPCD_DEBUG;
    356 		break;
    357 	case 'e':
    358 		add_environ(ifo, arg, 1);
    359 		break;
    360 	case 'h':
    361 		if (arg) {
    362 			s = parse_string(ifo->hostname,
    363 			    HOSTNAME_MAX_LEN, arg);
    364 			if (s == -1) {
    365 				syslog(LOG_ERR, "hostname: %m");
    366 				return -1;
    367 			}
    368 			if (s != 0 && ifo->hostname[0] == '.') {
    369 				syslog(LOG_ERR,
    370 				    "hostname cannot begin with .");
    371 				return -1;
    372 			}
    373 			ifo->hostname[s] = '\0';
    374 		}
    375 		if (ifo->hostname[0] == '\0')
    376 			ifo->options &= ~DHCPCD_HOSTNAME;
    377 		else
    378 			ifo->options |= DHCPCD_HOSTNAME;
    379 		break;
    380 	case 'i':
    381 		if (arg)
    382 			s = parse_string((char *)ifo->vendorclassid + 1,
    383 			    VENDORCLASSID_MAX_LEN, arg);
    384 		else
    385 			s = 0;
    386 		if (s == -1) {
    387 			syslog(LOG_ERR, "vendorclassid: %m");
    388 			return -1;
    389 		}
    390 		*ifo->vendorclassid = (uint8_t)s;
    391 		break;
    392 	case 'k':
    393 		ifo->options |= DHCPCD_RELEASE;
    394 		break;
    395 	case 'l':
    396 		if (*arg == '-') {
    397 			syslog(LOG_ERR,
    398 			    "leasetime must be a positive value");
    399 			return -1;
    400 		}
    401 		errno = 0;
    402 		ifo->leasetime = (uint32_t)strtol(arg, NULL, 0);
    403 		if (errno == EINVAL || errno == ERANGE) {
    404 			syslog(LOG_ERR, "`%s' out of range", arg);
    405 			return -1;
    406 		}
    407 		break;
    408 	case 'm':
    409 		ifo->metric = atoint(arg);
    410 		if (ifo->metric < 0) {
    411 			syslog(LOG_ERR, "metric must be a positive value");
    412 			return -1;
    413 		}
    414 		break;
    415 	case 'o':
    416 		if (make_option_mask(ifo->requestmask, arg, 1) != 0) {
    417 			syslog(LOG_ERR, "unknown option `%s'", arg);
    418 			return -1;
    419 		}
    420 		break;
    421 	case 'p':
    422 		ifo->options |= DHCPCD_PERSISTENT;
    423 		break;
    424 	case 'q':
    425 		ifo->options |= DHCPCD_QUIET;
    426 		break;
    427 	case 'r':
    428 		if (parse_addr(&ifo->req_addr, NULL, arg) != 0)
    429 			return -1;
    430 		ifo->options |= DHCPCD_REQUEST;
    431 		ifo->req_mask.s_addr = 0;
    432 		break;
    433 	case 's':
    434 		if (arg && *arg != '\0') {
    435 			if (parse_addr(&ifo->req_addr, &ifo->req_mask,
    436 				arg) != 0)
    437 				return -1;
    438 		} else {
    439 			ifo->req_addr.s_addr = 0;
    440 			ifo->req_mask.s_addr = 0;
    441 		}
    442 		ifo->options |= DHCPCD_INFORM | DHCPCD_PERSISTENT;
    443 		ifo->options &= ~(DHCPCD_ARP | DHCPCD_STATIC);
    444 		break;
    445 	case 't':
    446 		ifo->timeout = atoint(arg);
    447 		if (ifo->timeout < 0) {
    448 			syslog(LOG_ERR, "timeout must be a positive value");
    449 			return -1;
    450 		}
    451 		break;
    452 	case 'u':
    453 		s = USERCLASS_MAX_LEN - ifo->userclass[0] - 1;
    454 		s = parse_string((char *)ifo->userclass +
    455 		    ifo->userclass[0] + 2,
    456 		    s, arg);
    457 		if (s == -1) {
    458 			syslog(LOG_ERR, "userclass: %m");
    459 			return -1;
    460 		}
    461 		if (s != 0) {
    462 			ifo->userclass[ifo->userclass[0] + 1] = s;
    463 			ifo->userclass[0] += s + 1;
    464 		}
    465 		break;
    466 	case 'v':
    467 		p = strchr(arg, ',');
    468 		if (!p || !p[1]) {
    469 			syslog(LOG_ERR, "invalid vendor format");
    470 			return -1;
    471 		}
    472 
    473 		/* If vendor starts with , then it is not encapsulated */
    474 		if (p == arg) {
    475 			arg++;
    476 			s = parse_string((char *)ifo->vendor + 1,
    477 			    VENDOR_MAX_LEN, arg);
    478 			if (s == -1) {
    479 				syslog(LOG_ERR, "vendor: %m");
    480 				return -1;
    481 			}
    482 			ifo->vendor[0] = (uint8_t)s;
    483 			ifo->options |= DHCPCD_VENDORRAW;
    484 			break;
    485 		}
    486 
    487 		/* Encapsulated vendor options */
    488 		if (ifo->options & DHCPCD_VENDORRAW) {
    489 			ifo->options &= ~DHCPCD_VENDORRAW;
    490 			ifo->vendor[0] = 0;
    491 		}
    492 
    493 		*p = '\0';
    494 		i = atoint(arg);
    495 		arg = p + 1;
    496 		if (i < 1 || i > 254) {
    497 			syslog(LOG_ERR, "vendor option should be between"
    498 			    " 1 and 254 inclusive");
    499 			return -1;
    500 		}
    501 		s = VENDOR_MAX_LEN - ifo->vendor[0] - 2;
    502 		if (inet_aton(arg, &addr) == 1) {
    503 			if (s < 6) {
    504 				s = -1;
    505 				errno = ENOBUFS;
    506 			} else
    507 				memcpy(ifo->vendor + ifo->vendor[0] + 3,
    508 				    &addr.s_addr, sizeof(addr.s_addr));
    509 		} else {
    510 			s = parse_string((char *)ifo->vendor +
    511 			    ifo->vendor[0] + 3, s, arg);
    512 		}
    513 		if (s == -1) {
    514 			syslog(LOG_ERR, "vendor: %m");
    515 			return -1;
    516 		}
    517 		if (s != 0) {
    518 			ifo->vendor[ifo->vendor[0] + 1] = i;
    519 			ifo->vendor[ifo->vendor[0] + 2] = s;
    520 			ifo->vendor[0] += s + 2;
    521 		}
    522 		break;
    523 	case 'w':
    524 		ifo->options |= DHCPCD_WAITIP;
    525 		break;
    526 	case 'y':
    527 		ifo->reboot = atoint(arg);
    528 		if (ifo->reboot < 0) {
    529 			syslog(LOG_ERR, "reboot must be a positive value");
    530 			return -1;
    531 		}
    532 		break;
    533 	case 'z':
    534 		ifav = splitv(&ifac, ifav, arg);
    535 		break;
    536 	case 'A':
    537 		ifo->options &= ~DHCPCD_ARP;
    538 		/* IPv4LL requires ARP */
    539 		ifo->options &= ~DHCPCD_IPV4LL;
    540 		break;
    541 	case 'B':
    542 		ifo->options &= ~DHCPCD_DAEMONISE;
    543 		break;
    544 	case 'C':
    545 		/* Commas to spaces for shell */
    546 		while ((p = strchr(arg, ',')))
    547 			*p = ' ';
    548 		s = strlen("skip_hooks=") + strlen(arg) + 1;
    549 		p = xmalloc(sizeof(char) * s);
    550 		snprintf(p, s, "skip_hooks=%s", arg);
    551 		add_environ(ifo, p, 0);
    552 		free(p);
    553 		break;
    554 	case 'D':
    555 		ifo->options |= DHCPCD_CLIENTID | DHCPCD_DUID;
    556 		break;
    557 	case 'E':
    558 		ifo->options |= DHCPCD_LASTLEASE;
    559 		break;
    560 	case 'F':
    561 		if (!arg) {
    562 			ifo->fqdn = FQDN_BOTH;
    563 			break;
    564 		}
    565 		if (strcmp(arg, "none") == 0)
    566 			ifo->fqdn = FQDN_NONE;
    567 		else if (strcmp(arg, "ptr") == 0)
    568 			ifo->fqdn = FQDN_PTR;
    569 		else if (strcmp(arg, "both") == 0)
    570 			ifo->fqdn = FQDN_BOTH;
    571 		else if (strcmp(arg, "disable") == 0)
    572 			ifo->fqdn = FQDN_DISABLE;
    573 		else {
    574 			syslog(LOG_ERR, "invalid value `%s' for FQDN", arg);
    575 			return -1;
    576 		}
    577 		break;
    578 	case 'G':
    579 		ifo->options &= ~DHCPCD_GATEWAY;
    580 		break;
    581 	case 'H':
    582 		ifo->options |= DHCPCD_XID_HWADDR;
    583 		break;
    584 	case 'I':
    585 		/* Strings have a type of 0 */;
    586 		ifo->clientid[1] = 0;
    587 		if (arg)
    588 			s = parse_string_hwaddr((char *)ifo->clientid + 1,
    589 			    CLIENTID_MAX_LEN, arg, 1);
    590 		else
    591 			s = 0;
    592 		if (s == -1) {
    593 			syslog(LOG_ERR, "clientid: %m");
    594 			return -1;
    595 		}
    596 		ifo->options |= DHCPCD_CLIENTID;
    597 		ifo->clientid[0] = (uint8_t)s;
    598 		break;
    599 	case 'J':
    600 		ifo->options |= DHCPCD_BROADCAST;
    601 		break;
    602 	case 'K':
    603 		ifo->options &= ~DHCPCD_LINK;
    604 		break;
    605 	case 'L':
    606 		ifo->options &= ~DHCPCD_IPV4LL;
    607 		break;
    608 	case 'O':
    609 		if (make_option_mask(ifo->requestmask, arg, -1) != 0 ||
    610 		    make_option_mask(ifo->requiremask, arg, -1) != 0 ||
    611 		    make_option_mask(ifo->nomask, arg, 1) != 0)
    612 		{
    613 			syslog(LOG_ERR, "unknown option `%s'", arg);
    614 			return -1;
    615 		}
    616 		break;
    617 	case 'Q':
    618 		if (make_option_mask(ifo->requiremask, arg, 1) != 0 ||
    619 		    make_option_mask(ifo->requestmask, arg, 1) != 0)
    620 		{
    621 			syslog(LOG_ERR, "unknown option `%s'", arg);
    622 			return -1;
    623 		}
    624 		break;
    625 	case 'S':
    626 		p = strchr(arg, '=');
    627 		if (p == NULL) {
    628 			syslog(LOG_ERR, "static assignment required");
    629 			return -1;
    630 		}
    631 		p++;
    632 		if (strncmp(arg, "ip_address=", strlen("ip_address=")) == 0) {
    633 			if (parse_addr(&ifo->req_addr,
    634 			    ifo->req_mask.s_addr == 0 ? &ifo->req_mask : NULL,
    635 			    p) != 0)
    636 				return -1;
    637 
    638 			ifo->options |= DHCPCD_STATIC;
    639 			ifo->options &= ~DHCPCD_INFORM;
    640 		} else if (strncmp(arg, "subnet_mask=", strlen("subnet_mask=")) == 0) {
    641 			if (parse_addr(&ifo->req_mask, NULL, p) != 0)
    642 				return -1;
    643 		} else if (strncmp(arg, "routes=", strlen("routes=")) == 0 ||
    644 		    strncmp(arg, "static_routes=", strlen("static_routes=")) == 0 ||
    645 		    strncmp(arg, "classless_static_routes=", strlen("classless_static_routes=")) == 0 ||
    646 		    strncmp(arg, "ms_classless_static_routes=", strlen("ms_classless_static_routes=")) == 0)
    647 		{
    648 			np = strchr(p, ' ');
    649 			if (np == NULL) {
    650 				syslog(LOG_ERR, "all routes need a gateway");
    651 				return -1;
    652 			}
    653 			*np++ = '\0';
    654 			while (*np == ' ')
    655 				np++;
    656 			if (ifo->routes == NULL) {
    657 				rt = ifo->routes = xmalloc(sizeof(*rt));
    658 			} else {
    659 				rt = ifo->routes;
    660 				while (rt->next)
    661 					rt = rt->next;
    662 				rt->next = xmalloc(sizeof(*rt));
    663 				rt = rt->next;
    664 			}
    665 			rt->next = NULL;
    666 			if (parse_addr(&rt->dest, &rt->net, p) == -1 ||
    667 			    parse_addr(&rt->gate, NULL, np) == -1)
    668 				return -1;
    669 		} else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
    670 			if (ifo->routes == NULL) {
    671 				rt = ifo->routes = xzalloc(sizeof(*rt));
    672 			} else {
    673 				rt = ifo->routes;
    674 				while (rt->next)
    675 					rt = rt->next;
    676 				rt->next = xmalloc(sizeof(*rt));
    677 				rt = rt->next;
    678 			}
    679 			rt->dest.s_addr = INADDR_ANY;
    680 			rt->net.s_addr = INADDR_ANY;
    681 			rt->next = NULL;
    682 			if (parse_addr(&rt->gate, NULL, p) == -1)
    683 				return -1;
    684 		} else {
    685 			s = 0;
    686 			if (ifo->config != NULL) {
    687 				while (ifo->config[s] != NULL) {
    688 					if (strncmp(ifo->config[s], arg,
    689 						p - arg) == 0)
    690 					{
    691 						free(ifo->config[s]);
    692 						ifo->config[s] = xstrdup(arg);
    693 						return 1;
    694 					}
    695 					s++;
    696 				}
    697 			}
    698 			ifo->config = xrealloc(ifo->config,
    699 			    sizeof(char *) * (s + 2));
    700 			ifo->config[s] = xstrdup(arg);
    701 			ifo->config[s + 1] = NULL;
    702 		}
    703 		break;
    704 	case 'W':
    705 		if (parse_addr(&addr, &addr2, arg) != 0)
    706 			return -1;
    707 		if (strchr(arg, '/') == NULL)
    708 			addr2.s_addr = INADDR_BROADCAST;
    709 		ifo->whitelist = xrealloc(ifo->whitelist,
    710 		    sizeof(in_addr_t) * (ifo->whitelist_len + 2));
    711 		ifo->whitelist[ifo->whitelist_len++] = addr.s_addr;
    712 		ifo->whitelist[ifo->whitelist_len++] = addr2.s_addr;
    713 		break;
    714 	case 'X':
    715 		if (parse_addr(&addr, &addr2, arg) != 0)
    716 			return -1;
    717 		if (strchr(arg, '/') == NULL)
    718 			addr2.s_addr = INADDR_BROADCAST;
    719 		ifo->blacklist = xrealloc(ifo->blacklist,
    720 		    sizeof(in_addr_t) * (ifo->blacklist_len + 2));
    721 		ifo->blacklist[ifo->blacklist_len++] = addr.s_addr;
    722 		ifo->blacklist[ifo->blacklist_len++] = addr2.s_addr;
    723 		break;
    724 	case 'Z':
    725 		ifdv = splitv(&ifdc, ifdv, arg);
    726 		break;
    727 	case O_ARPING:
    728 		if (parse_addr(&addr, NULL, arg) != 0)
    729 			return -1;
    730 		ifo->arping = xrealloc(ifo->arping,
    731 		    sizeof(in_addr_t) * (ifo->arping_len + 1));
    732 		ifo->arping[ifo->arping_len++] = addr.s_addr;
    733 		break;
    734 	case O_DESTINATION:
    735 		if (make_option_mask(ifo->dstmask, arg, 2) != 0) {
    736 			if (errno == EINVAL)
    737 				syslog(LOG_ERR, "option `%s' does not take"
    738 				    " an IPv4 address", arg);
    739 			else
    740 				syslog(LOG_ERR, "unknown option `%s'", arg);
    741 			return -1;
    742 		}
    743 		break;
    744 	case O_FALLBACK:
    745 		free(ifo->fallback);
    746 		ifo->fallback = xstrdup(arg);
    747 		break;
    748 	case O_NOIPV6RS:
    749 		ifo->options &= ~DHCPCD_IPV6RS;
    750 		break;
    751 	case O_IPV6_RA_FORK:
    752 		ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS;
    753 		break;
    754 	default:
    755 		return 0;
    756 	}
    757 
    758 	return 1;
    759 }
    760 
    761 static int
    762 parse_config_line(struct if_options *ifo, const char *opt, char *line)
    763 {
    764 	unsigned int i;
    765 
    766 	for (i = 0; i < sizeof(cf_options) / sizeof(cf_options[0]); i++) {
    767 		if (!cf_options[i].name ||
    768 		    strcmp(cf_options[i].name, opt) != 0)
    769 			continue;
    770 
    771 		if (cf_options[i].has_arg == required_argument && !line) {
    772 			fprintf(stderr,
    773 			    PACKAGE ": option requires an argument -- %s\n",
    774 			    opt);
    775 			return -1;
    776 		}
    777 
    778 		return parse_option(ifo, cf_options[i].val, line);
    779 	}
    780 
    781 	fprintf(stderr, PACKAGE ": unknown option -- %s\n", opt);
    782 	return -1;
    783 }
    784 
    785 struct if_options *
    786 read_config(const char *file,
    787     const char *ifname, const char *ssid, const char *profile)
    788 {
    789 	struct if_options *ifo;
    790 	FILE *f;
    791 	char *line, *option, *p, *platform;
    792 	int skip = 0, have_profile = 0;
    793 	struct utsname utn;
    794 
    795 	/* Seed our default options */
    796 	ifo = xzalloc(sizeof(*ifo));
    797 	ifo->options |= DHCPCD_GATEWAY | DHCPCD_DAEMONISE | DHCPCD_LINK;
    798 	ifo->options |= DHCPCD_ARP | DHCPCD_IPV4LL;
    799 	ifo->options |= DHCPCD_IPV6RS | DHCPCD_IPV6RA_REQRDNSS;
    800 	ifo->timeout = DEFAULT_TIMEOUT;
    801 	ifo->reboot = DEFAULT_REBOOT;
    802 	ifo->metric = -1;
    803 	strlcpy(ifo->script, SCRIPT, sizeof(ifo->script));
    804 	gethostname(ifo->hostname, HOSTNAME_MAX_LEN);
    805 	/* Ensure that the hostname is NULL terminated */
    806 	ifo->hostname[HOSTNAME_MAX_LEN] = '\0';
    807 	if (strcmp(ifo->hostname, "(none)") == 0 ||
    808 	    strcmp(ifo->hostname, "localhost") == 0)
    809 		ifo->hostname[0] = '\0';
    810 
    811 	platform = hardware_platform();
    812 #ifndef ANDROID
    813 	if (uname(&utn) == 0)
    814 		ifo->vendorclassid[0] = snprintf((char *)ifo->vendorclassid + 1,
    815 		    VENDORCLASSID_MAX_LEN,
    816 	            "%s-%s:%s-%s:%s%s%s", PACKAGE, VERSION,
    817 		    utn.sysname, utn.release, utn.machine,
    818 		    platform ? ":" : "", platform ? platform : "");
    819 	else
    820 #endif
    821 		ifo->vendorclassid[0] = snprintf((char *)ifo->vendorclassid + 1,
    822 		    VENDORCLASSID_MAX_LEN, "%s-%s", PACKAGE, VERSION);
    823 
    824 	/* Parse our options file */
    825 	f = fopen(file ? file : CONFIG, "r");
    826 	if (f == NULL) {
    827 		if (file != NULL)
    828 			syslog(LOG_ERR, "fopen `%s': %m", file);
    829 		return ifo;
    830 	}
    831 
    832 	while ((line = get_line(f))) {
    833 		option = strsep(&line, " \t");
    834 		/* Trim trailing whitespace */
    835 		if (line && *line) {
    836 			p = line + strlen(line) - 1;
    837 			while (p != line &&
    838 			    (*p == ' ' || *p == '\t') &&
    839 			    *(p - 1) != '\\')
    840 				*p-- = '\0';
    841 		}
    842 		/* Start of an interface block, skip if not ours */
    843 		if (strcmp(option, "interface") == 0) {
    844 			if (ifname && line && strcmp(line, ifname) == 0)
    845 				skip = 0;
    846 			else
    847 				skip = 1;
    848 			continue;
    849 		}
    850 		/* Start of an ssid block, skip if not ours */
    851 		if (strcmp(option, "ssid") == 0) {
    852 			if (ssid && line && strcmp(line, ssid) == 0)
    853 				skip = 0;
    854 			else
    855 				skip = 1;
    856 			continue;
    857 		}
    858 		/* Start of a profile block, skip if not ours */
    859 		if (strcmp(option, "profile") == 0) {
    860 			if (profile && line && strcmp(line, profile) == 0) {
    861 				skip = 0;
    862 				have_profile = 1;
    863 			} else
    864 				skip = 1;
    865 			continue;
    866 		}
    867 		if (skip)
    868 			continue;
    869 		parse_config_line(ifo, option, line);
    870 	}
    871 	fclose(f);
    872 
    873 	if (profile && !have_profile) {
    874 		free_options(ifo);
    875 		errno = ENOENT;
    876 		ifo = NULL;
    877 	}
    878 
    879 	/* Terminate the encapsulated options */
    880 	if (ifo && ifo->vendor[0] && !(ifo->options & DHCPCD_VENDORRAW)) {
    881 		ifo->vendor[0]++;
    882 		ifo->vendor[ifo->vendor[0]] = DHO_END;
    883 	}
    884 	return ifo;
    885 }
    886 
    887 int
    888 add_options(struct if_options *ifo, int argc, char **argv)
    889 {
    890 	int oi, opt, r = 1;
    891 
    892 	optind = 0;
    893 	while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
    894 	{
    895 		r = parse_option(ifo, opt, optarg);
    896 		if (r != 1)
    897 			break;
    898 	}
    899 	/* Terminate the encapsulated options */
    900 	if (r == 1 && ifo->vendor[0] && !(ifo->options & DHCPCD_VENDORRAW)) {
    901 		ifo->vendor[0]++;
    902 		ifo->vendor[ifo->vendor[0]] = DHO_END;
    903 	}
    904 	return r;
    905 }
    906 
    907 void
    908 free_options(struct if_options *ifo)
    909 {
    910 	size_t i;
    911 
    912 	if (ifo) {
    913 		if (ifo->environ) {
    914 			i = 0;
    915 			while (ifo->environ[i])
    916 				free(ifo->environ[i++]);
    917 			free(ifo->environ);
    918 		}
    919 		if (ifo->config) {
    920 			i = 0;
    921 			while (ifo->config[i])
    922 				free(ifo->config[i++]);
    923 			free(ifo->config);
    924 		}
    925 		free_routes(ifo->routes);
    926 		free(ifo->arping);
    927 		free(ifo->blacklist);
    928 		free(ifo->fallback);
    929 		free(ifo);
    930 	}
    931 }
    932