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

Last change on this file since 31441 was 31441, checked in by brainslayer, 4 months ago

latest dnsmasq code

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