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