source: src/router/dnsmasq/src/option.c @ 31703

Last change on this file since 31703 was 31703, checked in by brainslayer, 5 days ago

latest dnsmasq

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