]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/option.c
More DNSSEC caching logic, and avoid repeated validation of DS/DNSKEY
[people/ms/dnsmasq.git] / src / option.c
CommitLineData
c47e3ba4 1/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
9e4abcb5
SK
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
824af85b
SK
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
9e4abcb5
SK
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
824af85b 12
73a08a24
SK
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
9e4abcb5
SK
15*/
16
849a8357
SK
17/* define this to get facilitynames */
18#define SYSLOG_NAMES
9e4abcb5 19#include "dnsmasq.h"
824af85b
SK
20#include <setjmp.h>
21
7622fc06
SK
22static volatile int mem_recover = 0;
23static jmp_buf mem_jmp;
395eb719 24static int one_file(char *file, int hard_opt);
7622fc06 25
824af85b
SK
26/* Solaris headers don't have facility names. */
27#ifdef HAVE_SOLARIS_NETWORK
28static const struct {
29 char *c_name;
30 unsigned int c_val;
31} facilitynames[] = {
32 { "kern", LOG_KERN },
33 { "user", LOG_USER },
34 { "mail", LOG_MAIL },
35 { "daemon", LOG_DAEMON },
36 { "auth", LOG_AUTH },
37 { "syslog", LOG_SYSLOG },
38 { "lpr", LOG_LPR },
39 { "news", LOG_NEWS },
40 { "uucp", LOG_UUCP },
824af85b 41 { "audit", LOG_AUDIT },
824af85b
SK
42 { "cron", LOG_CRON },
43 { "local0", LOG_LOCAL0 },
44 { "local1", LOG_LOCAL1 },
45 { "local2", LOG_LOCAL2 },
46 { "local3", LOG_LOCAL3 },
47 { "local4", LOG_LOCAL4 },
48 { "local5", LOG_LOCAL5 },
49 { "local6", LOG_LOCAL6 },
50 { "local7", LOG_LOCAL7 },
51 { NULL, 0 }
52};
53#endif
9e4abcb5 54
849a8357 55#ifndef HAVE_GETOPT_LONG
9e4abcb5
SK
56struct myoption {
57 const char *name;
58 int has_arg;
59 int *flag;
60 int val;
61};
849a8357 62#endif
9e4abcb5 63
9009d746 64#define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
9e4abcb5 65
1697269c 66/* options which don't have a one-char version */
8c0b73d3
KDB
67#define LOPT_RELOAD 256
68#define LOPT_NO_NAMES 257
69#define LOPT_TFTP 258
70#define LOPT_SECURE 259
71#define LOPT_PREFIX 260
72#define LOPT_PTR 261
73#define LOPT_BRIDGE 262
74#define LOPT_TFTP_MAX 263
75#define LOPT_FORCE 264
76#define LOPT_NOBLOCK 265
77#define LOPT_LOG_OPTS 266
78#define LOPT_MAX_LOGS 267
79#define LOPT_CIRCUIT 268
80#define LOPT_REMOTE 269
81#define LOPT_SUBSCR 270
82#define LOPT_INTNAME 271
83#define LOPT_BANK 272
84#define LOPT_DHCP_HOST 273
85#define LOPT_APREF 274
86#define LOPT_OVERRIDE 275
87#define LOPT_TFTPPORTS 276
88#define LOPT_REBIND 277
89#define LOPT_NOLAST 278
90#define LOPT_OPTS 279
91#define LOPT_DHCP_OPTS 280
92#define LOPT_MATCH 281
93#define LOPT_BROADCAST 282
94#define LOPT_NEGTTL 283
95#define LOPT_ALTPORT 284
96#define LOPT_SCRIPTUSR 285
97#define LOPT_LOCAL 286
98#define LOPT_NAPTR 287
99#define LOPT_MINPORT 288
100#define LOPT_DHCP_FQDN 289
101#define LOPT_CNAME 290
102#define LOPT_PXE_PROMT 291
103#define LOPT_PXE_SERV 292
104#define LOPT_TEST 293
105#define LOPT_TAG_IF 294
106#define LOPT_PROXY 295
107#define LOPT_GEN_NAMES 296
108#define LOPT_MAXTTL 297
109#define LOPT_NO_REBIND 298
110#define LOPT_LOC_REBND 299
111#define LOPT_ADD_MAC 300
112#define LOPT_DNSSEC 301
113#define LOPT_INCR_ADDR 302
114#define LOPT_CONNTRACK 303
115#define LOPT_FQDN 304
116#define LOPT_LUASCRIPT 305
117#define LOPT_RA 306
118#define LOPT_DUID 307
119#define LOPT_HOST_REC 308
120#define LOPT_TFTP_LC 309
121#define LOPT_RR 310
122#define LOPT_CLVERBIND 311
123#define LOPT_MAXCTTL 312
124#define LOPT_AUTHZONE 313
125#define LOPT_AUTHSERV 314
126#define LOPT_AUTHTTL 315
127#define LOPT_AUTHSOA 316
128#define LOPT_AUTHSFS 317
129#define LOPT_AUTHPEER 318
130#define LOPT_IPSET 319
131#define LOPT_SYNTH 320
c630924d 132#ifdef OPTION6_PREFIX_CLASS
8c0b73d3 133#define LOPT_PREF_CLSS 321
c630924d 134#endif
8c0b73d3
KDB
135#define LOPT_RELAY 323
136#define LOPT_RA_PARAM 324
137#define LOPT_ADD_SBNET 325
138#define LOPT_QUIET_DHCP 326
139#define LOPT_QUIET_DHCP6 327
140#define LOPT_QUIET_RA 328
5a4120db 141#define LOPT_SEC_VALID 329
0fc2f313 142#define LOPT_DNSKEY 330
a25720a3 143#define LOPT_DNSSEC_PERM 331
7dbe193b 144
849a8357
SK
145#ifdef HAVE_GETOPT_LONG
146static const struct option opts[] =
147#else
148static const struct myoption opts[] =
149#endif
150 {
7622fc06
SK
151 { "version", 0, 0, 'v' },
152 { "no-hosts", 0, 0, 'h' },
153 { "no-poll", 0, 0, 'n' },
154 { "help", 0, 0, 'w' },
155 { "no-daemon", 0, 0, 'd' },
156 { "log-queries", 0, 0, 'q' },
157 { "user", 2, 0, 'u' },
158 { "group", 2, 0, 'g' },
159 { "resolv-file", 2, 0, 'r' },
160 { "mx-host", 1, 0, 'm' },
161 { "mx-target", 1, 0, 't' },
162 { "cache-size", 2, 0, 'c' },
163 { "port", 1, 0, 'p' },
164 { "dhcp-leasefile", 2, 0, 'l' },
165 { "dhcp-lease", 1, 0, 'l' },
166 { "dhcp-host", 1, 0, 'G' },
167 { "dhcp-range", 1, 0, 'F' },
168 { "dhcp-option", 1, 0, 'O' },
169 { "dhcp-boot", 1, 0, 'M' },
170 { "domain", 1, 0, 's' },
171 { "domain-suffix", 1, 0, 's' },
172 { "interface", 1, 0, 'i' },
173 { "listen-address", 1, 0, 'a' },
174 { "bogus-priv", 0, 0, 'b' },
175 { "bogus-nxdomain", 1, 0, 'B' },
176 { "selfmx", 0, 0, 'e' },
177 { "filterwin2k", 0, 0, 'f' },
178 { "pid-file", 2, 0, 'x' },
179 { "strict-order", 0, 0, 'o' },
180 { "server", 1, 0, 'S' },
181 { "local", 1, 0, LOPT_LOCAL },
182 { "address", 1, 0, 'A' },
183 { "conf-file", 2, 0, 'C' },
184 { "no-resolv", 0, 0, 'R' },
185 { "expand-hosts", 0, 0, 'E' },
186 { "localmx", 0, 0, 'L' },
187 { "local-ttl", 1, 0, 'T' },
188 { "no-negcache", 0, 0, 'N' },
189 { "addn-hosts", 1, 0, 'H' },
190 { "query-port", 1, 0, 'Q' },
191 { "except-interface", 1, 0, 'I' },
192 { "no-dhcp-interface", 1, 0, '2' },
193 { "domain-needed", 0, 0, 'D' },
194 { "dhcp-lease-max", 1, 0, 'X' },
195 { "bind-interfaces", 0, 0, 'z' },
196 { "read-ethers", 0, 0, 'Z' },
197 { "alias", 1, 0, 'V' },
198 { "dhcp-vendorclass", 1, 0, 'U' },
199 { "dhcp-userclass", 1, 0, 'j' },
200 { "dhcp-ignore", 1, 0, 'J' },
201 { "edns-packet-max", 1, 0, 'P' },
202 { "keep-in-foreground", 0, 0, 'k' },
203 { "dhcp-authoritative", 0, 0, 'K' },
204 { "srv-host", 1, 0, 'W' },
205 { "localise-queries", 0, 0, 'y' },
206 { "txt-record", 1, 0, 'Y' },
9f7f3b12 207 { "dns-rr", 1, 0, LOPT_RR },
ad094275 208 { "enable-dbus", 2, 0, '1' },
7622fc06
SK
209 { "bootp-dynamic", 2, 0, '3' },
210 { "dhcp-mac", 1, 0, '4' },
211 { "no-ping", 0, 0, '5' },
212 { "dhcp-script", 1, 0, '6' },
213 { "conf-dir", 1, 0, '7' },
214 { "log-facility", 1, 0 ,'8' },
215 { "leasefile-ro", 0, 0, '9' },
216 { "dns-forward-max", 1, 0, '0' },
217 { "clear-on-reload", 0, 0, LOPT_RELOAD },
218 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
2937f8a0 219 { "enable-tftp", 2, 0, LOPT_TFTP },
7622fc06
SK
220 { "tftp-secure", 0, 0, LOPT_SECURE },
221 { "tftp-unique-root", 0, 0, LOPT_APREF },
222 { "tftp-root", 1, 0, LOPT_PREFIX },
223 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
61ce600b 224 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
7622fc06
SK
225 { "ptr-record", 1, 0, LOPT_PTR },
226 { "naptr-record", 1, 0, LOPT_NAPTR },
227 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
228 { "dhcp-option-force", 1, 0, LOPT_FORCE },
229 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
230 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
231 { "log-async", 2, 0, LOPT_MAX_LOGS },
232 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
233 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
234 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
235 { "interface-name", 1, 0, LOPT_INTNAME },
236 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
237 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
238 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
239 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
240 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
8ef5ada2 241 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
7622fc06
SK
242 { "all-servers", 0, 0, LOPT_NOLAST },
243 { "dhcp-match", 1, 0, LOPT_MATCH },
8ef5ada2 244 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
7622fc06 245 { "neg-ttl", 1, 0, LOPT_NEGTTL },
8ef5ada2 246 { "max-ttl", 1, 0, LOPT_MAXTTL },
1d860415 247 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
7622fc06
SK
248 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
249 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
250 { "min-port", 1, 0, LOPT_MINPORT },
251 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
252 { "cname", 1, 0, LOPT_CNAME },
253 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
254 { "pxe-service", 1, 0, LOPT_PXE_SERV },
255 { "test", 0, 0, LOPT_TEST },
8ef5ada2
SK
256 { "tag-if", 1, 0, LOPT_TAG_IF },
257 { "dhcp-proxy", 2, 0, LOPT_PROXY },
258 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
259 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
28866e95 260 { "add-mac", 0, 0, LOPT_ADD_MAC },
ed4c0767 261 { "add-subnet", 2, 0, LOPT_ADD_SBNET },
28866e95 262 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
7de060b0
SK
263 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
264 { "conntrack", 0, 0, LOPT_CONNTRACK },
c72daea8
SK
265 { "dhcp-client-update", 0, 0, LOPT_FQDN },
266 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
c5ad4e79 267 { "enable-ra", 0, 0, LOPT_RA },
8b372704 268 { "dhcp-duid", 1, 0, LOPT_DUID },
e759d426 269 { "host-record", 1, 0, LOPT_HOST_REC },
54dd393f 270 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
4f7b304f
SK
271 { "auth-zone", 1, 0, LOPT_AUTHZONE },
272 { "auth-server", 1, 0, LOPT_AUTHSERV },
273 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
274 { "auth-soa", 1, 0, LOPT_AUTHSOA },
e1ff419c 275 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
49678767 276 { "auth-peer", 1, 0, LOPT_AUTHPEER },
13d86c73 277 { "ipset", 1, 0, LOPT_IPSET },
2bb73af7 278 { "synth-domain", 1, 0, LOPT_SYNTH },
7dbe193b 279 { "dnssec", 0, 0, LOPT_SEC_VALID },
0fc2f313 280 { "dnskey", 1, 0, LOPT_DNSKEY },
a25720a3 281 { "dnssec-permissive", 0, 0, LOPT_DNSSEC_PERM },
c630924d
SK
282#ifdef OPTION6_PREFIX_CLASS
283 { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
284#endif
ff7eea27 285 { "dhcp-relay", 1, 0, LOPT_RELAY },
c4cd95df 286 { "ra-param", 1, 0, LOPT_RA_PARAM },
8c0b73d3
KDB
287 { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
288 { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
289 { "quiet-ra", 0, 0, LOPT_QUIET_RA },
849a8357
SK
290 { NULL, 0, 0, 0 }
291 };
9e4abcb5 292
28866e95
SK
293
294#define ARG_DUP OPT_LAST
295#define ARG_ONE OPT_LAST + 1
296#define ARG_USED_CL OPT_LAST + 2
297#define ARG_USED_FILE OPT_LAST + 3
9e4abcb5 298
1a6bca81
SK
299static struct {
300 int opt;
301 unsigned int rept;
302 char * const flagdesc;
b8187c80
SK
303 char * const desc;
304 char * const arg;
305} usage[] = {
8ecfaa4a
SK
306 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
307 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
1a6bca81 308 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
8ecfaa4a
SK
309 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
310 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
311 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
1a6bca81
SK
312 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
313 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
314 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
315 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
316 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
8ecfaa4a
SK
317 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
318 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
1a6bca81 319 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
8ecfaa4a
SK
320 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
321 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
8ef5ada2 322 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
1a6bca81 323 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
8ecfaa4a
SK
324 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
325 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
326 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
8ef5ada2
SK
327 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
328 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
329 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
330 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
331 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
332 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
1a6bca81
SK
333 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
334 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
8ecfaa4a 335 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
1a6bca81 336 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
8ecfaa4a 337 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
1a6bca81
SK
338 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
339 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
340 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
341 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
342 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
343 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
8ecfaa4a
SK
344 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
345 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
1a6bca81 346 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
8ecfaa4a 347 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
1a6bca81 348 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
8ecfaa4a
SK
349 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
350 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
351 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
9009d746 352 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
8ecfaa4a
SK
353 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
354 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
355 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
356 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
357 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
8ef5ada2 358 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
1a6bca81 359 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
8ecfaa4a
SK
360 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
361 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
1a6bca81 362 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
8ecfaa4a
SK
363 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
364 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
1a6bca81 365 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
8ecfaa4a
SK
366 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
367 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
368 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
1a6bca81
SK
369 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
370 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
ad094275 371 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
8ecfaa4a 372 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
8ef5ada2
SK
373 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
374 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
8ecfaa4a 375 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
1a6bca81 376 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
8ecfaa4a
SK
377 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
378 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
379 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
380 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
1a6bca81
SK
381 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
382 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
8ecfaa4a 383 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
1a6bca81 384 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
8ef5ada2 385 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
1a6bca81 386 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
2937f8a0 387 { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
8b3ae2fd 388 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
1a6bca81
SK
389 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
390 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
8ecfaa4a 391 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
1a6bca81 392 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
61ce600b 393 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
1a6bca81
SK
394 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
395 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
8ecfaa4a 396 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
1a6bca81 397 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
8ef5ada2 398 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
8ecfaa4a 399 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
1a6bca81 400 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
8ef5ada2 401 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
1a6bca81 402 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
1a6bca81
SK
403 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
404 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
9009d746 405 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
8ecfaa4a
SK
406 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
407 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
ff7eea27 408 { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
9009d746 409 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
7622fc06
SK
410 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
411 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
412 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
7de060b0 413 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
ed4c0767 414 { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL },
5a4120db 415 { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
7de060b0
SK
416 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
417 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
c72daea8 418 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
c5ad4e79 419 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
8b372704 420 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
e759d426 421 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
9f7f3b12 422 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
4f7b304f 423 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
86e3b9a0 424 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
333b2ceb 425 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
4f7b304f
SK
426 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
427 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
49678767
SK
428 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
429 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
13d86c73 430 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
a9bf81ad 431 { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
3a237152 432 { LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
0fc2f313 433 { LOPT_DNSKEY, ARG_DUP, "<domain>,<algo>,<key>", gettext_noop("Specify trust anchor DNSKEY"), NULL },
a25720a3 434 { LOPT_DNSSEC_PERM, OPT_DNSSEC_PERMISS, NULL, gettext_noop("Do NOT return SERVFAIL whne DNSSEC validation fails."), NULL },
c630924d
SK
435#ifdef OPTION6_PREFIX_CLASS
436 { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
437#endif
c4cd95df 438 { LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
8c0b73d3
KDB
439 { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
440 { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
441 { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
1a6bca81 442 { 0, 0, NULL, NULL, NULL }
b8187c80 443};
9e4abcb5 444
3d8df260 445/* We hide metacharaters in quoted strings by mapping them into the ASCII control
f2621c7f 446 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
3d8df260
SK
447 following sequence so that they map to themselves: it is therefore possible to call
448 unhide_metas repeatedly on string without breaking things.
824af85b 449 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
f2621c7f
SK
450 couple of other places.
451 Note that space is included here so that
452 --dhcp-option=3, string
453 has five characters, whilst
454 --dhcp-option=3," string"
455 has six.
456*/
3d8df260 457
f2621c7f 458static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
3d8df260
SK
459
460static char hide_meta(char c)
461{
462 unsigned int i;
463
464 for (i = 0; i < (sizeof(meta) - 1); i++)
465 if (c == meta[i])
466 return (char)i;
467
468 return c;
469}
470
471static char unhide_meta(char cr)
472{
473 unsigned int c = cr;
474
475 if (c < (sizeof(meta) - 1))
476 cr = meta[c];
477
478 return cr;
479}
480
481static void unhide_metas(char *cp)
482{
483 if (cp)
484 for(; *cp; cp++)
485 *cp = unhide_meta(*cp);
486}
487
824af85b
SK
488static void *opt_malloc(size_t size)
489{
490 void *ret;
491
492 if (mem_recover)
493 {
494 ret = whine_malloc(size);
495 if (!ret)
496 longjmp(mem_jmp, 1);
497 }
498 else
499 ret = safe_malloc(size);
500
501 return ret;
502}
503
504static char *opt_string_alloc(char *cp)
3d8df260
SK
505{
506 char *ret = NULL;
507
508 if (cp && strlen(cp) != 0)
509 {
824af85b 510 ret = opt_malloc(strlen(cp)+1);
3d8df260
SK
511 strcpy(ret, cp);
512
513 /* restore hidden metachars */
514 unhide_metas(ret);
515 }
516
517 return ret;
518}
519
f2621c7f
SK
520
521/* find next comma, split string with zero and eliminate spaces.
522 return start of string following comma */
73a08a24
SK
523
524static char *split_chr(char *s, char c)
3d8df260 525{
f2621c7f 526 char *comma, *p;
3d8df260 527
73a08a24 528 if (!s || !(comma = strchr(s, c)))
f2621c7f
SK
529 return NULL;
530
531 p = comma;
532 *comma = ' ';
533
8ef5ada2 534 for (; *comma == ' '; comma++);
f2621c7f 535
8ef5ada2 536 for (; (p >= s) && *p == ' '; p--)
f2621c7f
SK
537 *p = 0;
538
539 return comma;
3d8df260
SK
540}
541
73a08a24
SK
542static char *split(char *s)
543{
544 return split_chr(s, ',');
545}
546
1f15b81d 547static char *canonicalise_opt(char *s)
3d8df260 548{
1f15b81d
SK
549 char *ret;
550 int nomem;
551
3d8df260
SK
552 if (!s)
553 return 0;
554
555 unhide_metas(s);
1f15b81d
SK
556 if (!(ret = canonicalise(s, &nomem)) && nomem)
557 {
558 if (mem_recover)
559 longjmp(mem_jmp, 1);
560 else
561 die(_("could not get memory"), NULL, EC_NOMEM);
562 }
563
564 return ret;
3d8df260
SK
565}
566
567static int atoi_check(char *a, int *res)
568{
569 char *p;
570
571 if (!a)
572 return 0;
573
574 unhide_metas(a);
575
576 for (p = a; *p; p++)
577 if (*p < '0' || *p > '9')
578 return 0;
579
580 *res = atoi(a);
581 return 1;
582}
583
1ad24ae1
SK
584static int atoi_check16(char *a, int *res)
585{
586 if (!(atoi_check(a, res)) ||
587 *res < 0 ||
588 *res > 0xffff)
589 return 0;
590
591 return 1;
592}
593
5aabfc78 594static void add_txt(char *name, char *txt)
0a852541
SK
595{
596 size_t len = strlen(txt);
824af85b 597 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
0a852541 598
824af85b 599 r->name = opt_string_alloc(name);
0a852541
SK
600 r->next = daemon->txt;
601 daemon->txt = r;
602 r->class = C_CHAOS;
824af85b 603 r->txt = opt_malloc(len+1);
0a852541
SK
604 r->len = len+1;
605 *(r->txt) = len;
606 memcpy((r->txt)+1, txt, len);
607}
9e4abcb5 608
849a8357 609static void do_usage(void)
9e4abcb5 610{
849a8357 611 char buff[100];
832af0ba
SK
612 int i, j;
613
614 struct {
615 char handle;
616 int val;
617 } tab[] = {
618 { '$', CACHESIZ },
619 { '*', EDNS_PKTSZ },
620 { '&', MAXLEASES },
621 { '!', FTABSIZ },
622 { '#', TFTP_MAX_CONNECTIONS },
623 { '\0', 0 }
624 };
0a852541 625
849a8357
SK
626 printf(_("Usage: dnsmasq [options]\n\n"));
627#ifndef HAVE_GETOPT_LONG
628 printf(_("Use short options only on the command line.\n"));
629#endif
1a6bca81 630 printf(_("Valid options are:\n"));
3be34541 631
1a6bca81 632 for (i = 0; usage[i].opt != 0; i++)
9e4abcb5 633 {
1a6bca81
SK
634 char *desc = usage[i].flagdesc;
635 char *eq = "=";
636
637 if (!desc || *desc == '[')
638 eq = "";
639
640 if (!desc)
641 desc = "";
642
643 for ( j = 0; opts[j].name; j++)
644 if (opts[j].val == usage[i].opt)
645 break;
646 if (usage[i].opt < 256)
647 sprintf(buff, "-%c, ", usage[i].opt);
648 else
649 sprintf(buff, " ");
650
651 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
8ef5ada2 652 printf("%-40.40s", buff);
1a6bca81 653
849a8357 654 if (usage[i].arg)
0a852541 655 {
832af0ba
SK
656 strcpy(buff, usage[i].arg);
657 for (j = 0; tab[j].handle; j++)
658 if (tab[j].handle == *(usage[i].arg))
659 sprintf(buff, "%d", tab[j].val);
0a852541 660 }
849a8357
SK
661 printf(_(usage[i].desc), buff);
662 printf("\n");
663 }
664}
0a852541 665
c740e4f3
SK
666#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
667
faafb3f7
SK
668char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
669{
670 int source_port = 0, serv_port = NAMESERVER_PORT;
671 char *portno, *source;
672#ifdef HAVE_IPV6
673 int scope_index = 0;
674 char *scope_id;
675#endif
676
677 if ((source = split_chr(arg, '@')) && /* is there a source. */
678 (portno = split_chr(source, '#')) &&
679 !atoi_check16(portno, &source_port))
680 return _("bad port");
681
682 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
683 !atoi_check16(portno, &serv_port))
684 return _("bad port");
685
686#ifdef HAVE_IPV6
687 scope_id = split_chr(arg, '%');
688#endif
689
ddd9a6b4 690 if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
faafb3f7
SK
691 {
692 addr->in.sin_port = htons(serv_port);
693 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
694#ifdef HAVE_SOCKADDR_SA_LEN
695 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
696#endif
697 source_addr->in.sin_addr.s_addr = INADDR_ANY;
698 source_addr->in.sin_port = htons(daemon->query_port);
699
700 if (source)
701 {
702 if (flags)
703 *flags |= SERV_HAS_SOURCE;
704 source_addr->in.sin_port = htons(source_port);
ddd9a6b4 705 if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
faafb3f7
SK
706 {
707#if defined(SO_BINDTODEVICE)
708 source_addr->in.sin_addr.s_addr = INADDR_ANY;
709 strncpy(interface, source, IF_NAMESIZE - 1);
710#else
711 return _("interface binding not supported");
712#endif
713 }
714 }
715 }
716#ifdef HAVE_IPV6
717 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
718 {
719 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
720 return _("bad interface name");
721
722 addr->in6.sin6_port = htons(serv_port);
723 addr->in6.sin6_scope_id = scope_index;
724 source_addr->in6.sin6_addr = in6addr_any;
725 source_addr->in6.sin6_port = htons(daemon->query_port);
726 source_addr->in6.sin6_scope_id = 0;
727 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
728 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
729#ifdef HAVE_SOCKADDR_SA_LEN
730 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
731#endif
732 if (source)
733 {
734 if (flags)
735 *flags |= SERV_HAS_SOURCE;
736 source_addr->in6.sin6_port = htons(source_port);
737 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
738 {
739#if defined(SO_BINDTODEVICE)
740 source_addr->in6.sin6_addr = in6addr_any;
741 strncpy(interface, source, IF_NAMESIZE - 1);
742#else
743 return _("interface binding not supported");
744#endif
745 }
746 }
747 }
748#endif
749 else
750 return _("bad address");
751
752 return NULL;
753}
754
b5a8dd1d
SK
755#ifdef HAVE_DHCP
756
757static int is_tag_prefix(char *arg)
758{
759 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
760 return 1;
761
762 return 0;
763}
764
765static char *set_prefix(char *arg)
766{
767 if (strstr(arg, "set:") == arg)
768 return arg+4;
769
770 return arg;
771}
772
832af0ba 773/* This is too insanely large to keep in-line in the switch */
c4a7f90e 774static int parse_dhcp_opt(char *errstr, char *arg, int flags)
832af0ba 775{
824af85b 776 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
832af0ba 777 char lenchar = 0, *cp;
40ef23b5 778 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
c4a7f90e 779 char *comma = NULL;
f2621c7f 780 struct dhcp_netid *np = NULL;
4cb1b320
SK
781 u16 opt_len = 0;
782 int is6 = 0;
bd08ae67 783 int option_ok = 0;
832af0ba
SK
784
785 new->len = 0;
824af85b 786 new->flags = flags;
832af0ba
SK
787 new->netid = NULL;
788 new->val = NULL;
f2621c7f 789 new->opt = 0;
832af0ba 790
f2621c7f 791 while (arg)
832af0ba 792 {
f2621c7f
SK
793 comma = split(arg);
794
795 for (cp = arg; *cp; cp++)
796 if (*cp < '0' || *cp > '9')
797 break;
832af0ba 798
f2621c7f
SK
799 if (!*cp)
800 {
801 new->opt = atoi(arg);
802 opt_len = 0;
bd08ae67 803 option_ok = 1;
832af0ba 804 break;
f2621c7f
SK
805 }
806
807 if (strstr(arg, "option:") == arg)
808 {
bd08ae67
SK
809 if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
810 {
811 opt_len = lookup_dhcp_len(AF_INET, new->opt);
812 /* option:<optname> must follow tag and vendor string. */
813 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
814 option_ok = 1;
815 }
f2621c7f
SK
816 break;
817 }
4cb1b320
SK
818#ifdef HAVE_DHCP6
819 else if (strstr(arg, "option6:") == arg)
820 {
821 for (cp = arg+8; *cp; cp++)
822 if (*cp < '0' || *cp > '9')
823 break;
824
825 if (!*cp)
826 {
827 new->opt = atoi(arg+8);
828 opt_len = 0;
bd08ae67 829 option_ok = 1;
4cb1b320
SK
830 }
831 else
40ef23b5 832 {
bd08ae67
SK
833 if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
834 {
835 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
836 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
837 option_ok = 1;
838 }
40ef23b5 839 }
4cb1b320
SK
840 /* option6:<opt>|<optname> must follow tag and vendor string. */
841 is6 = 1;
842 break;
843 }
844#endif
f2621c7f
SK
845 else if (strstr(arg, "vendor:") == arg)
846 {
73a08a24
SK
847 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
848 new->flags |= DHOPT_VENDOR;
849 }
850 else if (strstr(arg, "encap:") == arg)
851 {
852 new->u.encap = atoi(arg+6);
f2621c7f
SK
853 new->flags |= DHOPT_ENCAPSULATE;
854 }
316e2730
SK
855 else if (strstr(arg, "vi-encap:") == arg)
856 {
857 new->u.encap = atoi(arg+9);
858 new->flags |= DHOPT_RFC3925;
859 if (flags == DHOPT_MATCH)
860 {
bd08ae67 861 option_ok = 1;
316e2730
SK
862 break;
863 }
864 }
f2621c7f
SK
865 else
866 {
824af85b 867 new->netid = opt_malloc(sizeof (struct dhcp_netid));
8ef5ada2
SK
868 /* allow optional "net:" or "tag:" for consistency */
869 if (is_tag_prefix(arg))
824af85b 870 new->netid->net = opt_string_alloc(arg+4);
f2621c7f 871 else
8ef5ada2 872 new->netid->net = opt_string_alloc(set_prefix(arg));
f2621c7f
SK
873 new->netid->next = np;
874 np = new->netid;
875 }
876
877 arg = comma;
832af0ba 878 }
4cb1b320
SK
879
880#ifdef HAVE_DHCP6
881 if (is6)
882 {
883 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
c4a7f90e 884 ret_err(_("unsupported encapsulation for IPv6 option"));
4cb1b320
SK
885
886 if (opt_len == 0 &&
887 !(new->flags & DHOPT_RFC3925))
bd08ae67 888 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
4cb1b320
SK
889 }
890 else
891#endif
892 if (opt_len == 0 &&
893 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
bd08ae67 894 opt_len = lookup_dhcp_len(AF_INET, new->opt);
40ef23b5 895
316e2730 896 /* option may be missing with rfc3925 match */
bd08ae67 897 if (!option_ok)
c4a7f90e
SK
898 ret_err(_("bad dhcp-option"));
899
900 if (comma)
832af0ba
SK
901 {
902 /* characterise the value */
f2621c7f 903 char c;
28866e95 904 int found_dig = 0;
4cb1b320 905 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
832af0ba 906 addrs = digs = 1;
f2621c7f
SK
907 dots = 0;
908 for (cp = comma; (c = *cp); cp++)
909 if (c == ',')
832af0ba
SK
910 {
911 addrs++;
912 is_dec = is_hex = 0;
913 }
f2621c7f 914 else if (c == ':')
832af0ba
SK
915 {
916 digs++;
917 is_dec = is_addr = 0;
918 }
f2621c7f 919 else if (c == '/')
832af0ba 920 {
4cb1b320 921 is_addr6 = is_dec = is_hex = 0;
832af0ba
SK
922 if (cp == comma) /* leading / means a pathname */
923 is_addr = 0;
924 }
f2621c7f
SK
925 else if (c == '.')
926 {
23245c0c 927 is_addr6 = is_dec = is_hex = 0;
f2621c7f
SK
928 dots++;
929 }
930 else if (c == '-')
4cb1b320 931 is_hex = is_addr = is_addr6 = 0;
f2621c7f 932 else if (c == ' ')
832af0ba 933 is_dec = is_hex = 0;
f2621c7f 934 else if (!(c >='0' && c <= '9'))
832af0ba
SK
935 {
936 is_addr = 0;
937 if (cp[1] == 0 && is_dec &&
f2621c7f 938 (c == 'b' || c == 's' || c == 'i'))
832af0ba 939 {
f2621c7f 940 lenchar = c;
832af0ba
SK
941 *cp = 0;
942 }
943 else
944 is_dec = 0;
f2621c7f 945 if (!((c >='A' && c <= 'F') ||
73a08a24
SK
946 (c >='a' && c <= 'f') ||
947 (c == '*' && (flags & DHOPT_MATCH))))
4cb1b320
SK
948 {
949 is_hex = 0;
950 if (c != '[' && c != ']')
951 is_addr6 = 0;
952 }
832af0ba 953 }
28866e95
SK
954 else
955 found_dig = 1;
f2621c7f 956
28866e95
SK
957 if (!found_dig)
958 is_dec = is_addr = 0;
4cb1b320 959
f2621c7f 960 /* We know that some options take addresses */
7622fc06 961 if (opt_len & OT_ADDR_LIST)
f2621c7f
SK
962 {
963 is_string = is_dec = is_hex = 0;
4cb1b320
SK
964
965 if (!is6 && (!is_addr || dots == 0))
c4a7f90e 966 ret_err(_("bad IP address"));
4cb1b320
SK
967
968 if (is6 && !is_addr6)
c4a7f90e 969 ret_err(_("bad IPv6 address"));
f2621c7f 970 }
28866e95 971 /* or names */
4cb1b320
SK
972 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
973 is_addr6 = is_addr = is_dec = is_hex = 0;
23245c0c
SK
974
975 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
976 {
977 int val, fac = 1;
978
979 switch (comma[strlen(comma) - 1])
980 {
42243214
SK
981 case 'w':
982 case 'W':
983 fac *= 7;
984 /* fall through */
23245c0c
SK
985 case 'd':
986 case 'D':
987 fac *= 24;
988 /* fall though */
989 case 'h':
990 case 'H':
991 fac *= 60;
992 /* fall through */
993 case 'm':
994 case 'M':
995 fac *= 60;
996 /* fall through */
997 case 's':
998 case 'S':
999 comma[strlen(comma) - 1] = 0;
1000 }
1001
1002 new->len = 4;
1003 new->val = opt_malloc(4);
1004 val = atoi(comma);
1005 *((int *)new->val) = htonl(val * fac);
1006 }
1007 else if (is_hex && digs > 1)
832af0ba
SK
1008 {
1009 new->len = digs;
824af85b 1010 new->val = opt_malloc(new->len);
73a08a24
SK
1011 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
1012 new->flags |= DHOPT_HEX;
832af0ba
SK
1013 }
1014 else if (is_dec)
1015 {
1016 int i, val = atoi(comma);
1017 /* assume numeric arg is 1 byte except for
1018 options where it is known otherwise.
1019 For vendor class option, we have to hack. */
f2621c7f
SK
1020 if (opt_len != 0)
1021 new->len = opt_len;
1022 else if (val & 0xffff0000)
1023 new->len = 4;
1024 else if (val & 0xff00)
1025 new->len = 2;
1026 else
1027 new->len = 1;
1028
832af0ba
SK
1029 if (lenchar == 'b')
1030 new->len = 1;
1031 else if (lenchar == 's')
1032 new->len = 2;
1033 else if (lenchar == 'i')
1034 new->len = 4;
f2621c7f 1035
824af85b 1036 new->val = opt_malloc(new->len);
832af0ba
SK
1037 for (i=0; i<new->len; i++)
1038 new->val[i] = val>>((new->len - i - 1)*8);
1039 }
4cb1b320 1040 else if (is_addr && !is6)
832af0ba
SK
1041 {
1042 struct in_addr in;
1043 unsigned char *op;
1044 char *slash;
1045 /* max length of address/subnet descriptor is five bytes,
1046 add one for the option 120 enc byte too */
824af85b 1047 new->val = op = opt_malloc((5 * addrs) + 1);
6b01084f
SK
1048 new->flags |= DHOPT_ADDR;
1049
572b41eb
SK
1050 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1051 new->opt == OPTION_SIP_SERVER)
832af0ba 1052 {
6b01084f
SK
1053 *(op++) = 1; /* RFC 3361 "enc byte" */
1054 new->flags &= ~DHOPT_ADDR;
832af0ba
SK
1055 }
1056 while (addrs--)
1057 {
1058 cp = comma;
f2621c7f 1059 comma = split(cp);
73a08a24 1060 slash = split_chr(cp, '/');
ddd9a6b4 1061 inet_pton(AF_INET, cp, &in);
832af0ba
SK
1062 if (!slash)
1063 {
1064 memcpy(op, &in, INADDRSZ);
1065 op += INADDRSZ;
1066 }
1067 else
1068 {
1069 unsigned char *p = (unsigned char *)&in;
1070 int netsize = atoi(slash);
1071 *op++ = netsize;
1072 if (netsize > 0)
1073 *op++ = *p++;
1074 if (netsize > 8)
1075 *op++ = *p++;
1076 if (netsize > 16)
1077 *op++ = *p++;
1078 if (netsize > 24)
1079 *op++ = *p++;
1080 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1081 }
1082 }
1083 new->len = op - new->val;
1084 }
4cb1b320
SK
1085 else if (is_addr6 && is6)
1086 {
1087 unsigned char *op;
1088 new->val = op = opt_malloc(16 * addrs);
1089 new->flags |= DHOPT_ADDR6;
1090 while (addrs--)
1091 {
1092 cp = comma;
1093 comma = split(cp);
1094
1095 /* check for [1234::7] */
1096 if (*cp == '[')
1097 cp++;
1098 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1099 cp[strlen(cp)-1] = 0;
1100
1101 if (inet_pton(AF_INET6, cp, op))
1102 {
1103 op += IN6ADDRSZ;
1104 continue;
1105 }
1106
c4a7f90e 1107 ret_err(_("bad IPv6 address"));
4cb1b320
SK
1108 }
1109 new->len = op - new->val;
1110 }
f2621c7f 1111 else if (is_string)
832af0ba 1112 {
4cb1b320 1113 /* text arg */
572b41eb 1114 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
4cb1b320 1115 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
832af0ba
SK
1116 {
1117 /* dns search, RFC 3397, or SIP, RFC 3361 */
1118 unsigned char *q, *r, *tail;
824af85b 1119 unsigned char *p, *m = NULL, *newp;
832af0ba 1120 size_t newlen, len = 0;
572b41eb 1121 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
832af0ba
SK
1122
1123 arg = comma;
f2621c7f 1124 comma = split(arg);
832af0ba
SK
1125
1126 while (arg && *arg)
1127 {
c52e1897
SK
1128 char *in, *dom = NULL;
1129 size_t domlen = 1;
1130 /* Allow "." as an empty domain */
1131 if (strcmp (arg, ".") != 0)
832af0ba 1132 {
c52e1897 1133 if (!(dom = canonicalise_opt(arg)))
c4a7f90e
SK
1134 ret_err(_("bad domain in dhcp-option"));
1135
c52e1897 1136 domlen = strlen(dom) + 2;
832af0ba 1137 }
c52e1897
SK
1138
1139 newp = opt_malloc(len + domlen + header_size);
824af85b 1140 if (m)
c52e1897
SK
1141 {
1142 memcpy(newp, m, header_size + len);
1143 free(m);
1144 }
824af85b 1145 m = newp;
832af0ba
SK
1146 p = m + header_size;
1147 q = p + len;
1148
1149 /* add string on the end in RFC1035 format */
c52e1897 1150 for (in = dom; in && *in;)
832af0ba
SK
1151 {
1152 unsigned char *cp = q++;
1153 int j;
c52e1897
SK
1154 for (j = 0; *in && (*in != '.'); in++, j++)
1155 *q++ = *in;
832af0ba 1156 *cp = j;
c52e1897
SK
1157 if (*in)
1158 in++;
832af0ba
SK
1159 }
1160 *q++ = 0;
1f15b81d 1161 free(dom);
c52e1897 1162
832af0ba
SK
1163 /* Now tail-compress using earlier names. */
1164 newlen = q - p;
1165 for (tail = p + len; *tail; tail += (*tail) + 1)
1166 for (r = p; r - p < (int)len; r += (*r) + 1)
1167 if (strcmp((char *)r, (char *)tail) == 0)
1168 {
1169 PUTSHORT((r - p) | 0xc000, tail);
1170 newlen = tail - p;
1171 goto end;
1172 }
1173 end:
1174 len = newlen;
1175
1176 arg = comma;
f2621c7f 1177 comma = split(arg);
832af0ba
SK
1178 }
1179
1180 /* RFC 3361, enc byte is zero for names */
572b41eb 1181 if (new->opt == OPTION_SIP_SERVER)
832af0ba
SK
1182 m[0] = 0;
1183 new->len = (int) len + header_size;
1184 new->val = m;
1185 }
4cb1b320
SK
1186#ifdef HAVE_DHCP6
1187 else if (comma && (opt_len & OT_CSTRING))
1188 {
1189 /* length fields are two bytes so need 16 bits for each string */
40ef23b5 1190 int i, commas = 1;
4cb1b320
SK
1191 unsigned char *p, *newp;
1192
40ef23b5 1193 for (i = 0; comma[i]; i++)
4cb1b320
SK
1194 if (comma[i] == ',')
1195 commas++;
1196
1197 newp = opt_malloc(strlen(comma)+(2*commas));
1198 p = newp;
1199 arg = comma;
1200 comma = split(arg);
1201
1202 while (arg && *arg)
1203 {
1204 u16 len = strlen(arg);
18f0fb05 1205 unhide_metas(arg);
4cb1b320
SK
1206 PUTSHORT(len, p);
1207 memcpy(p, arg, len);
1208 p += len;
1209
1210 arg = comma;
1211 comma = split(arg);
1212 }
1213
1214 new->val = newp;
1215 new->len = p - newp;
1216 }
1217 else if (comma && (opt_len & OT_RFC1035_NAME))
1218 {
18f0fb05
SK
1219 unsigned char *p = NULL, *newp, *end;
1220 int len = 0;
4cb1b320
SK
1221 arg = comma;
1222 comma = split(arg);
1223
1224 while (arg && *arg)
1225 {
18f0fb05
SK
1226 char *dom = canonicalise_opt(arg);
1227 if (!dom)
c4a7f90e
SK
1228 ret_err(_("bad domain in dhcp-option"));
1229
18f0fb05
SK
1230 newp = opt_malloc(len + strlen(dom) + 2);
1231
1232 if (p)
1233 {
1234 memcpy(newp, p, len);
1235 free(p);
1236 }
4cb1b320 1237
18f0fb05
SK
1238 p = newp;
1239 end = do_rfc1035_name(p + len, dom);
1240 *end++ = 0;
1241 len = end - p;
1242 free(dom);
1243
4cb1b320
SK
1244 arg = comma;
1245 comma = split(arg);
1246 }
1247
18f0fb05
SK
1248 new->val = p;
1249 new->len = len;
4cb1b320
SK
1250 }
1251#endif
832af0ba
SK
1252 else
1253 {
1254 new->len = strlen(comma);
1255 /* keep terminating zero on string */
824af85b 1256 new->val = (unsigned char *)opt_string_alloc(comma);
832af0ba
SK
1257 new->flags |= DHOPT_STRING;
1258 }
1259 }
1260 }
1261
4cb1b320
SK
1262 if (!is6 &&
1263 ((new->len > 255) ||
316e2730 1264 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
4cb1b320 1265 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
c4a7f90e 1266 ret_err(_("dhcp-option too long"));
832af0ba 1267
c4a7f90e 1268 if (flags == DHOPT_MATCH)
824af85b 1269 {
c4a7f90e
SK
1270 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1271 !new->netid ||
1272 new->netid->next)
1273 ret_err(_("illegal dhcp-match"));
1274
1275 if (is6)
4cb1b320 1276 {
c4a7f90e
SK
1277 new->next = daemon->dhcp_match6;
1278 daemon->dhcp_match6 = new;
4cb1b320
SK
1279 }
1280 else
73a08a24 1281 {
c4a7f90e
SK
1282 new->next = daemon->dhcp_match;
1283 daemon->dhcp_match = new;
73a08a24 1284 }
824af85b 1285 }
c4a7f90e
SK
1286 else if (is6)
1287 {
1288 new->next = daemon->dhcp_opts6;
1289 daemon->dhcp_opts6 = new;
1290 }
1291 else
1292 {
1293 new->next = daemon->dhcp_opts;
1294 daemon->dhcp_opts = new;
1295 }
1296
1297 return 1;
832af0ba
SK
1298}
1299
7622fc06 1300#endif
832af0ba 1301
28866e95
SK
1302void set_option_bool(unsigned int opt)
1303{
1304 if (opt < 32)
1305 daemon->options |= 1u << opt;
1306 else
1307 daemon->options2 |= 1u << (opt - 32);
1308}
1309
2b5bae9a
SK
1310void reset_option_bool(unsigned int opt)
1311{
1312 if (opt < 32)
1313 daemon->options &= ~(1u << opt);
1314 else
1315 daemon->options2 &= ~(1u << (opt - 32));
1316}
1317
c4a7f90e 1318static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
849a8357
SK
1319{
1320 int i;
c4a7f90e 1321 char *comma;
b8187c80 1322
832af0ba 1323 if (option == '?')
c4a7f90e 1324 ret_err(gen_err);
832af0ba 1325
1a6bca81
SK
1326 for (i=0; usage[i].opt != 0; i++)
1327 if (usage[i].opt == option)
849a8357 1328 {
1a6bca81
SK
1329 int rept = usage[i].rept;
1330
28866e95 1331 if (command_line)
1a6bca81
SK
1332 {
1333 /* command line */
1334 if (rept == ARG_USED_CL)
c4a7f90e 1335 ret_err(_("illegal repeated flag"));
1a6bca81
SK
1336 if (rept == ARG_ONE)
1337 usage[i].rept = ARG_USED_CL;
1338 }
1339 else
1340 {
1341 /* allow file to override command line */
1342 if (rept == ARG_USED_FILE)
c4a7f90e 1343 ret_err(_("illegal repeated keyword"));
1a6bca81
SK
1344 if (rept == ARG_USED_CL || rept == ARG_ONE)
1345 usage[i].rept = ARG_USED_FILE;
1346 }
1347
1348 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1349 {
28866e95 1350 set_option_bool(rept);
c4a7f90e 1351 return 1;
1a6bca81
SK
1352 }
1353
1354 break;
849a8357 1355 }
1a6bca81 1356
849a8357
SK
1357 switch (option)
1358 {
f2621c7f 1359 case 'C': /* --conf-file */
849a8357 1360 {
824af85b 1361 char *file = opt_string_alloc(arg);
849a8357 1362 if (file)
9009d746 1363 {
28866e95 1364 one_file(file, 0);
9009d746
SK
1365 free(file);
1366 }
849a8357
SK
1367 break;
1368 }
1369
f2621c7f 1370 case '7': /* --conf-dir */
849a8357
SK
1371 {
1372 DIR *dir_stream;
1373 struct dirent *ent;
1374 char *directory, *path;
1f15b81d
SK
1375 struct list {
1376 char *suffix;
1377 struct list *next;
1378 } *ignore_suffix = NULL, *li;
849a8357 1379
1f15b81d 1380 comma = split(arg);
824af85b 1381 if (!(directory = opt_string_alloc(arg)))
849a8357
SK
1382 break;
1383
1f15b81d
SK
1384 for (arg = comma; arg; arg = comma)
1385 {
1386 comma = split(arg);
1387 li = opt_malloc(sizeof(struct list));
1388 li->next = ignore_suffix;
1389 ignore_suffix = li;
1390 /* Have to copy: buffer is overwritten */
1391 li->suffix = opt_string_alloc(arg);
1392 };
1393
849a8357 1394 if (!(dir_stream = opendir(directory)))
5aabfc78 1395 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1f15b81d 1396
849a8357 1397 while ((ent = readdir(dir_stream)))
9e4abcb5 1398 {
7622fc06 1399 size_t len = strlen(ent->d_name);
849a8357 1400 struct stat buf;
1f15b81d
SK
1401
1402 /* ignore emacs backups and dotfiles */
7622fc06
SK
1403 if (len == 0 ||
1404 ent->d_name[len - 1] == '~' ||
849a8357
SK
1405 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1406 ent->d_name[0] == '.')
1407 continue;
7622fc06 1408
1f15b81d
SK
1409 for (li = ignore_suffix; li; li = li->next)
1410 {
1411 /* check for proscribed suffices */
1412 size_t ls = strlen(li->suffix);
1413 if (len > ls &&
1414 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1415 break;
1416 }
1417 if (li)
1418 continue;
1419
824af85b 1420 path = opt_malloc(strlen(directory) + len + 2);
849a8357
SK
1421 strcpy(path, directory);
1422 strcat(path, "/");
1423 strcat(path, ent->d_name);
7622fc06 1424
39595cfe 1425 /* files must be readable */
849a8357 1426 if (stat(path, &buf) == -1)
5aabfc78 1427 die(_("cannot access %s: %s"), path, EC_FILE);
39595cfe 1428
849a8357 1429 /* only reg files allowed. */
39595cfe
SK
1430 if (S_ISREG(buf.st_mode))
1431 one_file(path, 0);
849a8357 1432
849a8357 1433 free(path);
9e4abcb5 1434 }
849a8357
SK
1435
1436 closedir(dir_stream);
9009d746 1437 free(directory);
1f15b81d
SK
1438 for(; ignore_suffix; ignore_suffix = li)
1439 {
1440 li = ignore_suffix->next;
1441 free(ignore_suffix->suffix);
1442 free(ignore_suffix);
1443 }
1444
849a8357
SK
1445 break;
1446 }
1447
ed4c0767
SK
1448 case LOPT_ADD_SBNET: /* --add-subnet */
1449 set_option_bool(OPT_CLIENT_SUBNET);
1450 if (arg)
1451 {
1452 comma = split(arg);
1453 if (!atoi_check(arg, &daemon->addr4_netmask) ||
1454 (comma && !atoi_check(comma, &daemon->addr6_netmask)))
1455 ret_err(gen_err);
1456 }
1457 break;
1458
ad094275
SK
1459 case '1': /* --enable-dbus */
1460 set_option_bool(OPT_DBUS);
1461 if (arg)
1462 daemon->dbus_name = opt_string_alloc(arg);
1463 else
1464 daemon->dbus_name = DNSMASQ_SERVICE;
1465 break;
1466
f2621c7f
SK
1467 case '8': /* --log-facility */
1468 /* may be a filename */
8ef5ada2 1469 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
824af85b 1470 daemon->log_file = opt_string_alloc(arg);
849a8357 1471 else
f2621c7f 1472 {
572b41eb 1473#ifdef __ANDROID__
c4a7f90e 1474 ret_err(_("setting log facility is not possible under Android"));
572b41eb 1475#else
f2621c7f
SK
1476 for (i = 0; facilitynames[i].c_name; i++)
1477 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1478 break;
1479
1480 if (facilitynames[i].c_name)
1481 daemon->log_fac = facilitynames[i].c_val;
1482 else
c4a7f90e 1483 ret_err(_("bad log facility"));
572b41eb 1484#endif
849a8357
SK
1485 }
1486 break;
1487
f2621c7f 1488 case 'x': /* --pid-file */
824af85b 1489 daemon->runfile = opt_string_alloc(arg);
849a8357 1490 break;
5aabfc78 1491
f2621c7f 1492 case 'r': /* --resolv-file */
849a8357 1493 {
824af85b 1494 char *name = opt_string_alloc(arg);
849a8357
SK
1495 struct resolvc *new, *list = daemon->resolv_files;
1496
1497 if (list && list->is_default)
1498 {
1499 /* replace default resolv file - possibly with nothing */
1500 if (name)
9e4abcb5 1501 {
849a8357
SK
1502 list->is_default = 0;
1503 list->name = name;
9e4abcb5 1504 }
849a8357
SK
1505 else
1506 list = NULL;
1507 }
1508 else if (name)
1509 {
824af85b 1510 new = opt_malloc(sizeof(struct resolvc));
849a8357
SK
1511 new->next = list;
1512 new->name = name;
1513 new->is_default = 0;
1514 new->mtime = 0;
1515 new->logged = 0;
1516 list = new;
1517 }
1518 daemon->resolv_files = list;
1519 break;
1520 }
1521
f2621c7f 1522 case 'm': /* --mx-host */
849a8357
SK
1523 {
1524 int pref = 1;
1525 struct mx_srv_record *new;
1f15b81d
SK
1526 char *name, *target = NULL;
1527
f2621c7f 1528 if ((comma = split(arg)))
849a8357
SK
1529 {
1530 char *prefstr;
1f15b81d 1531 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
c4a7f90e 1532 ret_err(_("bad MX preference"));
849a8357
SK
1533 }
1534
1f15b81d
SK
1535 if (!(name = canonicalise_opt(arg)) ||
1536 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 1537 ret_err(_("bad MX name"));
1f15b81d 1538
824af85b 1539 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
1540 new->next = daemon->mxnames;
1541 daemon->mxnames = new;
1542 new->issrv = 0;
1f15b81d
SK
1543 new->name = name;
1544 new->target = target; /* may be NULL */
849a8357
SK
1545 new->weight = pref;
1546 break;
1547 }
1548
f2621c7f 1549 case 't': /* --mx-target */
1f15b81d 1550 if (!(daemon->mxtarget = canonicalise_opt(arg)))
c4a7f90e 1551 ret_err(_("bad MX target"));
849a8357 1552 break;
7622fc06
SK
1553
1554#ifdef HAVE_DHCP
f2621c7f 1555 case 'l': /* --dhcp-leasefile */
824af85b 1556 daemon->lease_file = opt_string_alloc(arg);
849a8357
SK
1557 break;
1558
c72daea8
SK
1559 /* Sorry about the gross pre-processor abuse */
1560 case '6': /* --dhcp-script */
1561 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1f15b81d 1562# if defined(NO_FORK)
c4a7f90e 1563 ret_err(_("cannot run scripts under uClinux"));
1f15b81d 1564# elif !defined(HAVE_SCRIPT)
c4a7f90e 1565 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
7622fc06 1566# else
c72daea8
SK
1567 if (option == LOPT_LUASCRIPT)
1568# if !defined(HAVE_LUASCRIPT)
c4a7f90e 1569 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
c72daea8
SK
1570# else
1571 daemon->luascript = opt_string_alloc(arg);
1572# endif
1573 else
1574 daemon->lease_change_command = opt_string_alloc(arg);
7622fc06 1575# endif
849a8357 1576 break;
c72daea8 1577#endif /* HAVE_DHCP */
7622fc06 1578
28866e95
SK
1579 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1580 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
f2621c7f 1581 case 'H': /* --addn-hosts */
849a8357 1582 {
824af85b 1583 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
849a8357 1584 static int hosts_index = 1;
824af85b 1585 new->fname = opt_string_alloc(arg);
849a8357 1586 new->index = hosts_index++;
7622fc06 1587 new->flags = 0;
28866e95
SK
1588 if (option == 'H')
1589 {
1590 new->next = daemon->addn_hosts;
1591 daemon->addn_hosts = new;
1592 }
1593 else if (option == LOPT_DHCP_HOST)
1594 {
1595 new->next = daemon->dhcp_hosts_file;
1596 daemon->dhcp_hosts_file = new;
1597 }
e1ff419c 1598 else if (option == LOPT_DHCP_OPTS)
28866e95
SK
1599 {
1600 new->next = daemon->dhcp_opts_file;
1601 daemon->dhcp_opts_file = new;
1602 }
849a8357
SK
1603 break;
1604 }
1605
f373a15b
SK
1606
1607#ifdef HAVE_AUTH
4f7b304f 1608 case LOPT_AUTHSERV: /* --auth-server */
86e3b9a0 1609 if (!(comma = split(arg)))
4f7b304f
SK
1610 ret_err(gen_err);
1611
4f7b304f 1612 daemon->authserver = opt_string_alloc(arg);
429798fd
SK
1613 arg = comma;
1614 do {
1615 struct iname *new = opt_malloc(sizeof(struct iname));
1616 comma = split(arg);
1617 new->name = NULL;
1618 unhide_metas(arg);
ddd9a6b4 1619 if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
429798fd
SK
1620 new->addr.sa.sa_family = AF_INET;
1621#ifdef HAVE_IPV6
1622 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1623 new->addr.sa.sa_family = AF_INET6;
1624#endif
1625 else
f25e6c6d
SK
1626 {
1627 char *fam = split_chr(arg, '/');
1628 new->name = opt_string_alloc(arg);
1629 new->addr.sa.sa_family = 0;
1630 if (fam)
1631 {
1632 if (strcmp(fam, "4") == 0)
1633 new->addr.sa.sa_family = AF_INET;
1634#ifdef HAVE_IPV6
1635 else if (strcmp(fam, "6") == 0)
1636 new->addr.sa.sa_family = AF_INET6;
1637#endif
1638 else
1639 ret_err(gen_err);
1640 }
1641 }
429798fd
SK
1642 new->next = daemon->authinterface;
1643 daemon->authinterface = new;
1644
1645 arg = comma;
1646 } while (arg);
1647
4f7b304f 1648 break;
e1ff419c
SK
1649
1650 case LOPT_AUTHSFS: /* --auth-sec-servers */
1651 {
1652 struct name_list *new;
1653
1654 do {
1655 comma = split(arg);
429798fd 1656 new = opt_malloc(sizeof(struct name_list));
e1ff419c
SK
1657 new->name = opt_string_alloc(arg);
1658 new->next = daemon->secondary_forward_server;
1659 daemon->secondary_forward_server = new;
1660 arg = comma;
1661 } while (arg);
1662 break;
1663 }
1664
4f7b304f
SK
1665 case LOPT_AUTHZONE: /* --auth-zone */
1666 {
1667 struct auth_zone *new;
1668
1669 comma = split(arg);
1e14cc0f 1670
429798fd 1671 new = opt_malloc(sizeof(struct auth_zone));
4f7b304f
SK
1672 new->domain = opt_string_alloc(arg);
1673 new->subnet = NULL;
376d48c7 1674 new->interface_names = NULL;
4f7b304f
SK
1675 new->next = daemon->auth_zones;
1676 daemon->auth_zones = new;
1677
1678 while ((arg = comma))
1679 {
1680 int prefixlen = 0;
1681 char *prefix;
376d48c7
SK
1682 struct addrlist *subnet = NULL;
1683 struct all_addr addr;
4f7b304f
SK
1684
1685 comma = split(arg);
1686 prefix = split_chr(arg, '/');
1687
1688 if (prefix && !atoi_check(prefix, &prefixlen))
1689 ret_err(gen_err);
1690
376d48c7 1691 if (inet_pton(AF_INET, arg, &addr.addr.addr4))
4f7b304f 1692 {
376d48c7 1693 subnet = opt_malloc(sizeof(struct addrlist));
4f7b304f 1694 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
376d48c7 1695 subnet->flags = ADDRLIST_LITERAL;
4f7b304f
SK
1696 }
1697#ifdef HAVE_IPV6
376d48c7 1698 else if (inet_pton(AF_INET6, arg, &addr.addr.addr6))
4f7b304f 1699 {
376d48c7 1700 subnet = opt_malloc(sizeof(struct addrlist));
4f7b304f 1701 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
376d48c7 1702 subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
4f7b304f
SK
1703 }
1704#endif
376d48c7
SK
1705 else
1706 {
1707 struct auth_name_list *name = opt_malloc(sizeof(struct auth_name_list));
1708 name->name = opt_string_alloc(arg);
1709 name->flags = AUTH4 | AUTH6;
1710 name->next = new->interface_names;
1711 new->interface_names = name;
1712 if (prefix)
1713 {
1714 if (prefixlen == 4)
1715 name->flags &= ~AUTH6;
1716#ifdef HAVE_IPV6
1717 else if (prefixlen == 6)
1718 name->flags &= ~AUTH4;
1719#endif
1720 else
1721 ret_err(gen_err);
1722 }
1723 }
1724
1725 if (subnet)
1726 {
1727 subnet->addr = addr;
1728 subnet->next = new->subnet;
1729 new->subnet = subnet;
1730 }
4f7b304f
SK
1731 }
1732 break;
1733 }
376d48c7 1734
4f7b304f
SK
1735 case LOPT_AUTHSOA: /* --auth-soa */
1736 comma = split(arg);
5c72bb9e 1737 daemon->soa_sn = (u32)atoi(arg);
4f7b304f
SK
1738 if (comma)
1739 {
86e3b9a0 1740 char *cp;
4f7b304f
SK
1741 arg = comma;
1742 comma = split(arg);
1743 daemon->hostmaster = opt_string_alloc(arg);
86e3b9a0
SK
1744 for (cp = daemon->hostmaster; *cp; cp++)
1745 if (*cp == '@')
1746 *cp = '.';
1747
4f7b304f
SK
1748 if (comma)
1749 {
1750 arg = comma;
1751 comma = split(arg);
5c72bb9e 1752 daemon->soa_refresh = (u32)atoi(arg);
4f7b304f
SK
1753 if (comma)
1754 {
1755 arg = comma;
1756 comma = split(arg);
5c72bb9e 1757 daemon->soa_retry = (u32)atoi(arg);
4f7b304f
SK
1758 if (comma)
1759 {
1760 arg = comma;
1761 comma = split(arg);
5c72bb9e 1762 daemon->soa_expiry = (u32)atoi(arg);
4f7b304f
SK
1763 }
1764 }
1765 }
1766 }
1767
1768 break;
f373a15b 1769#endif
4f7b304f 1770
2bb73af7
SK
1771 case 's': /* --domain */
1772 case LOPT_SYNTH: /* --synth-domain */
849a8357 1773 if (strcmp (arg, "#") == 0)
28866e95 1774 set_option_bool(OPT_RESOLV_DOMAIN);
849a8357 1775 else
9009d746 1776 {
1f15b81d 1777 char *d;
9009d746 1778 comma = split(arg);
1f15b81d 1779 if (!(d = canonicalise_opt(arg)))
c4a7f90e 1780 ret_err(gen_err);
9009d746
SK
1781 else
1782 {
9009d746
SK
1783 if (comma)
1784 {
429798fd 1785 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
28866e95 1786 char *netpart;
2bb73af7 1787
48fd1c4d
SK
1788 new->prefix = NULL;
1789
9009d746 1790 unhide_metas(comma);
28866e95 1791 if ((netpart = split_chr(comma, '/')))
9009d746 1792 {
d74942a0
SK
1793 int msize;
1794
28866e95 1795 arg = split(netpart);
d74942a0 1796 if (!atoi_check(netpart, &msize))
c4a7f90e 1797 ret_err(gen_err);
d74942a0 1798 else if (inet_pton(AF_INET, comma, &new->start))
9009d746 1799 {
d74942a0
SK
1800 int mask = (1 << (32 - msize)) - 1;
1801 new->is6 = 0;
9009d746
SK
1802 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1803 new->end.s_addr = new->start.s_addr | htonl(mask);
28866e95
SK
1804 if (arg)
1805 {
48fd1c4d 1806 if (option != 's')
b5a7ff42
SK
1807 {
1808 if (!(new->prefix = canonicalise_opt(arg)) ||
1809 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1810 ret_err(_("bad prefix"));
1811 }
48fd1c4d
SK
1812 else if (strcmp(arg, "local") != 0 ||
1813 (msize != 8 && msize != 16 && msize != 24))
c4a7f90e 1814 ret_err(gen_err);
28866e95
SK
1815 else
1816 {
48fd1c4d
SK
1817 /* generate the equivalent of
1818 local=/<domain>/
1819 local=/xxx.yyy.zzz.in-addr.arpa/ */
28866e95
SK
1820 struct server *serv = opt_malloc(sizeof(struct server));
1821 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1822 char *p;
48fd1c4d 1823
28866e95
SK
1824 memset(serv, 0, sizeof(struct server));
1825 serv->domain = d;
1826 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1827 serv->next = daemon->servers;
1828 daemon->servers = serv;
48fd1c4d 1829
28866e95
SK
1830 serv = opt_malloc(sizeof(struct server));
1831 memset(serv, 0, sizeof(struct server));
1832 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1833
1834 if (msize == 24)
1835 p += sprintf(p, "%d.", a & 0xff);
1836 a = a >> 8;
1837 if (msize != 8)
1838 p += sprintf(p, "%d.", a & 0xff);
1839 a = a >> 8;
1840 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
48fd1c4d 1841
28866e95
SK
1842 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1843 serv->next = daemon->servers;
1844 daemon->servers = serv;
1845 }
1846 }
9009d746 1847 }
d74942a0
SK
1848#ifdef HAVE_IPV6
1849 else if (inet_pton(AF_INET6, comma, &new->start6))
1850 {
1851 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1852 u64 addrpart = addr6part(&new->start6);
1853 new->is6 = 1;
48fd1c4d 1854
d74942a0
SK
1855 /* prefix==64 overflows the mask calculation above */
1856 if (msize == 64)
1857 mask = (u64)-1LL;
48fd1c4d 1858
d74942a0
SK
1859 new->end6 = new->start6;
1860 setaddr6part(&new->start6, addrpart & ~mask);
1861 setaddr6part(&new->end6, addrpart | mask);
1862
1863 if (msize < 64)
c4a7f90e 1864 ret_err(gen_err);
d74942a0
SK
1865 else if (arg)
1866 {
48fd1c4d 1867 if (option != 's')
b5a7ff42
SK
1868 {
1869 if (!(new->prefix = canonicalise_opt(arg)) ||
1870 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
1871 ret_err(_("bad prefix"));
1872 }
48fd1c4d 1873 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
c4a7f90e 1874 ret_err(gen_err);
d74942a0
SK
1875 else
1876 {
48fd1c4d
SK
1877 /* generate the equivalent of
1878 local=/<domain>/
1879 local=/xxx.yyy.zzz.ip6.arpa/ */
d74942a0 1880 struct server *serv = opt_malloc(sizeof(struct server));
d74942a0 1881 char *p;
ceae00dd 1882
d74942a0
SK
1883 memset(serv, 0, sizeof(struct server));
1884 serv->domain = d;
1885 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1886 serv->next = daemon->servers;
1887 daemon->servers = serv;
1888
1889 serv = opt_malloc(sizeof(struct server));
1890 memset(serv, 0, sizeof(struct server));
1891 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1892
1893 for (i = msize-1; i >= 0; i -= 4)
1894 {
1895 int dig = ((unsigned char *)&new->start6)[i>>3];
1896 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1897 }
1898 p += sprintf(p, "ip6.arpa");
1899
1900 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1901 serv->next = daemon->servers;
1902 daemon->servers = serv;
1903 }
1904 }
1905 }
1906#endif
1907 else
c4a7f90e 1908 ret_err(gen_err);
9009d746 1909 }
eec5c1e2 1910 else
9009d746 1911 {
eec5c1e2 1912 char *prefstr;
d74942a0 1913 arg = split(comma);
eec5c1e2
SK
1914 prefstr = split(arg);
1915
d74942a0
SK
1916 if (inet_pton(AF_INET, comma, &new->start))
1917 {
1918 new->is6 = 0;
1919 if (!arg)
1920 new->end.s_addr = new->start.s_addr;
1921 else if (!inet_pton(AF_INET, arg, &new->end))
c4a7f90e 1922 ret_err(gen_err);
d74942a0
SK
1923 }
1924#ifdef HAVE_IPV6
1925 else if (inet_pton(AF_INET6, comma, &new->start6))
1926 {
1927 new->is6 = 1;
1928 if (!arg)
1929 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1930 else if (!inet_pton(AF_INET6, arg, &new->end6))
c4a7f90e 1931 ret_err(gen_err);
d74942a0
SK
1932 }
1933#endif
1934 else
c4a7f90e 1935 ret_err(gen_err);
eec5c1e2
SK
1936
1937 if (option != 's' && prefstr)
1938 {
1939 if (!(new->prefix = canonicalise_opt(prefstr)) ||
1940 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1941 ret_err(_("bad prefix"));
1942 }
d74942a0 1943 }
2307eac6
SK
1944
1945 new->domain = d;
2bb73af7
SK
1946 if (option == 's')
1947 {
1948 new->next = daemon->cond_domain;
1949 daemon->cond_domain = new;
1950 }
1951 else
1952 {
1953 new->next = daemon->synth_domains;
1954 daemon->synth_domains = new;
1955 }
9009d746 1956 }
2bb73af7 1957 else if (option == 's')
9009d746 1958 daemon->domain_suffix = d;
2bb73af7
SK
1959 else
1960 ret_err(gen_err);
9009d746
SK
1961 }
1962 }
849a8357
SK
1963 break;
1964
f2621c7f 1965 case 'u': /* --user */
824af85b 1966 daemon->username = opt_string_alloc(arg);
849a8357
SK
1967 break;
1968
f2621c7f 1969 case 'g': /* --group */
824af85b 1970 daemon->groupname = opt_string_alloc(arg);
1a6bca81 1971 daemon->group_set = 1;
849a8357 1972 break;
9e038946 1973
7622fc06 1974#ifdef HAVE_DHCP
9e038946
SK
1975 case LOPT_SCRIPTUSR: /* --scriptuser */
1976 daemon->scriptuser = opt_string_alloc(arg);
1977 break;
7622fc06 1978#endif
849a8357 1979
f2621c7f 1980 case 'i': /* --interface */
849a8357 1981 do {
824af85b 1982 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1983 comma = split(arg);
849a8357
SK
1984 new->next = daemon->if_names;
1985 daemon->if_names = new;
1986 /* new->name may be NULL if someone does
1987 "interface=" to disable all interfaces except loop. */
824af85b 1988 new->name = opt_string_alloc(arg);
4ce4f377 1989 new->used = 0;
849a8357
SK
1990 arg = comma;
1991 } while (arg);
1992 break;
1993
2937f8a0
SK
1994 case LOPT_TFTP: /* --enable-tftp */
1995 set_option_bool(OPT_TFTP);
1996 if (!arg)
1997 break;
1998 /* fall through */
1999
f2621c7f
SK
2000 case 'I': /* --except-interface */
2001 case '2': /* --no-dhcp-interface */
849a8357 2002 do {
824af85b 2003 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 2004 comma = split(arg);
824af85b 2005 new->name = opt_string_alloc(arg);
849a8357
SK
2006 if (option == 'I')
2007 {
2008 new->next = daemon->if_except;
2009 daemon->if_except = new;
2010 }
2937f8a0
SK
2011 else if (option == LOPT_TFTP)
2012 {
2013 new->next = daemon->tftp_interfaces;
2014 daemon->tftp_interfaces = new;
2015 }
849a8357
SK
2016 else
2017 {
2018 new->next = daemon->dhcp_except;
2019 daemon->dhcp_except = new;
2020 }
2021 arg = comma;
2022 } while (arg);
2023 break;
2024
f2621c7f 2025 case 'B': /* --bogus-nxdomain */
849a8357
SK
2026 {
2027 struct in_addr addr;
2028 unhide_metas(arg);
ddd9a6b4 2029 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
849a8357 2030 {
824af85b 2031 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
849a8357
SK
2032 baddr->next = daemon->bogus_addr;
2033 daemon->bogus_addr = baddr;
2034 baddr->addr = addr;
2035 }
2036 else
c4a7f90e 2037 ret_err(gen_err); /* error */
849a8357
SK
2038 break;
2039 }
2040
f2621c7f 2041 case 'a': /* --listen-address */
49678767 2042 case LOPT_AUTHPEER: /* --auth-peer */
849a8357 2043 do {
824af85b 2044 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 2045 comma = split(arg);
849a8357 2046 unhide_metas(arg);
ddd9a6b4 2047 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
849a8357
SK
2048 {
2049 new->addr.sa.sa_family = AF_INET;
49678767 2050 new->addr.in.sin_port = 0;
849a8357
SK
2051#ifdef HAVE_SOCKADDR_SA_LEN
2052 new->addr.in.sin_len = sizeof(new->addr.in);
2053#endif
2054 }
2055#ifdef HAVE_IPV6
2056 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
2057 {
2058 new->addr.sa.sa_family = AF_INET6;
2059 new->addr.in6.sin6_flowinfo = 0;
2060 new->addr.in6.sin6_scope_id = 0;
49678767 2061 new->addr.in6.sin6_port = 0;
849a8357
SK
2062#ifdef HAVE_SOCKADDR_SA_LEN
2063 new->addr.in6.sin6_len = sizeof(new->addr.in6);
2064#endif
2065 }
2066#endif
2067 else
c4a7f90e 2068 ret_err(gen_err);
4ce4f377
SK
2069
2070 new->used = 0;
49678767
SK
2071 if (option == 'a')
2072 {
2073 new->next = daemon->if_addrs;
2074 daemon->if_addrs = new;
2075 }
2076 else
2077 {
2078 new->next = daemon->auth_peers;
2079 daemon->auth_peers = new;
2080 }
849a8357
SK
2081 arg = comma;
2082 } while (arg);
2083 break;
2084
8ef5ada2
SK
2085 case 'S': /* --server */
2086 case LOPT_LOCAL: /* --local */
2087 case 'A': /* --address */
2088 case LOPT_NO_REBIND: /* --rebind-domain-ok */
849a8357
SK
2089 {
2090 struct server *serv, *newlist = NULL;
2091
2092 unhide_metas(arg);
2093
8ef5ada2 2094 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
849a8357 2095 {
8ef5ada2
SK
2096 int rebind = !(*arg == '/');
2097 char *end = NULL;
2098 if (!rebind)
2099 arg++;
2100 while (rebind || (end = split_chr(arg, '/')))
fd9fa481 2101 {
849a8357 2102 char *domain = NULL;
8ef5ada2
SK
2103 /* elide leading dots - they are implied in the search algorithm */
2104 while (*arg == '.') arg++;
849a8357
SK
2105 /* # matches everything and becomes a zero length domain string */
2106 if (strcmp(arg, "#") == 0)
2107 domain = "";
1f15b81d 2108 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
849a8357 2109 option = '?';
824af85b
SK
2110 serv = opt_malloc(sizeof(struct server));
2111 memset(serv, 0, sizeof(struct server));
849a8357
SK
2112 serv->next = newlist;
2113 newlist = serv;
849a8357
SK
2114 serv->domain = domain;
2115 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
73a08a24 2116 arg = end;
8ef5ada2
SK
2117 if (rebind)
2118 break;
fd9fa481 2119 }
849a8357 2120 if (!newlist)
c4a7f90e 2121 ret_err(gen_err);
849a8357
SK
2122 }
2123 else
2124 {
824af85b
SK
2125 newlist = opt_malloc(sizeof(struct server));
2126 memset(newlist, 0, sizeof(struct server));
849a8357
SK
2127 }
2128
2129 if (option == 'A')
2130 {
2131 newlist->flags |= SERV_LITERAL_ADDRESS;
2132 if (!(newlist->flags & SERV_TYPE))
c4a7f90e 2133 ret_err(gen_err);
849a8357 2134 }
8ef5ada2
SK
2135 else if (option == LOPT_NO_REBIND)
2136 newlist->flags |= SERV_NO_REBIND;
849a8357
SK
2137
2138 if (!arg || !*arg)
2139 {
8ef5ada2
SK
2140 if (!(newlist->flags & SERV_NO_REBIND))
2141 newlist->flags |= SERV_NO_ADDR; /* no server */
2142 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 2143 ret_err(gen_err);
8ef5ada2
SK
2144 }
2145
2146 else if (strcmp(arg, "#") == 0)
2147 {
2148 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
849a8357 2149 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 2150 ret_err(gen_err);
849a8357
SK
2151 }
2152 else
2153 {
faafb3f7
SK
2154 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2155 if (err)
2156 ret_err(err);
849a8357
SK
2157 }
2158
f2621c7f
SK
2159 serv = newlist;
2160 while (serv->next)
849a8357 2161 {
f2621c7f
SK
2162 serv->next->flags = serv->flags;
2163 serv->next->addr = serv->addr;
2164 serv->next->source_addr = serv->source_addr;
faafb3f7 2165 strcpy(serv->next->interface, serv->interface);
f2621c7f 2166 serv = serv->next;
849a8357 2167 }
f2621c7f
SK
2168 serv->next = daemon->servers;
2169 daemon->servers = newlist;
849a8357
SK
2170 break;
2171 }
13d86c73
JD
2172
2173 case LOPT_IPSET: /* --ipset */
2174#ifndef HAVE_IPSET
2175 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2176 break;
2177#else
2178 {
2179 struct ipsets ipsets_head;
2180 struct ipsets *ipsets = &ipsets_head;
2181 int size;
2182 char *end;
2183 char **sets, **sets_pos;
2184 memset(ipsets, 0, sizeof(struct ipsets));
2185 unhide_metas(arg);
2186 if (arg && *arg == '/')
2187 {
2188 arg++;
2189 while ((end = split_chr(arg, '/')))
2190 {
2191 char *domain = NULL;
2192 /* elide leading dots - they are implied in the search algorithm */
2193 while (*arg == '.')
2194 arg++;
2195 /* # matches everything and becomes a zero length domain string */
2196 if (strcmp(arg, "#") == 0 || !*arg)
2197 domain = "";
2198 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2199 option = '?';
2200 ipsets->next = opt_malloc(sizeof(struct ipsets));
2201 ipsets = ipsets->next;
2202 memset(ipsets, 0, sizeof(struct ipsets));
2203 ipsets->domain = domain;
2204 arg = end;
2205 }
2206 }
2207 else
2208 {
2209 ipsets->next = opt_malloc(sizeof(struct ipsets));
2210 ipsets = ipsets->next;
2211 memset(ipsets, 0, sizeof(struct ipsets));
2212 ipsets->domain = "";
2213 }
2214 if (!arg || !*arg)
2215 {
2216 option = '?';
2217 break;
2218 }
2219 size = 2;
2220 for (end = arg; *end; ++end)
2221 if (*end == ',')
2222 ++size;
2223
2224 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2225
2226 do {
2227 end = split(arg);
2228 *sets_pos++ = opt_string_alloc(arg);
2229 arg = end;
2230 } while (end);
2231 *sets_pos = 0;
2232 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2233 ipsets->next->sets = sets;
2234 ipsets->next = daemon->ipsets;
2235 daemon->ipsets = ipsets_head.next;
2236
2237 break;
2238 }
2239#endif
849a8357 2240
f2621c7f 2241 case 'c': /* --cache-size */
849a8357
SK
2242 {
2243 int size;
2244
2245 if (!atoi_check(arg, &size))
c4a7f90e 2246 ret_err(gen_err);
849a8357
SK
2247 else
2248 {
2249 /* zero is OK, and means no caching. */
2250
2251 if (size < 0)
2252 size = 0;
2253 else if (size > 10000)
2254 size = 10000;
2255
2256 daemon->cachesize = size;
2257 }
2258 break;
2259 }
2260
f2621c7f 2261 case 'p': /* --port */
1ad24ae1 2262 if (!atoi_check16(arg, &daemon->port))
c4a7f90e 2263 ret_err(gen_err);
849a8357 2264 break;
208b65c5 2265
1a6bca81 2266 case LOPT_MINPORT: /* --min-port */
1ad24ae1 2267 if (!atoi_check16(arg, &daemon->min_port))
c4a7f90e 2268 ret_err(gen_err);
1a6bca81
SK
2269 break;
2270
f2621c7f 2271 case '0': /* --dns-forward-max */
208b65c5 2272 if (!atoi_check(arg, &daemon->ftabsize))
c4a7f90e 2273 ret_err(gen_err);
208b65c5
SK
2274 break;
2275
f2621c7f
SK
2276 case LOPT_MAX_LOGS: /* --log-async */
2277 daemon->max_logs = LOG_MAX; /* default */
2278 if (arg && !atoi_check(arg, &daemon->max_logs))
c4a7f90e 2279 ret_err(gen_err);
f2621c7f
SK
2280 else if (daemon->max_logs > 100)
2281 daemon->max_logs = 100;
2282 break;
2283
2284 case 'P': /* --edns-packet-max */
849a8357
SK
2285 {
2286 int i;
2287 if (!atoi_check(arg, &i))
c4a7f90e 2288 ret_err(gen_err);
849a8357
SK
2289 daemon->edns_pktsz = (unsigned short)i;
2290 break;
2291 }
2292
f2621c7f 2293 case 'Q': /* --query-port */
1ad24ae1 2294 if (!atoi_check16(arg, &daemon->query_port))
c4a7f90e 2295 ret_err(gen_err);
1a6bca81
SK
2296 /* if explicitly set to zero, use single OS ephemeral port
2297 and disable random ports */
2298 if (daemon->query_port == 0)
2299 daemon->osport = 1;
849a8357
SK
2300 break;
2301
824af85b
SK
2302 case 'T': /* --local-ttl */
2303 case LOPT_NEGTTL: /* --neg-ttl */
8ef5ada2 2304 case LOPT_MAXTTL: /* --max-ttl */
1d860415 2305 case LOPT_MAXCTTL: /* --max-cache-ttl */
4f7b304f 2306 case LOPT_AUTHTTL: /* --auth-ttl */
849a8357
SK
2307 {
2308 int ttl;
2309 if (!atoi_check(arg, &ttl))
c4a7f90e 2310 ret_err(gen_err);
824af85b
SK
2311 else if (option == LOPT_NEGTTL)
2312 daemon->neg_ttl = (unsigned long)ttl;
8ef5ada2
SK
2313 else if (option == LOPT_MAXTTL)
2314 daemon->max_ttl = (unsigned long)ttl;
1d860415
SK
2315 else if (option == LOPT_MAXCTTL)
2316 daemon->max_cache_ttl = (unsigned long)ttl;
4f7b304f
SK
2317 else if (option == LOPT_AUTHTTL)
2318 daemon->auth_ttl = (unsigned long)ttl;
849a8357
SK
2319 else
2320 daemon->local_ttl = (unsigned long)ttl;
2321 break;
2322 }
2323
7622fc06 2324#ifdef HAVE_DHCP
f2621c7f 2325 case 'X': /* --dhcp-lease-max */
849a8357 2326 if (!atoi_check(arg, &daemon->dhcp_max))
c4a7f90e 2327 ret_err(gen_err);
849a8357 2328 break;
7622fc06 2329#endif
849a8357 2330
7622fc06 2331#ifdef HAVE_TFTP
f2621c7f 2332 case LOPT_TFTP_MAX: /* --tftp-max */
832af0ba 2333 if (!atoi_check(arg, &daemon->tftp_max))
c4a7f90e 2334 ret_err(gen_err);
832af0ba
SK
2335 break;
2336
824af85b 2337 case LOPT_PREFIX: /* --tftp-prefix */
8ef5ada2
SK
2338 comma = split(arg);
2339 if (comma)
2340 {
2341 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2342 new->interface = opt_string_alloc(comma);
2343 new->prefix = opt_string_alloc(arg);
2344 new->next = daemon->if_prefix;
2345 daemon->if_prefix = new;
2346 }
2347 else
2348 daemon->tftp_prefix = opt_string_alloc(arg);
832af0ba
SK
2349 break;
2350
824af85b
SK
2351 case LOPT_TFTPPORTS: /* --tftp-port-range */
2352 if (!(comma = split(arg)) ||
1ad24ae1
SK
2353 !atoi_check16(arg, &daemon->start_tftp_port) ||
2354 !atoi_check16(comma, &daemon->end_tftp_port))
c4a7f90e 2355 ret_err(_("bad port range"));
824af85b
SK
2356
2357 if (daemon->start_tftp_port > daemon->end_tftp_port)
2358 {
2359 int tmp = daemon->start_tftp_port;
2360 daemon->start_tftp_port = daemon->end_tftp_port;
2361 daemon->end_tftp_port = tmp;
2362 }
2363
2364 break;
7622fc06 2365#endif
824af85b 2366
f2621c7f 2367 case LOPT_BRIDGE: /* --bridge-interface */
832af0ba 2368 {
824af85b 2369 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
316e2730 2370 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
c4a7f90e 2371 ret_err(_("bad bridge-interface"));
832af0ba 2372
316e2730 2373 strcpy(new->iface, arg);
832af0ba
SK
2374 new->alias = NULL;
2375 new->next = daemon->bridges;
2376 daemon->bridges = new;
2377
2378 do {
f2621c7f
SK
2379 arg = comma;
2380 comma = split(arg);
316e2730 2381 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
832af0ba 2382 {
824af85b 2383 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
832af0ba
SK
2384 b->next = new->alias;
2385 new->alias = b;
316e2730 2386 strcpy(b->iface, arg);
832af0ba
SK
2387 }
2388 } while (comma);
2389
2390 break;
2391 }
832af0ba 2392
7622fc06 2393#ifdef HAVE_DHCP
f2621c7f 2394 case 'F': /* --dhcp-range */
849a8357
SK
2395 {
2396 int k, leasepos = 2;
8445f5d2 2397 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
824af85b 2398 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
849a8357 2399
52b92f4d 2400 memset (new, 0, sizeof(*new));
849a8357 2401 new->lease_time = DEFLEASE;
52b92f4d 2402
849a8357
SK
2403 if (!arg)
2404 {
2405 option = '?';
2406 break;
2407 }
2408
2409 while(1)
2410 {
2411 for (cp = arg; *cp; cp++)
52b92f4d
SK
2412 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2413 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2414 (*cp >='0' && *cp <= '9')))
849a8357
SK
2415 break;
2416
f2621c7f 2417 if (*cp != ',' && (comma = split(arg)))
849a8357 2418 {
8bc4cece 2419 if (is_tag_prefix(arg))
9e4abcb5 2420 {
824af85b
SK
2421 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2422 tt->net = opt_string_alloc(arg+4);
849a8357 2423 tt->next = new->filter;
0c38719f
SK
2424 /* ignore empty tag */
2425 if (tt->net)
2426 new->filter = tt;
9e4abcb5
SK
2427 }
2428 else
2429 {
849a8357 2430 if (new->netid.net)
c4a7f90e 2431 ret_err(_("only one tag allowed"));
8ef5ada2
SK
2432 else if (strstr(arg, "set:") == arg)
2433 new->netid.net = opt_string_alloc(arg+4);
9e4abcb5 2434 else
824af85b 2435 new->netid.net = opt_string_alloc(arg);
9e4abcb5 2436 }
f2621c7f 2437 arg = comma;
9e4abcb5 2438 }
849a8357 2439 else
9e4abcb5 2440 {
849a8357 2441 a[0] = arg;
9e4abcb5
SK
2442 break;
2443 }
849a8357
SK
2444 }
2445
1f776932 2446 for (k = 1; k < 8; k++)
f2621c7f
SK
2447 if (!(a[k] = split(a[k-1])))
2448 break;
849a8357 2449
52b92f4d 2450 if (k < 2)
c4a7f90e
SK
2451 ret_err(_("bad dhcp-range"));
2452
2453 if (inet_pton(AF_INET, a[0], &new->start))
849a8357 2454 {
52b92f4d
SK
2455 new->next = daemon->dhcp;
2456 daemon->dhcp = new;
30cd9666 2457 new->end = new->start;
52b92f4d 2458 if (strcmp(a[1], "static") == 0)
30cd9666 2459 new->flags |= CONTEXT_STATIC;
52b92f4d 2460 else if (strcmp(a[1], "proxy") == 0)
30cd9666
SK
2461 new->flags |= CONTEXT_PROXY;
2462 else if (!inet_pton(AF_INET, a[1], &new->end))
c4a7f90e 2463 ret_err(_("bad dhcp-range"));
52b92f4d
SK
2464
2465 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2466 {
2467 struct in_addr tmp = new->start;
2468 new->start = new->end;
2469 new->end = tmp;
2470 }
2471
c4a7f90e 2472 if (k >= 3 && strchr(a[2], '.') &&
ddd9a6b4 2473 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
52b92f4d
SK
2474 {
2475 new->flags |= CONTEXT_NETMASK;
2476 leasepos = 3;
2477 if (!is_same_net(new->start, new->end, new->netmask))
c4a7f90e 2478 ret_err(_("inconsistent DHCP range"));
52b92f4d
SK
2479 }
2480
2481 if (k >= 4 && strchr(a[3], '.') &&
ddd9a6b4 2482 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
52b92f4d
SK
2483 {
2484 new->flags |= CONTEXT_BRDCAST;
2485 leasepos = 4;
2486 }
849a8357 2487 }
52b92f4d
SK
2488#ifdef HAVE_DHCP6
2489 else if (inet_pton(AF_INET6, a[0], &new->start6))
849a8357 2490 {
89500e31 2491 new->flags |= CONTEXT_V6;
52b92f4d 2492 new->prefix = 64; /* default */
30cd9666 2493 new->end6 = new->start6;
6692a1a5
SK
2494 new->next = daemon->dhcp6;
2495 daemon->dhcp6 = new;
2496
30cd9666 2497 for (leasepos = 1; leasepos < k; leasepos++)
801ca9a7 2498 {
30cd9666
SK
2499 if (strcmp(a[leasepos], "static") == 0)
2500 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2501 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
1f776932 2502 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
30cd9666 2503 else if (strcmp(a[leasepos], "ra-names") == 0)
1f776932 2504 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
30cd9666 2505 else if (strcmp(a[leasepos], "ra-stateless") == 0)
1f776932 2506 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
30cd9666
SK
2507 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2508 new->flags |= CONTEXT_DHCP;
1f776932
SK
2509 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2510 {
2511 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2512 new->flags |= CONTEXT_TEMPLATE;
2513 }
30cd9666
SK
2514 else
2515 break;
801ca9a7 2516 }
6692a1a5 2517
52b92f4d 2518 /* bare integer < 128 is prefix value */
c4a7f90e 2519 if (leasepos < k)
52b92f4d
SK
2520 {
2521 int pref;
30cd9666 2522 for (cp = a[leasepos]; *cp; cp++)
52b92f4d
SK
2523 if (!(*cp >= '0' && *cp <= '9'))
2524 break;
30cd9666 2525 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
52b92f4d
SK
2526 {
2527 new->prefix = pref;
30cd9666 2528 leasepos++;
52b92f4d
SK
2529 }
2530 }
30cd9666 2531
6692a1a5
SK
2532 if (new->prefix != 64)
2533 {
2534 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2535 ret_err(_("prefix length must be exactly 64 for RA subnets"));
2536 else if (new->flags & CONTEXT_TEMPLATE)
2537 ret_err(_("prefix length must be exactly 64 for subnet constructors"));
2538 }
2539
2540 if (new->prefix < 64)
2541 ret_err(_("prefix length must be at least 64"));
2542
c4a7f90e
SK
2543 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2544 ret_err(_("inconsistent DHCPv6 range"));
6692a1a5
SK
2545
2546 /* dhcp-range=:: enables DHCP stateless on any interface */
2547 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
2548 new->prefix = 0;
66409193
SK
2549
2550 if (new->flags & CONTEXT_TEMPLATE)
2551 {
2552 struct in6_addr zero;
2553 memset(&zero, 0, sizeof(zero));
2554 if (!is_same_net6(&zero, &new->start6, new->prefix))
2555 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2556 }
2557
c4a7f90e 2558 if (addr6part(&new->start6) > addr6part(&new->end6))
52b92f4d
SK
2559 {
2560 struct in6_addr tmp = new->start6;
2561 new->start6 = new->end6;
2562 new->end6 = tmp;
2563 }
849a8357 2564 }
52b92f4d 2565#endif
d9ee9c08
SK
2566 else
2567 ret_err(_("bad dhcp-range"));
849a8357 2568
30cd9666 2569 if (leasepos < k)
849a8357
SK
2570 {
2571 if (strcmp(a[leasepos], "infinite") == 0)
2572 new->lease_time = 0xffffffff;
c8257540
SK
2573 else if (strcmp(a[leasepos], "deprecated") == 0)
2574 new->flags |= CONTEXT_DEPRECATE;
849a8357 2575 else
9e4abcb5 2576 {
849a8357
SK
2577 int fac = 1;
2578 if (strlen(a[leasepos]) > 0)
36717eee 2579 {
849a8357 2580 switch (a[leasepos][strlen(a[leasepos]) - 1])
36717eee 2581 {
42243214
SK
2582 case 'w':
2583 case 'W':
2584 fac *= 7;
2585 /* fall through */
849a8357
SK
2586 case 'd':
2587 case 'D':
2588 fac *= 24;
2589 /* fall though */
2590 case 'h':
2591 case 'H':
2592 fac *= 60;
2593 /* fall through */
2594 case 'm':
2595 case 'M':
2596 fac *= 60;
2597 /* fall through */
2598 case 's':
2599 case 'S':
f2621c7f 2600 a[leasepos][strlen(a[leasepos]) - 1] = 0;
9e4abcb5 2601 }
849a8357 2602
be37986a
SK
2603 for (cp = a[leasepos]; *cp; cp++)
2604 if (!(*cp >= '0' && *cp <= '9'))
2605 break;
2606
54dae552 2607 if (*cp || (leasepos+1 < k))
be37986a
SK
2608 ret_err(_("bad dhcp-range"));
2609
849a8357
SK
2610 new->lease_time = atoi(a[leasepos]) * fac;
2611 /* Leases of a minute or less confuse
2612 some clients, notably Apple's */
2613 if (new->lease_time < 120)
2614 new->lease_time = 120;
9e4abcb5 2615 }
9e4abcb5 2616 }
849a8357
SK
2617 }
2618 break;
2619 }
5aabfc78 2620
5aabfc78 2621 case LOPT_BANK:
f2621c7f 2622 case 'G': /* --dhcp-host */
849a8357 2623 {
f2621c7f 2624 int j, k = 0;
3e8ed78b 2625 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
5aabfc78 2626 struct dhcp_config *new;
849a8357
SK
2627 struct in_addr in;
2628
824af85b
SK
2629 new = opt_malloc(sizeof(struct dhcp_config));
2630
849a8357 2631 new->next = daemon->dhcp_conf;
9009d746
SK
2632 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2633 new->hwaddr = NULL;
8ef5ada2
SK
2634 new->netid = NULL;
2635
849a8357 2636 if ((a[0] = arg))
3e8ed78b 2637 for (k = 1; k < 7; k++)
f2621c7f
SK
2638 if (!(a[k] = split(a[k-1])))
2639 break;
849a8357
SK
2640
2641 for (j = 0; j < k; j++)
2642 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2643 {
2644 char *arg = a[j];
2645
2646 if ((arg[0] == 'i' || arg[0] == 'I') &&
2647 (arg[1] == 'd' || arg[1] == 'D') &&
2648 arg[2] == ':')
2649 {
2650 if (arg[3] == '*')
2651 new->flags |= CONFIG_NOCLID;
2652 else
3d8df260 2653 {
849a8357
SK
2654 int len;
2655 arg += 3; /* dump id: */
2656 if (strchr(arg, ':'))
2657 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2658 else
5aabfc78
SK
2659 {
2660 unhide_metas(arg);
2661 len = (int) strlen(arg);
2662 }
2663
28866e95 2664 if (len == -1)
9f7f3b12 2665
c4a7f90e 2666 ret_err(_("bad hex constant"));
28866e95 2667 else if ((new->clid = opt_malloc(len)))
5aabfc78
SK
2668 {
2669 new->flags |= CONFIG_CLID;
2670 new->clid_len = len;
2671 memcpy(new->clid, arg, len);
2672 }
3d8df260 2673 }
849a8357 2674 }
8ef5ada2
SK
2675 /* dhcp-host has strange backwards-compat needs. */
2676 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
849a8357 2677 {
8ef5ada2
SK
2678 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2679 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2680 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2681 newlist->next = new->netid;
2682 new->netid = newlist;
2683 newlist->list = newtag;
2684 strcpy(newtag->net, arg+4);
2685 unhide_metas(newtag->net);
849a8357 2686 }
7de060b0 2687 else if (strstr(arg, "tag:") == arg)
c4a7f90e 2688 ret_err(_("cannot match tags in --dhcp-host"));
4cb1b320
SK
2689#ifdef HAVE_DHCP6
2690 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2691 {
2692 arg[strlen(arg)-1] = 0;
2693 arg++;
2694
2695 if (!inet_pton(AF_INET6, arg, &new->addr6))
c4a7f90e 2696 ret_err(_("bad IPv6 address"));
30393100
SK
2697
2698 for (i= 0; i < 8; i++)
2699 if (new->addr6.s6_addr[i] != 0)
2700 break;
2701
2702 /* set WILDCARD if network part all zeros */
2703 if (i == 8)
2704 new->flags |= CONFIG_WILDCARD;
4cb1b320
SK
2705
2706 new->flags |= CONFIG_ADDR6;
2707 }
2708#endif
7de060b0 2709 else
849a8357 2710 {
9009d746 2711 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
28866e95
SK
2712 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2713 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
c4a7f90e 2714 ret_err(_("bad hex constant"));
28866e95
SK
2715 else
2716 {
2717
2718 newhw->next = new->hwaddr;
2719 new->hwaddr = newhw;
2720 }
849a8357
SK
2721 }
2722 }
ddd9a6b4 2723 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
849a8357 2724 {
c4a7f90e
SK
2725 struct dhcp_config *configs;
2726
849a8357
SK
2727 new->addr = in;
2728 new->flags |= CONFIG_ADDR;
c4a7f90e
SK
2729
2730 /* If the same IP appears in more than one host config, then DISCOVER
2731 for one of the hosts will get the address, but REQUEST will be NAKed,
2732 since the address is reserved by the other one -> protocol loop. */
2733 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2734 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2735 {
2736 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2737 return 0;
2738 }
849a8357
SK
2739 }
2740 else
2741 {
2742 char *cp, *lastp = NULL, last = 0;
76ff440e 2743 int fac = 1, isdig = 0;
849a8357
SK
2744
2745 if (strlen(a[j]) > 1)
2746 {
2747 lastp = a[j] + strlen(a[j]) - 1;
2748 last = *lastp;
2749 switch (last)
9e4abcb5 2750 {
42243214
SK
2751 case 'w':
2752 case 'W':
2753 fac *= 7;
2754 /* fall through */
849a8357
SK
2755 case 'd':
2756 case 'D':
2757 fac *= 24;
2758 /* fall through */
2759 case 'h':
2760 case 'H':
2761 fac *= 60;
2762 /* fall through */
2763 case 'm':
2764 case 'M':
2765 fac *= 60;
2766 /* fall through */
2767 case 's':
2768 case 'S':
2769 *lastp = 0;
9e4abcb5 2770 }
849a8357
SK
2771 }
2772
2773 for (cp = a[j]; *cp; cp++)
76ff440e
SK
2774 if (isdigit((unsigned char)*cp))
2775 isdig = 1;
2776 else if (*cp != ' ')
849a8357 2777 break;
76ff440e 2778
849a8357
SK
2779 if (*cp)
2780 {
2781 if (lastp)
2782 *lastp = last;
2783 if (strcmp(a[j], "infinite") == 0)
33820b7e 2784 {
849a8357
SK
2785 new->lease_time = 0xffffffff;
2786 new->flags |= CONFIG_TIME;
33820b7e 2787 }
849a8357
SK
2788 else if (strcmp(a[j], "ignore") == 0)
2789 new->flags |= CONFIG_DISABLE;
9e4abcb5
SK
2790 else
2791 {
1f15b81d
SK
2792 if (!(new->hostname = canonicalise_opt(a[j])) ||
2793 !legal_hostname(new->hostname))
c4a7f90e
SK
2794 ret_err(_("bad DHCP host name"));
2795
2796 new->flags |= CONFIG_NAME;
2797 new->domain = strip_hostname(new->hostname);
9e4abcb5 2798 }
849a8357 2799 }
76ff440e 2800 else if (isdig)
849a8357
SK
2801 {
2802 new->lease_time = atoi(a[j]) * fac;
2803 /* Leases of a minute or less confuse
2804 some clients, notably Apple's */
2805 if (new->lease_time < 120)
2806 new->lease_time = 120;
2807 new->flags |= CONFIG_TIME;
2808 }
2809 }
2810
5aabfc78 2811 daemon->dhcp_conf = new;
849a8357
SK
2812 break;
2813 }
8ef5ada2
SK
2814
2815 case LOPT_TAG_IF: /* --tag-if */
2816 {
2817 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2818
2819 new->tag = NULL;
2820 new->set = NULL;
2821 new->next = NULL;
2822
2823 /* preserve order */
2824 if (!daemon->tag_if)
2825 daemon->tag_if = new;
2826 else
2827 {
2828 struct tag_if *tmp;
2829 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2830 tmp->next = new;
2831 }
2832
2833 while (arg)
2834 {
2835 size_t len;
2836
2837 comma = split(arg);
2838 len = strlen(arg);
2839
2840 if (len < 5)
2841 {
2842 new->set = NULL;
2843 break;
2844 }
2845 else
2846 {
2847 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2848 newtag->net = opt_malloc(len - 3);
2849 strcpy(newtag->net, arg+4);
2850 unhide_metas(newtag->net);
2851
2852 if (strstr(arg, "set:") == arg)
2853 {
2854 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2855 newlist->next = new->set;
2856 new->set = newlist;
2857 newlist->list = newtag;
2858 }
2859 else if (strstr(arg, "tag:") == arg)
2860 {
2861 newtag->next = new->tag;
2862 new->tag = newtag;
2863 }
2864 else
2865 {
2866 new->set = NULL;
4dc9c657 2867 free(newtag);
8ef5ada2
SK
2868 break;
2869 }
2870 }
2871
2872 arg = comma;
2873 }
2874
2875 if (!new->set)
c4a7f90e 2876 ret_err(_("bad tag-if"));
8ef5ada2
SK
2877
2878 break;
2879 }
2880
849a8357 2881
73a08a24
SK
2882 case 'O': /* --dhcp-option */
2883 case LOPT_FORCE: /* --dhcp-option-force */
824af85b 2884 case LOPT_OPTS:
73a08a24 2885 case LOPT_MATCH: /* --dhcp-match */
c4a7f90e
SK
2886 return parse_dhcp_opt(errstr, arg,
2887 option == LOPT_FORCE ? DHOPT_FORCE :
2888 (option == LOPT_MATCH ? DHOPT_MATCH :
2889 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2890
f2621c7f 2891 case 'M': /* --dhcp-boot */
849a8357
SK
2892 {
2893 struct dhcp_netid *id = NULL;
8ef5ada2 2894 while (is_tag_prefix(arg))
849a8357 2895 {
824af85b 2896 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
849a8357
SK
2897 newid->next = id;
2898 id = newid;
f2621c7f 2899 comma = split(arg);
824af85b 2900 newid->net = opt_string_alloc(arg+4);
849a8357
SK
2901 arg = comma;
2902 };
2903
2904 if (!arg)
c4a7f90e 2905 ret_err(gen_err);
849a8357
SK
2906 else
2907 {
7de060b0 2908 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
849a8357 2909 struct in_addr dhcp_next_server;
c4a7f90e 2910 struct dhcp_boot *new;
f2621c7f 2911 comma = split(arg);
824af85b 2912 dhcp_file = opt_string_alloc(arg);
849a8357
SK
2913 dhcp_next_server.s_addr = 0;
2914 if (comma)
a84fa1d0 2915 {
849a8357 2916 arg = comma;
f2621c7f 2917 comma = split(arg);
824af85b 2918 dhcp_sname = opt_string_alloc(arg);
849a8357 2919 if (comma)
a84fa1d0 2920 {
849a8357 2921 unhide_metas(comma);
ddd9a6b4
SK
2922 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2923 {
2924 /*
2925 * The user may have specified the tftp hostname here.
2926 * save it so that it can be resolved/looked up during
2927 * actual dhcp_reply().
2928 */
2929
2930 tftp_sname = opt_string_alloc(comma);
2931 dhcp_next_server.s_addr = 0;
2932 }
a84fa1d0 2933 }
a84fa1d0 2934 }
c4a7f90e
SK
2935
2936 new = opt_malloc(sizeof(struct dhcp_boot));
2937 new->file = dhcp_file;
2938 new->sname = dhcp_sname;
2939 new->tftp_sname = tftp_sname;
2940 new->next_server = dhcp_next_server;
2941 new->netid = id;
2942 new->next = daemon->boot_config;
2943 daemon->boot_config = new;
849a8357 2944 }
ddd9a6b4 2945
849a8357
SK
2946 break;
2947 }
7622fc06
SK
2948
2949 case LOPT_PXE_PROMT: /* --pxe-prompt */
2950 {
2951 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2952 int timeout;
2953
2954 new->netid = NULL;
2955 new->opt = 10; /* PXE_MENU_PROMPT */
2956
8ef5ada2
SK
2957 while (is_tag_prefix(arg))
2958 {
7622fc06
SK
2959 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2960 comma = split(arg);
2961 nn->next = new->netid;
2962 new->netid = nn;
2963 nn->net = opt_string_alloc(arg+4);
2964 arg = comma;
2965 }
2966
2967 if (!arg)
c4a7f90e 2968 ret_err(gen_err);
7622fc06
SK
2969 else
2970 {
2971 comma = split(arg);
2972 unhide_metas(arg);
2973 new->len = strlen(arg) + 1;
2974 new->val = opt_malloc(new->len);
2975 memcpy(new->val + 1, arg, new->len - 1);
2976
2977 new->u.vendor_class = (unsigned char *)"PXEClient";
2978 new->flags = DHOPT_VENDOR;
2979
2980 if (comma && atoi_check(comma, &timeout))
2981 *(new->val) = timeout;
2982 else
2983 *(new->val) = 255;
2984
2985 new->next = daemon->dhcp_opts;
2986 daemon->dhcp_opts = new;
1f15b81d 2987 daemon->enable_pxe = 1;
7622fc06
SK
2988 }
2989
2990 break;
2991 }
2992
2993 case LOPT_PXE_SERV: /* --pxe-service */
2994 {
2995 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2996 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2997 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2998 static int boottype = 32768;
2999
3000 new->netid = NULL;
751d6f4a 3001 new->sname = NULL;
7622fc06
SK
3002 new->server.s_addr = 0;
3003
8ef5ada2 3004 while (is_tag_prefix(arg))
7622fc06
SK
3005 {
3006 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
3007 comma = split(arg);
3008 nn->next = new->netid;
3009 new->netid = nn;
3010 nn->net = opt_string_alloc(arg+4);
3011 arg = comma;
3012 }
3013
3014 if (arg && (comma = split(arg)))
3015 {
3016 for (i = 0; CSA[i]; i++)
3017 if (strcasecmp(CSA[i], arg) == 0)
3018 break;
3019
3020 if (CSA[i] || atoi_check(arg, &i))
3021 {
3022 arg = comma;
3023 comma = split(arg);
3024
3025 new->CSA = i;
3026 new->menu = opt_string_alloc(arg);
3027
316e2730
SK
3028 if (!comma)
3029 {
3030 new->type = 0; /* local boot */
3031 new->basename = NULL;
3032 }
3033 else
7622fc06
SK
3034 {
3035 arg = comma;
3036 comma = split(arg);
3037 if (atoi_check(arg, &i))
3038 {
3039 new->type = i;
3040 new->basename = NULL;
3041 }
3042 else
3043 {
3044 new->type = boottype++;
3045 new->basename = opt_string_alloc(arg);
3046 }
3047
751d6f4a
SK
3048 if (comma)
3049 {
3050 if (!inet_pton(AF_INET, comma, &new->server))
3051 {
3052 new->server.s_addr = 0;
3053 new->sname = opt_string_alloc(comma);
3054 }
3055
3056 }
7622fc06 3057 }
751d6f4a 3058
316e2730
SK
3059 /* Order matters */
3060 new->next = NULL;
3061 if (!daemon->pxe_services)
3062 daemon->pxe_services = new;
3063 else
3064 {
3065 struct pxe_service *s;
3066 for (s = daemon->pxe_services; s->next; s = s->next);
3067 s->next = new;
3068 }
3069
3070 daemon->enable_pxe = 1;
3071 break;
3072
7622fc06
SK
3073 }
3074 }
3075
c4a7f90e 3076 ret_err(gen_err);
7622fc06
SK
3077 }
3078
f2621c7f 3079 case '4': /* --dhcp-mac */
849a8357 3080 {
f2621c7f 3081 if (!(comma = split(arg)))
c4a7f90e 3082 ret_err(gen_err);
849a8357
SK
3083 else
3084 {
824af85b 3085 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
8ef5ada2 3086 new->netid.net = opt_string_alloc(set_prefix(arg));
f2621c7f
SK
3087 unhide_metas(comma);
3088 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
28866e95 3089 if (new->hwaddr_len == -1)
c4a7f90e 3090 ret_err(gen_err);
28866e95
SK
3091 else
3092 {
3093 new->next = daemon->dhcp_macs;
3094 daemon->dhcp_macs = new;
3095 }
849a8357
SK
3096 }
3097 }
3098 break;
c630924d
SK
3099
3100#ifdef OPTION6_PREFIX_CLASS
3101 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3102 {
3103 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3104
3105 if (!(comma = split(arg)) ||
3106 !atoi_check16(comma, &new->class))
3107 ret_err(gen_err);
3108
3109 new->tag.net = opt_string_alloc(set_prefix(arg));
3110 new->next = daemon->prefix_classes;
3111 daemon->prefix_classes = new;
3112
3113 break;
3114 }
3115#endif
3116
3117
f2621c7f
SK
3118 case 'U': /* --dhcp-vendorclass */
3119 case 'j': /* --dhcp-userclass */
3120 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3121 case LOPT_REMOTE: /* --dhcp-remoteid */
3122 case LOPT_SUBSCR: /* --dhcp-subscrid */
849a8357 3123 {
c4a7f90e
SK
3124 unsigned char *p;
3125 int dig = 0;
3126 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3127
3128 if (!(comma = split(arg)))
3129 ret_err(gen_err);
3130
3131 new->netid.net = opt_string_alloc(set_prefix(arg));
3132 /* check for hex string - must digits may include : must not have nothing else,
3133 only allowed for agent-options. */
3134
3135 arg = comma;
3136 if ((comma = split(arg)))
3137 {
3138 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3139 ret_err(gen_err);
3140 else
3141 new->enterprise = atoi(arg+11);
3142 }
3143 else
3144 comma = arg;
3145
3146 for (p = (unsigned char *)comma; *p; p++)
3147 if (isxdigit(*p))
3148 dig = 1;
3149 else if (*p != ':')
3150 break;
3151 unhide_metas(comma);
3152 if (option == 'U' || option == 'j' || *p || !dig)
3153 {
3154 new->len = strlen(comma);
3155 new->data = opt_malloc(new->len);
3156 memcpy(new->data, comma, new->len);
3157 }
3158 else
3159 {
3160 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3161 new->data = opt_malloc(new->len);
3162 memcpy(new->data, comma, new->len);
3163 }
3164
3165 switch (option)
3166 {
3167 case 'j':
3168 new->match_type = MATCH_USER;
3169 break;
3170 case 'U':
3171 new->match_type = MATCH_VENDOR;
3172 break;
3173 case LOPT_CIRCUIT:
3174 new->match_type = MATCH_CIRCUIT;
3175 break;
3176 case LOPT_REMOTE:
3177 new->match_type = MATCH_REMOTE;
3178 break;
3179 case LOPT_SUBSCR:
3180 new->match_type = MATCH_SUBSCRIBER;
3181 break;
3182 }
3183 new->next = daemon->dhcp_vendors;
3184 daemon->dhcp_vendors = new;
824af85b 3185
c4a7f90e 3186 break;
849a8357
SK
3187 }
3188
9e038946
SK
3189 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3190 if (!arg)
3191 {
3192 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3193 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3194 }
3195 else
3196 {
3197 comma = split(arg);
1ad24ae1
SK
3198 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3199 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
c4a7f90e 3200 ret_err(_("invalid port number"));
9e038946
SK
3201 if (!comma)
3202 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3203 }
3204 break;
3205
824af85b
SK
3206 case 'J': /* --dhcp-ignore */
3207 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3208 case LOPT_BROADCAST: /* --dhcp-broadcast */
8ef5ada2
SK
3209 case '3': /* --bootp-dynamic */
3210 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
849a8357 3211 {
824af85b 3212 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
849a8357 3213 struct dhcp_netid *list = NULL;
832af0ba
SK
3214 if (option == 'J')
3215 {
3216 new->next = daemon->dhcp_ignore;
3217 daemon->dhcp_ignore = new;
3218 }
824af85b
SK
3219 else if (option == LOPT_BROADCAST)
3220 {
3221 new->next = daemon->force_broadcast;
3222 daemon->force_broadcast = new;
3223 }
9009d746
SK
3224 else if (option == '3')
3225 {
3226 new->next = daemon->bootp_dynamic;
3227 daemon->bootp_dynamic = new;
3228 }
8ef5ada2
SK
3229 else if (option == LOPT_GEN_NAMES)
3230 {
3231 new->next = daemon->dhcp_gen_names;
3232 daemon->dhcp_gen_names = new;
3233 }
832af0ba
SK
3234 else
3235 {
3236 new->next = daemon->dhcp_ignore_names;
3237 daemon->dhcp_ignore_names = new;
3238 }
3239
3240 while (arg) {
824af85b 3241 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
f2621c7f 3242 comma = split(arg);
849a8357
SK
3243 member->next = list;
3244 list = member;
8ef5ada2 3245 if (is_tag_prefix(arg))
9009d746
SK
3246 member->net = opt_string_alloc(arg+4);
3247 else
3248 member->net = opt_string_alloc(arg);
849a8357 3249 arg = comma;
832af0ba 3250 }
849a8357
SK
3251
3252 new->list = list;
3253 break;
3254 }
8ef5ada2
SK
3255
3256 case LOPT_PROXY: /* --dhcp-proxy */
3257 daemon->override = 1;
3258 while (arg) {
3259 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3260 comma = split(arg);
ddd9a6b4 3261 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
c4a7f90e 3262 ret_err(_("bad dhcp-proxy address"));
8ef5ada2
SK
3263 new->next = daemon->override_relays;
3264 daemon->override_relays = new;
3265 arg = comma;
3266 }
3267 break;
ff7eea27
SK
3268
3269 case LOPT_RELAY: /* --dhcp-relay */
3270 {
3271 struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
3272 comma = split(arg);
3273 new->interface = opt_string_alloc(split(comma));
3274 new->iface_index = 0;
3275 if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
3276 {
3277 new->next = daemon->relay4;
3278 daemon->relay4 = new;
3279 }
3280#ifdef HAVE_DHCP6
3281 else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
3282 {
3283 new->next = daemon->relay6;
3284 daemon->relay6 = new;
3285 }
3286#endif
3287 else
3288 ret_err(_("Bad dhcp-relay"));
3289
3290 break;
3291 }
3292
7622fc06 3293#endif
849a8357 3294
8b372704 3295#ifdef HAVE_DHCP6
c4cd95df
SK
3296 case LOPT_RA_PARAM: /* --ra-param */
3297 if ((comma = split(arg)))
3298 {
3299 struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
3300 new->lifetime = -1;
3301 new->prio = 0;
3302 new->name = opt_string_alloc(arg);
3303 if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
3304 {
3305 if (*comma == 'l' || *comma == 'L')
3306 new->prio = 0x18;
3307 else
3308 new->prio = 0x08;
3309 comma = split(comma);
3310 }
3311 arg = split(comma);
3312 if (!atoi_check(comma, &new->interval) ||
3313 (arg && !atoi_check(arg, &new->lifetime)))
3314 ret_err(_("bad RA-params"));
3315
3316 new->next = daemon->ra_interfaces;
3317 daemon->ra_interfaces = new;
3318 }
3319 break;
3320
8b372704
SK
3321 case LOPT_DUID: /* --dhcp-duid */
3322 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
c4a7f90e 3323 ret_err(_("bad DUID"));
8b372704
SK
3324 else
3325 {
3326 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3327 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3328 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3329 }
3330 break;
3331#endif
3332
f2621c7f 3333 case 'V': /* --alias */
849a8357 3334 {
73a08a24 3335 char *dash, *a[3] = { NULL, NULL, NULL };
f2621c7f 3336 int k = 0;
73a08a24
SK
3337 struct doctor *new = opt_malloc(sizeof(struct doctor));
3338 new->next = daemon->doctors;
3339 daemon->doctors = new;
3340 new->mask.s_addr = 0xffffffff;
3341 new->end.s_addr = 0;
3342
849a8357
SK
3343 if ((a[0] = arg))
3344 for (k = 1; k < 3; k++)
3345 {
f2621c7f 3346 if (!(a[k] = split(a[k-1])))
849a8357 3347 break;
849a8357
SK
3348 unhide_metas(a[k]);
3349 }
849a8357 3350
73a08a24
SK
3351 dash = split_chr(a[0], '-');
3352
849a8357 3353 if ((k < 2) ||
ddd9a6b4
SK
3354 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3355 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
73a08a24 3356 option = '?';
849a8357
SK
3357
3358 if (k == 3)
ddd9a6b4 3359 inet_pton(AF_INET, a[2], &new->mask);
849a8357 3360
73a08a24 3361 if (dash &&
ddd9a6b4 3362 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
73a08a24
SK
3363 !is_same_net(new->in, new->end, new->mask) ||
3364 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
c4a7f90e 3365 ret_err(_("invalid alias range"));
849a8357
SK
3366
3367 break;
3368 }
3369
f2621c7f 3370 case LOPT_INTNAME: /* --interface-name */
832af0ba 3371 {
f2621c7f 3372 struct interface_name *new, **up;
1f15b81d
SK
3373 char *domain = NULL;
3374
f2621c7f
SK
3375 comma = split(arg);
3376
1f15b81d 3377 if (!comma || !(domain = canonicalise_opt(arg)))
c4a7f90e 3378 ret_err(_("bad interface name"));
1f15b81d 3379
824af85b 3380 new = opt_malloc(sizeof(struct interface_name));
f2621c7f 3381 new->next = NULL;
376d48c7
SK
3382 new->addr = NULL;
3383
f2621c7f
SK
3384 /* Add to the end of the list, so that first name
3385 of an interface is used for PTR lookups. */
824af85b 3386 for (up = &daemon->int_names; *up; up = &((*up)->next));
f2621c7f 3387 *up = new;
1f15b81d 3388 new->name = domain;
f7029f5c
SK
3389 new->family = 0;
3390 arg = split_chr(comma, '/');
3391 if (arg)
3392 {
3393 if (strcmp(arg, "4") == 0)
3394 new->family = AF_INET;
3395#ifdef HAVE_IPV6
3396 else if (strcmp(arg, "6") == 0)
3397 new->family = AF_INET6;
3398#endif
3399 else
3400 ret_err(gen_err);
3401 }
824af85b 3402 new->intr = opt_string_alloc(comma);
f2621c7f
SK
3403 break;
3404 }
9009d746
SK
3405
3406 case LOPT_CNAME: /* --cname */
3407 {
3408 struct cname *new;
c4a7f90e
SK
3409 char *alias;
3410 char *target;
3411
9009d746 3412 if (!(comma = split(arg)))
c4a7f90e
SK
3413 ret_err(gen_err);
3414
3415 alias = canonicalise_opt(arg);
3416 target = canonicalise_opt(comma);
3417
3418 if (!alias || !target)
3419 ret_err(_("bad CNAME"));
9009d746
SK
3420 else
3421 {
c4a7f90e
SK
3422 for (new = daemon->cnames; new; new = new->next)
3423 if (hostname_isequal(new->alias, arg))
3424 ret_err(_("duplicate CNAME"));
3425 new = opt_malloc(sizeof(struct cname));
3426 new->next = daemon->cnames;
3427 daemon->cnames = new;
3428 new->alias = alias;
3429 new->target = target;
9009d746 3430 }
c4a7f90e 3431
9009d746
SK
3432 break;
3433 }
f2621c7f
SK
3434
3435 case LOPT_PTR: /* --ptr-record */
3436 {
3437 struct ptr_record *new;
1f15b81d
SK
3438 char *dom, *target = NULL;
3439
f2621c7f
SK
3440 comma = split(arg);
3441
1f15b81d
SK
3442 if (!(dom = canonicalise_opt(arg)) ||
3443 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 3444 ret_err(_("bad PTR record"));
1f15b81d
SK
3445 else
3446 {
3447 new = opt_malloc(sizeof(struct ptr_record));
3448 new->next = daemon->ptr;
3449 daemon->ptr = new;
3450 new->name = dom;
3451 new->ptr = target;
3452 }
832af0ba
SK
3453 break;
3454 }
3455
1a6bca81
SK
3456 case LOPT_NAPTR: /* --naptr-record */
3457 {
3458 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3459 int k = 0;
3460 struct naptr *new;
3461 int order, pref;
1f15b81d 3462 char *name, *replace = NULL;
1a6bca81
SK
3463
3464 if ((a[0] = arg))
3465 for (k = 1; k < 7; k++)
3466 if (!(a[k] = split(a[k-1])))
3467 break;
3468
3469
3470 if (k < 6 ||
1f15b81d 3471 !(name = canonicalise_opt(a[0])) ||
1ad24ae1
SK
3472 !atoi_check16(a[1], &order) ||
3473 !atoi_check16(a[2], &pref) ||
1f15b81d 3474 (k == 7 && !(replace = canonicalise_opt(a[6]))))
c4a7f90e 3475 ret_err(_("bad NAPTR record"));
1a6bca81
SK
3476 else
3477 {
3478 new = opt_malloc(sizeof(struct naptr));
3479 new->next = daemon->naptr;
3480 daemon->naptr = new;
1f15b81d 3481 new->name = name;
1a6bca81
SK
3482 new->flags = opt_string_alloc(a[3]);
3483 new->services = opt_string_alloc(a[4]);
3484 new->regexp = opt_string_alloc(a[5]);
1f15b81d 3485 new->replace = replace;
1a6bca81
SK
3486 new->order = order;
3487 new->pref = pref;
3488 }
3489 break;
3490 }
9f7f3b12
SK
3491
3492 case LOPT_RR: /* dns-rr */
3493 {
3494 struct txt_record *new;
d082faf3 3495 size_t len = len;
9f7f3b12
SK
3496 char *data;
3497 int val;
3498
3499 comma = split(arg);
3500 data = split(comma);
3501
3502 new = opt_malloc(sizeof(struct txt_record));
3503 new->next = daemon->rr;
3504 daemon->rr = new;
3505
3506 if (!atoi_check(comma, &val) ||
3507 !(new->name = canonicalise_opt(arg)) ||
51931b88 3508 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
c4a7f90e
SK
3509 ret_err(_("bad RR record"));
3510
9f7f3b12
SK
3511 new->class = val;
3512 new->len = 0;
3513
3514 if (data)
3515 {
3516 new->txt=opt_malloc(len);
3517 new->len = len;
3518 memcpy(new->txt, data, len);
3519 }
3520
3521 break;
3522 }
3523
f2621c7f 3524 case 'Y': /* --txt-record */
849a8357
SK
3525 {
3526 struct txt_record *new;
28866e95
SK
3527 unsigned char *p, *cnt;
3528 size_t len;
3529
3530 comma = split(arg);
3531
824af85b 3532 new = opt_malloc(sizeof(struct txt_record));
849a8357
SK
3533 new->next = daemon->txt;
3534 daemon->txt = new;
3535 new->class = C_IN;
849a8357 3536
1f15b81d 3537 if (!(new->name = canonicalise_opt(arg)))
c4a7f90e
SK
3538 ret_err(_("bad TXT record"));
3539
28866e95
SK
3540 len = comma ? strlen(comma) : 0;
3541 len += (len/255) + 1; /* room for extra counts */
3542 new->txt = p = opt_malloc(len);
3543
3544 cnt = p++;
3545 *cnt = 0;
3546
3547 while (comma && *comma)
3548 {
3549 unsigned char c = (unsigned char)*comma++;
3550
3551 if (c == ',' || *cnt == 255)
3552 {
3553 if (c != ',')
3554 comma--;
3555 cnt = p++;
3556 *cnt = 0;
3557 }
3558 else
3559 {
3560 *p++ = unhide_meta(c);
3561 (*cnt)++;
3562 }
3563 }
3564
3565 new->len = p - new->txt;
3566
849a8357
SK
3567 break;
3568 }
3569
f2621c7f 3570 case 'W': /* --srv-host */
849a8357
SK
3571 {
3572 int port = 1, priority = 0, weight = 0;
3573 char *name, *target = NULL;
3574 struct mx_srv_record *new;
3575
f2621c7f 3576 comma = split(arg);
849a8357 3577
1f15b81d 3578 if (!(name = canonicalise_opt(arg)))
c4a7f90e
SK
3579 ret_err(_("bad SRV record"));
3580
849a8357
SK
3581 if (comma)
3582 {
3583 arg = comma;
f2621c7f 3584 comma = split(arg);
c4a7f90e
SK
3585 if (!(target = canonicalise_opt(arg)))
3586 ret_err(_("bad SRV target"));
824af85b 3587
849a8357 3588 if (comma)
f6b7dc47 3589 {
849a8357 3590 arg = comma;
f2621c7f 3591 comma = split(arg);
1ad24ae1 3592 if (!atoi_check16(arg, &port))
c4a7f90e 3593 ret_err(_("invalid port number"));
824af85b 3594
f6b7dc47
SK
3595 if (comma)
3596 {
91dccd09 3597 arg = comma;
f2621c7f 3598 comma = split(arg);
1ad24ae1 3599 if (!atoi_check16(arg, &priority))
c4a7f90e 3600 ret_err(_("invalid priority"));
824af85b 3601
f6b7dc47
SK
3602 if (comma)
3603 {
91dccd09 3604 arg = comma;
f2621c7f 3605 comma = split(arg);
1ad24ae1 3606 if (!atoi_check16(arg, &weight))
c4a7f90e 3607 ret_err(_("invalid weight"));
f6b7dc47
SK
3608 }
3609 }
f6b7dc47 3610 }
849a8357
SK
3611 }
3612
824af85b 3613 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
3614 new->next = daemon->mxnames;
3615 daemon->mxnames = new;
3616 new->issrv = 1;
3617 new->name = name;
3618 new->target = target;
3619 new->srvport = port;
3620 new->priority = priority;
3621 new->weight = weight;
3622 break;
3623 }
7622fc06 3624
e759d426
SK
3625 case LOPT_HOST_REC: /* --host-record */
3626 {
3627 struct host_record *new = opt_malloc(sizeof(struct host_record));
3628 memset(new, 0, sizeof(struct host_record));
3629
3630 if (!arg || !(comma = split(arg)))
c4a7f90e
SK
3631 ret_err(_("Bad host-record"));
3632
3633 while (arg)
3634 {
3635 struct all_addr addr;
3636 if (inet_pton(AF_INET, arg, &addr))
3637 new->addr = addr.addr.addr4;
e759d426 3638#ifdef HAVE_IPV6
c4a7f90e
SK
3639 else if (inet_pton(AF_INET6, arg, &addr))
3640 new->addr6 = addr.addr.addr6;
e759d426 3641#endif
c4a7f90e
SK
3642 else
3643 {
3644 int nomem;
3645 char *canon = canonicalise(arg, &nomem);
3646 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3647 if (!canon)
3648 ret_err(_("Bad name in host-record"));
3649
3650 nl->name = canon;
3651 /* keep order, so that PTR record goes to first name */
3652 nl->next = NULL;
3653 if (!new->names)
3654 new->names = nl;
3655 else
3656 {
3657 struct name_list *tmp;
3658 for (tmp = new->names; tmp->next; tmp = tmp->next);
3659 tmp->next = nl;
3660 }
c4a7f90e 3661 }
e4807d8b
SK
3662
3663 arg = comma;
3664 comma = split(arg);
c4a7f90e 3665 }
e759d426
SK
3666
3667 /* Keep list order */
3668 if (!daemon->host_records_tail)
3669 daemon->host_records = new;
3670 else
3671 daemon->host_records_tail->next = new;
3672 new->next = NULL;
3673 daemon->host_records_tail = new;
3674 break;
3675 }
0fc2f313
SK
3676
3677#ifdef HAVE_DNSSEC
3678 case LOPT_DNSKEY:
3679 {
3680 struct dnskey *new = opt_malloc(sizeof(struct dnskey));
3681 char *key64, *algo;
3682
3683 if (!(comma = split(arg)) || !(algo = split(comma)) || !(key64 = split(algo)) ||
3684 !atoi_check16(comma, &new->flags) || !atoi_check16(algo, &new->algo) ||
3685 !(new->name = canonicalise_opt(arg)))
3686 ret_err(_("bad DNSKEY"));
3687
3688
3689 /* Upper bound on length */
86bec2d3 3690 new->key = opt_malloc((3*strlen(key64)/4)+1);
0fc2f313
SK
3691 unhide_metas(key64);
3692 if ((new->keylen = parse_base64(key64, new->key)) == -1)
3693 ret_err(_("bad base64 in DNSKEY"));
3694
3695 new->next = daemon->dnskeys;
3696 daemon->dnskeys = new;
3697
3698 break;
3699 }
3700#endif
3701
7622fc06 3702 default:
0fc2f313 3703 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
c4a7f90e 3704
849a8357 3705 }
824af85b 3706
c4a7f90e 3707 return 1;
849a8357
SK
3708}
3709
28866e95 3710static void read_file(char *file, FILE *f, int hard_opt)
849a8357 3711{
824af85b 3712 volatile int lineno = 0;
8ef5ada2 3713 char *buff = daemon->namebuff;
849a8357
SK
3714
3715 while (fgets(buff, MAXDNAME, f))
3716 {
611ebc5f
SK
3717 int white, i, option = hard_opt;
3718 char *errmess, *p, *arg = NULL, *start;
8ef5ada2 3719 size_t len;
832af0ba 3720
824af85b 3721 /* Memory allocation failure longjmps here if mem_recover == 1 */
611ebc5f 3722 if (option != 0)
824af85b
SK
3723 {
3724 if (setjmp(mem_jmp))
3725 continue;
3726 mem_recover = 1;
3727 }
3728
849a8357 3729 lineno++;
824af85b
SK
3730 errmess = NULL;
3731
849a8357
SK
3732 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3733 metacharacters get hidden also strip comments */
8ef5ada2 3734 for (white = 1, p = buff; *p; p++)
849a8357
SK
3735 {
3736 if (*p == '"')
3737 {
3738 memmove(p, p+1, strlen(p+1)+1);
8ef5ada2 3739
849a8357
SK
3740 for(; *p && *p != '"'; p++)
3741 {
5aabfc78 3742 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
849a8357
SK
3743 {
3744 if (p[1] == 't')
3745 p[1] = '\t';
3746 else if (p[1] == 'n')
3747 p[1] = '\n';
849a8357
SK
3748 else if (p[1] == 'b')
3749 p[1] = '\b';
3750 else if (p[1] == 'r')
3751 p[1] = '\r';
6b01084f
SK
3752 else if (p[1] == 'e') /* escape */
3753 p[1] = '\033';
849a8357
SK
3754 memmove(p, p+1, strlen(p+1)+1);
3755 }
3756 *p = hide_meta(*p);
3757 }
8ef5ada2
SK
3758
3759 if (*p == 0)
f2621c7f
SK
3760 {
3761 errmess = _("missing \"");
3762 goto oops;
3763 }
8ef5ada2
SK
3764
3765 memmove(p, p+1, strlen(p+1)+1);
849a8357 3766 }
f2621c7f 3767
8ef5ada2
SK
3768 if (isspace(*p))
3769 {
3770 *p = ' ';
3771 white = 1;
9e4abcb5 3772 }
8ef5ada2
SK
3773 else
3774 {
3775 if (white && *p == '#')
3776 {
3777 *p = 0;
3778 break;
3779 }
3780 white = 0;
3781 }
849a8357
SK
3782 }
3783
8ef5ada2
SK
3784
3785 /* strip leading spaces */
3786 for (start = buff; *start && *start == ' '; start++);
3787
3788 /* strip trailing spaces */
3789 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3790
3791 if (len == 0)
849a8357 3792 continue;
8ef5ada2
SK
3793 else
3794 start[len] = 0;
3795
611ebc5f 3796 if (option != 0)
8ef5ada2
SK
3797 arg = start;
3798 else if ((p=strchr(start, '=')))
849a8357
SK
3799 {
3800 /* allow spaces around "=" */
8ef5ada2
SK
3801 for (arg = p+1; *arg == ' '; arg++);
3802 for (; p >= start && (*p == ' ' || *p == '='); p--)
849a8357 3803 *p = 0;
9e4abcb5 3804 }
849a8357
SK
3805 else
3806 arg = NULL;
832af0ba 3807
611ebc5f 3808 if (option == 0)
5aabfc78 3809 {
5aabfc78
SK
3810 for (option = 0, i = 0; opts[i].name; i++)
3811 if (strcmp(opts[i].name, start) == 0)
3812 {
3813 option = opts[i].val;
3814 break;
3815 }
3816
3817 if (!option)
3818 errmess = _("bad option");
3819 else if (opts[i].has_arg == 0 && arg)
3820 errmess = _("extraneous parameter");
3821 else if (opts[i].has_arg == 1 && !arg)
3822 errmess = _("missing parameter");
3823 }
c4a7f90e
SK
3824
3825 oops:
832af0ba 3826 if (errmess)
c4a7f90e
SK
3827 strcpy(daemon->namebuff, errmess);
3828
3829 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
f2621c7f 3830 {
c4a7f90e 3831 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
824af85b 3832 if (hard_opt != 0)
c4a7f90e 3833 my_syslog(LOG_ERR, "%s", daemon->namebuff);
5aabfc78 3834 else
c4a7f90e 3835 die("%s", daemon->namebuff, EC_BADCONF);
f2621c7f 3836 }
849a8357
SK
3837 }
3838
8ef5ada2 3839 mem_recover = 0;
849a8357
SK
3840 fclose(f);
3841}
3842
395eb719 3843static int one_file(char *file, int hard_opt)
28866e95
SK
3844{
3845 FILE *f;
3846 int nofile_ok = 0;
3847 static int read_stdin = 0;
3848 static struct fileread {
3849 dev_t dev;
3850 ino_t ino;
3851 struct fileread *next;
3852 } *filesread = NULL;
3853
3854 if (hard_opt == '7')
3855 {
3856 /* default conf-file reading */
3857 hard_opt = 0;
3858 nofile_ok = 1;
3859 }
3860
3861 if (hard_opt == 0 && strcmp(file, "-") == 0)
3862 {
3863 if (read_stdin == 1)
395eb719 3864 return 1;
28866e95
SK
3865 read_stdin = 1;
3866 file = "stdin";
3867 f = stdin;
3868 }
3869 else
3870 {
3871 /* ignore repeated files. */
3872 struct stat statbuf;
3873
3874 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3875 {
3876 struct fileread *r;
3877
3878 for (r = filesread; r; r = r->next)
3879 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
395eb719 3880 return 1;
28866e95
SK
3881
3882 r = safe_malloc(sizeof(struct fileread));
3883 r->next = filesread;
3884 filesread = r;
3885 r->dev = statbuf.st_dev;
3886 r->ino = statbuf.st_ino;
3887 }
3888
3889 if (!(f = fopen(file, "r")))
3890 {
3891 if (errno == ENOENT && nofile_ok)
395eb719 3892 return 1; /* No conffile, all done. */
28866e95
SK
3893 else
3894 {
3895 char *str = _("cannot read %s: %s");
3896 if (hard_opt != 0)
3897 {
3898 my_syslog(LOG_ERR, str, file, strerror(errno));
395eb719 3899 return 0;
28866e95
SK
3900 }
3901 else
3902 die(str, file, EC_FILE);
3903 }
3904 }
3905 }
3906
3907 read_file(file, f, hard_opt);
395eb719 3908 return 1;
28866e95
SK
3909}
3910
3911/* expand any name which is a directory */
3912struct hostsfile *expand_filelist(struct hostsfile *list)
3913{
3914 int i;
3915 struct hostsfile *ah;
3916
3917 for (i = 0, ah = list; ah; ah = ah->next)
3918 {
3919 if (i <= ah->index)
3920 i = ah->index + 1;
3921
3922 if (ah->flags & AH_DIR)
3923 ah->flags |= AH_INACTIVE;
3924 else
3925 ah->flags &= ~AH_INACTIVE;
3926 }
3927
3928 for (ah = list; ah; ah = ah->next)
3929 if (!(ah->flags & AH_INACTIVE))
3930 {
3931 struct stat buf;
3932 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3933 {
3934 DIR *dir_stream;
3935 struct dirent *ent;
3936
3937 /* don't read this as a file */
3938 ah->flags |= AH_INACTIVE;
3939
3940 if (!(dir_stream = opendir(ah->fname)))
3941 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3942 ah->fname, strerror(errno));
3943 else
3944 {
3945 while ((ent = readdir(dir_stream)))
3946 {
3947 size_t lendir = strlen(ah->fname);
3948 size_t lenfile = strlen(ent->d_name);
3949 struct hostsfile *ah1;
3950 char *path;
3951
3952 /* ignore emacs backups and dotfiles */
3953 if (lenfile == 0 ||
3954 ent->d_name[lenfile - 1] == '~' ||
3955 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3956 ent->d_name[0] == '.')
3957 continue;
3958
3959 /* see if we have an existing record.
3960 dir is ah->fname
3961 file is ent->d_name
3962 path to match is ah1->fname */
3963
3964 for (ah1 = list; ah1; ah1 = ah1->next)
3965 {
3966 if (lendir < strlen(ah1->fname) &&
3967 strstr(ah1->fname, ah->fname) == ah1->fname &&
3968 ah1->fname[lendir] == '/' &&
3969 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3970 {
3971 ah1->flags &= ~AH_INACTIVE;
3972 break;
3973 }
3974 }
3975
3976 /* make new record */
3977 if (!ah1)
3978 {
3979 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3980 continue;
3981
3982 if (!(path = whine_malloc(lendir + lenfile + 2)))
3983 {
3984 free(ah1);
3985 continue;
3986 }
3987
3988 strcpy(path, ah->fname);
3989 strcat(path, "/");
3990 strcat(path, ent->d_name);
3991 ah1->fname = path;
3992 ah1->index = i++;
3993 ah1->flags = AH_DIR;
3994 ah1->next = list;
3995 list = ah1;
3996 }
3997
3998 /* inactivate record if not regular file */
3999 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
4000 ah1->flags |= AH_INACTIVE;
4001
4002 }
4003 closedir(dir_stream);
4004 }
4005 }
4006 }
4007
4008 return list;
4009}
4010
4011
7622fc06 4012#ifdef HAVE_DHCP
824af85b
SK
4013void reread_dhcp(void)
4014{
28866e95
SK
4015 struct hostsfile *hf;
4016
824af85b
SK
4017 if (daemon->dhcp_hosts_file)
4018 {
4019 struct dhcp_config *configs, *cp, **up;
28866e95 4020
824af85b
SK
4021 /* remove existing... */
4022 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
4023 {
4024 cp = configs->next;
4025
4026 if (configs->flags & CONFIG_BANK)
4027 {
9009d746 4028 struct hwaddr_config *mac, *tmp;
8ef5ada2 4029 struct dhcp_netid_list *list, *tmplist;
9009d746
SK
4030
4031 for (mac = configs->hwaddr; mac; mac = tmp)
4032 {
4033 tmp = mac->next;
4034 free(mac);
4035 }
8ef5ada2 4036
824af85b
SK
4037 if (configs->flags & CONFIG_CLID)
4038 free(configs->clid);
8ef5ada2
SK
4039
4040 for (list = configs->netid; list; list = tmplist)
4041 {
4042 free(list->list);
4043 tmplist = list->next;
4044 free(list);
4045 }
4046
824af85b
SK
4047 if (configs->flags & CONFIG_NAME)
4048 free(configs->hostname);
4049
4050 *up = configs->next;
4051 free(configs);
4052 }
4053 else
4054 up = &configs->next;
4055 }
4056
28866e95
SK
4057 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
4058 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
4059 if (!(hf->flags & AH_INACTIVE))
4060 {
395eb719
SK
4061 if (one_file(hf->fname, LOPT_BANK))
4062 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 4063 }
824af85b
SK
4064 }
4065
4066 if (daemon->dhcp_opts_file)
4067 {
4068 struct dhcp_opt *opts, *cp, **up;
4069 struct dhcp_netid *id, *next;
4070
4071 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
4072 {
4073 cp = opts->next;
4074
4075 if (opts->flags & DHOPT_BANK)
4076 {
73a08a24
SK
4077 if ((opts->flags & DHOPT_VENDOR))
4078 free(opts->u.vendor_class);
824af85b
SK
4079 free(opts->val);
4080 for (id = opts->netid; id; id = next)
4081 {
4082 next = id->next;
4083 free(id->net);
4084 free(id);
4085 }
4086 *up = opts->next;
4087 free(opts);
4088 }
4089 else
4090 up = &opts->next;
4091 }
4092
28866e95
SK
4093 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
4094 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
4095 if (!(hf->flags & AH_INACTIVE))
4096 {
395eb719
SK
4097 if (one_file(hf->fname, LOPT_OPTS))
4098 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 4099 }
824af85b
SK
4100 }
4101}
7622fc06 4102#endif
824af85b 4103
5aabfc78 4104void read_opts(int argc, char **argv, char *compile_opts)
849a8357 4105{
824af85b 4106 char *buff = opt_malloc(MAXDNAME);
28866e95 4107 int option, conffile_opt = '7', testmode = 0;
c4a7f90e 4108 char *arg, *conffile = CONFFILE;
849a8357
SK
4109
4110 opterr = 0;
5aabfc78 4111
824af85b 4112 daemon = opt_malloc(sizeof(struct daemon));
849a8357
SK
4113 memset(daemon, 0, sizeof(struct daemon));
4114 daemon->namebuff = buff;
4115
4116 /* Set defaults - everything else is zero or NULL */
4117 daemon->cachesize = CACHESIZ;
208b65c5 4118 daemon->ftabsize = FTABSIZ;
849a8357 4119 daemon->port = NAMESERVER_PORT;
9e038946
SK
4120 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
4121 daemon->dhcp_server_port = DHCP_SERVER_PORT;
849a8357
SK
4122 daemon->default_resolv.is_default = 1;
4123 daemon->default_resolv.name = RESOLVFILE;
4124 daemon->resolv_files = &daemon->default_resolv;
4125 daemon->username = CHUSER;
849a8357
SK
4126 daemon->runfile = RUNFILE;
4127 daemon->dhcp_max = MAXLEASES;
832af0ba 4128 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
849a8357
SK
4129 daemon->edns_pktsz = EDNS_PKTSZ;
4130 daemon->log_fac = -1;
4f7b304f
SK
4131 daemon->auth_ttl = AUTH_TTL;
4132 daemon->soa_refresh = SOA_REFRESH;
4133 daemon->soa_retry = SOA_RETRY;
4134 daemon->soa_expiry = SOA_EXPIRY;
5aabfc78
SK
4135 add_txt("version.bind", "dnsmasq-" VERSION );
4136 add_txt("authors.bind", "Simon Kelley");
4137 add_txt("copyright.bind", COPYRIGHT);
849a8357
SK
4138
4139 while (1)
4140 {
26128d27 4141#ifdef HAVE_GETOPT_LONG
849a8357 4142 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
26128d27 4143#else
849a8357 4144 option = getopt(argc, argv, OPTSTRING);
26128d27 4145#endif
849a8357
SK
4146
4147 if (option == -1)
28866e95 4148 {
572b41eb
SK
4149 for (; optind < argc; optind++)
4150 {
4151 unsigned char *c = (unsigned char *)argv[optind];
4152 for (; *c != 0; c++)
4153 if (!isspace(*c))
4154 die(_("junk found in command line"), NULL, EC_BADCONF);
4155 }
28866e95
SK
4156 break;
4157 }
4158
849a8357
SK
4159 /* Copy optarg so that argv doesn't get changed */
4160 if (optarg)
4161 {
4162 strncpy(buff, optarg, MAXDNAME);
4163 buff[MAXDNAME-1] = 0;
4164 arg = buff;
9e4abcb5 4165 }
849a8357
SK
4166 else
4167 arg = NULL;
9e4abcb5 4168
849a8357 4169 /* command-line only stuff */
7622fc06
SK
4170 if (option == LOPT_TEST)
4171 testmode = 1;
4172 else if (option == 'w')
849a8357 4173 {
7622fc06 4174#ifdef HAVE_DHCP
4cb1b320 4175 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
7622fc06 4176 display_opts();
4cb1b320
SK
4177#ifdef HAVE_DHCP6
4178 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4179 display_opts6();
7622fc06 4180#endif
4cb1b320 4181 else
7622fc06 4182#endif
4cb1b320
SK
4183 do_usage();
4184
849a8357
SK
4185 exit(0);
4186 }
4187 else if (option == 'v')
4188 {
4189 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
c72daea8 4190 printf(_("Compile time options: %s\n\n"), compile_opts);
849a8357
SK
4191 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4192 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
824af85b 4193 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
849a8357
SK
4194 exit(0);
4195 }
4196 else if (option == 'C')
4197 {
28866e95 4198 conffile_opt = 0; /* file must exist */
824af85b 4199 conffile = opt_string_alloc(arg);
849a8357
SK
4200 }
4201 else
4202 {
4203#ifdef HAVE_GETOPT_LONG
c4a7f90e 4204 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
849a8357 4205#else
c4a7f90e 4206 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
849a8357 4207#endif
c4a7f90e 4208 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
849a8357
SK
4209 }
4210 }
4211
4212 if (conffile)
28866e95 4213 one_file(conffile, conffile_opt);
849a8357 4214
1a6bca81 4215 /* port might not be known when the address is parsed - fill in here */
3be34541 4216 if (daemon->servers)
9e4abcb5
SK
4217 {
4218 struct server *tmp;
3be34541 4219 for (tmp = daemon->servers; tmp; tmp = tmp->next)
9e4abcb5
SK
4220 if (!(tmp->flags & SERV_HAS_SOURCE))
4221 {
4222 if (tmp->source_addr.sa.sa_family == AF_INET)
3be34541 4223 tmp->source_addr.in.sin_port = htons(daemon->query_port);
9e4abcb5
SK
4224#ifdef HAVE_IPV6
4225 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3be34541 4226 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
5aabfc78
SK
4227#endif
4228 }
9e4abcb5
SK
4229 }
4230
3be34541 4231 if (daemon->if_addrs)
9e4abcb5
SK
4232 {
4233 struct iname *tmp;
3be34541 4234 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
9e4abcb5 4235 if (tmp->addr.sa.sa_family == AF_INET)
3be34541 4236 tmp->addr.in.sin_port = htons(daemon->port);
9e4abcb5
SK
4237#ifdef HAVE_IPV6
4238 else if (tmp->addr.sa.sa_family == AF_INET6)
3be34541 4239 tmp->addr.in6.sin6_port = htons(daemon->port);
9e4abcb5
SK
4240#endif /* IPv6 */
4241 }
4f7b304f
SK
4242
4243 /* create default, if not specified */
4244 if (daemon->authserver && !daemon->hostmaster)
4245 {
4246 strcpy(buff, "hostmaster.");
4247 strcat(buff, daemon->authserver);
4248 daemon->hostmaster = opt_string_alloc(buff);
4249 }
4250
f6b7dc47 4251 /* only one of these need be specified: the other defaults to the host-name */
28866e95 4252 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
9e4abcb5 4253 {
0a852541
SK
4254 struct mx_srv_record *mx;
4255
9e4abcb5 4256 if (gethostname(buff, MAXDNAME) == -1)
5aabfc78 4257 die(_("cannot get host-name: %s"), NULL, EC_MISC);
f6b7dc47 4258
0a852541
SK
4259 for (mx = daemon->mxnames; mx; mx = mx->next)
4260 if (!mx->issrv && hostname_isequal(mx->name, buff))
4261 break;
4262
28866e95 4263 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
de37951c 4264 {
824af85b 4265 mx = opt_malloc(sizeof(struct mx_srv_record));
91dccd09
SK
4266 mx->next = daemon->mxnames;
4267 mx->issrv = 0;
4268 mx->target = NULL;
824af85b 4269 mx->name = opt_string_alloc(buff);
91dccd09 4270 daemon->mxnames = mx;
f6b7dc47 4271 }
9e4abcb5 4272
3be34541 4273 if (!daemon->mxtarget)
824af85b 4274 daemon->mxtarget = opt_string_alloc(buff);
0a852541
SK
4275
4276 for (mx = daemon->mxnames; mx; mx = mx->next)
4277 if (!mx->issrv && !mx->target)
4278 mx->target = daemon->mxtarget;
9e4abcb5 4279 }
f6b7dc47 4280
28866e95 4281 if (!option_bool(OPT_NO_RESOLV) &&
208b65c5
SK
4282 daemon->resolv_files &&
4283 daemon->resolv_files->next &&
28866e95 4284 option_bool(OPT_NO_POLL))
5aabfc78 4285 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
de37951c 4286
28866e95 4287 if (option_bool(OPT_RESOLV_DOMAIN))
de37951c
SK
4288 {
4289 char *line;
849a8357
SK
4290 FILE *f;
4291
28866e95 4292 if (option_bool(OPT_NO_RESOLV) ||
208b65c5
SK
4293 !daemon->resolv_files ||
4294 (daemon->resolv_files)->next)
5aabfc78 4295 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
de37951c 4296
3be34541 4297 if (!(f = fopen((daemon->resolv_files)->name, "r")))
5aabfc78 4298 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
de37951c
SK
4299
4300 while ((line = fgets(buff, MAXDNAME, f)))
4301 {
4302 char *token = strtok(line, " \t\n\r");
4303
4304 if (!token || strcmp(token, "search") != 0)
4305 continue;
4306
4307 if ((token = strtok(NULL, " \t\n\r")) &&
1f15b81d 4308 (daemon->domain_suffix = canonicalise_opt(token)))
de37951c
SK
4309 break;
4310 }
3be34541 4311
de37951c 4312 fclose(f);
8a911ccc 4313
3be34541 4314 if (!daemon->domain_suffix)
5aabfc78 4315 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
de37951c 4316 }
3d8df260
SK
4317
4318 if (daemon->domain_suffix)
4319 {
4320 /* add domain for any srv record without one. */
4321 struct mx_srv_record *srv;
de37951c 4322
3d8df260
SK
4323 for (srv = daemon->mxnames; srv; srv = srv->next)
4324 if (srv->issrv &&
4325 strchr(srv->name, '.') &&
4326 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4327 {
4328 strcpy(buff, srv->name);
4329 strcat(buff, ".");
4330 strcat(buff, daemon->domain_suffix);
4331 free(srv->name);
824af85b 4332 srv->name = opt_string_alloc(buff);
3d8df260
SK
4333 }
4334 }
28866e95 4335 else if (option_bool(OPT_DHCP_FQDN))
9009d746 4336 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
7622fc06
SK
4337
4338 if (testmode)
4339 {
4340 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4341 exit(0);
4342 }
849a8357 4343}