1/* dnsmasq is Copyright (c) 2000-2009 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 void one_file(char *file, int nest, 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
106#ifdef HAVE_GETOPT_LONG
107static const struct option opts[] =
108#else
109static const struct myoption opts[] =
110#endif
111  {
112    { "version", 0, 0, 'v' },
113    { "no-hosts", 0, 0, 'h' },
114    { "no-poll", 0, 0, 'n' },
115    { "help", 0, 0, 'w' },
116    { "no-daemon", 0, 0, 'd' },
117    { "log-queries", 0, 0, 'q' },
118    { "user", 2, 0, 'u' },
119    { "group", 2, 0, 'g' },
120    { "resolv-file", 2, 0, 'r' },
121    { "mx-host", 1, 0, 'm' },
122    { "mx-target", 1, 0, 't' },
123    { "cache-size", 2, 0, 'c' },
124    { "port", 1, 0, 'p' },
125    { "dhcp-leasefile", 2, 0, 'l' },
126    { "dhcp-lease", 1, 0, 'l' },
127    { "dhcp-host", 1, 0, 'G' },
128    { "dhcp-range", 1, 0, 'F' },
129    { "dhcp-option", 1, 0, 'O' },
130    { "dhcp-boot", 1, 0, 'M' },
131    { "domain", 1, 0, 's' },
132    { "domain-suffix", 1, 0, 's' },
133    { "interface", 1, 0, 'i' },
134    { "listen-address", 1, 0, 'a' },
135    { "bogus-priv", 0, 0, 'b' },
136    { "bogus-nxdomain", 1, 0, 'B' },
137    { "selfmx", 0, 0, 'e' },
138    { "filterwin2k", 0, 0, 'f' },
139    { "pid-file", 2, 0, 'x' },
140    { "strict-order", 0, 0, 'o' },
141    { "server", 1, 0, 'S' },
142    { "local", 1, 0, LOPT_LOCAL },
143    { "address", 1, 0, 'A' },
144    { "conf-file", 2, 0, 'C' },
145    { "no-resolv", 0, 0, 'R' },
146    { "expand-hosts", 0, 0, 'E' },
147    { "localmx", 0, 0, 'L' },
148    { "local-ttl", 1, 0, 'T' },
149    { "no-negcache", 0, 0, 'N' },
150    { "addn-hosts", 1, 0, 'H' },
151    { "query-port", 1, 0, 'Q' },
152    { "except-interface", 1, 0, 'I' },
153    { "no-dhcp-interface", 1, 0, '2' },
154    { "domain-needed", 0, 0, 'D' },
155    { "dhcp-lease-max", 1, 0, 'X' },
156    { "bind-interfaces", 0, 0, 'z' },
157    { "read-ethers", 0, 0, 'Z' },
158    { "alias", 1, 0, 'V' },
159    { "dhcp-vendorclass", 1, 0, 'U' },
160    { "dhcp-userclass", 1, 0, 'j' },
161    { "dhcp-ignore", 1, 0, 'J' },
162    { "edns-packet-max", 1, 0, 'P' },
163    { "keep-in-foreground", 0, 0, 'k' },
164    { "dhcp-authoritative", 0, 0, 'K' },
165    { "srv-host", 1, 0, 'W' },
166    { "localise-queries", 0, 0, 'y' },
167    { "txt-record", 1, 0, 'Y' },
168    { "enable-dbus", 0, 0, '1' },
169    { "bootp-dynamic", 2, 0, '3' },
170    { "dhcp-mac", 1, 0, '4' },
171    { "no-ping", 0, 0, '5' },
172    { "dhcp-script", 1, 0, '6' },
173    { "conf-dir", 1, 0, '7' },
174    { "log-facility", 1, 0 ,'8' },
175    { "leasefile-ro", 0, 0, '9' },
176    { "dns-forward-max", 1, 0, '0' },
177    { "clear-on-reload", 0, 0, LOPT_RELOAD },
178    { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
179    { "enable-tftp", 0, 0, LOPT_TFTP },
180    { "tftp-secure", 0, 0, LOPT_SECURE },
181    { "tftp-unique-root", 0, 0, LOPT_APREF },
182    { "tftp-root", 1, 0, LOPT_PREFIX },
183    { "tftp-max", 1, 0, LOPT_TFTP_MAX },
184    { "ptr-record", 1, 0, LOPT_PTR },
185    { "naptr-record", 1, 0, LOPT_NAPTR },
186    { "bridge-interface", 1, 0 , LOPT_BRIDGE },
187    { "dhcp-option-force", 1, 0, LOPT_FORCE },
188    { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
189    { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
190    { "log-async", 2, 0, LOPT_MAX_LOGS },
191    { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
192    { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
193    { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
194    { "interface-name", 1, 0, LOPT_INTNAME },
195    { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
196    { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
197    { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
198    { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
199    { "stop-dns-rebind", 0, 0, LOPT_REBIND },
200    { "all-servers", 0, 0, LOPT_NOLAST },
201    { "dhcp-match", 1, 0, LOPT_MATCH },
202    { "dhcp-broadcast", 1, 0, LOPT_BROADCAST },
203    { "neg-ttl", 1, 0, LOPT_NEGTTL },
204    { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
205    { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
206    { "min-port", 1, 0, LOPT_MINPORT },
207    { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
208    { "cname", 1, 0, LOPT_CNAME },
209    { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
210    { "pxe-service", 1, 0, LOPT_PXE_SERV },
211    { "test", 0, 0, LOPT_TEST },
212    { NULL, 0, 0, 0 }
213  };
214
215/* These must have more the one '1' bit */
216#define ARG_DUP       3
217#define ARG_ONE       5
218#define ARG_USED_CL   7
219#define ARG_USED_FILE 9
220
221static struct {
222  int opt;
223  unsigned int rept;
224  char * const flagdesc;
225  char * const desc;
226  char * const arg;
227} usage[] = {
228  { 'a', ARG_DUP, "ipaddr",  gettext_noop("Specify local address(es) to listen on."), NULL },
229  { 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
230  { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
231  { 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
232  { 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
233  { 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
234  { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
235  { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
236  { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
237  { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
238  { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
239  { 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
240  { 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
241  { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
242  { LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
243  { LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL },
244  { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
245  { 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
246  { 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
247  { 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
248  { 'j', ARG_DUP, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
249  { LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
250  { LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
251  { LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
252  { 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
253  { LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
254  { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
255  { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
256  { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
257  { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
258  { 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
259  { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
260  { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
261  { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
262  { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
263  { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
264  { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
265  { 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
266  { 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
267  { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
268  { 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
269  { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
270  { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
271  { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
272  { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
273  { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
274  { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
275  { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
276  { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
277  { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
278  { 'U', ARG_DUP, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
279  { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
280  { 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
281  { 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
282  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
283  { 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
284  { 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
285  { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
286  { 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
287  { LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL },
288  { LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
289  { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
290  { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
291  { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
292  { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
293  { '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
294  { '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
295  { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
296  { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
297  { '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
298  { '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
299  { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
300  { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
301  { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
302  { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
303  { LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
304  { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
305  { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
306  { LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
307  { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
308  { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
309  { LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
310  { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
311  { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
312  { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
313  { LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
314  { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
315  { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
316  { LOPT_MATCH, ARG_DUP, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
317  { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
318  { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
319  { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
320  { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
321  { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
322  { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
323  { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
324  { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
325  { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
326  { 0, 0, NULL, NULL, NULL }
327};
328
329#ifdef HAVE_DHCP
330/* makes options which take a list of addresses */
331#define OT_ADDR_LIST 0x80
332/* DHCP-internal options, for logging. not valid in config file */
333#define OT_INTERNAL 0x40
334#define OT_NAME 0x20
335
336static const struct {
337  char *name;
338  unsigned char val, size;
339} opttab[] = {
340  { "netmask", 1, OT_ADDR_LIST },
341  { "time-offset", 2, 4 },
342  { "router", 3, OT_ADDR_LIST  },
343  { "dns-server", 6, OT_ADDR_LIST },
344  { "log-server", 7, OT_ADDR_LIST },
345  { "lpr-server", 9, OT_ADDR_LIST },
346  { "hostname", 12, OT_INTERNAL | OT_NAME },
347  { "boot-file-size", 13, 2 },
348  { "domain-name", 15, OT_NAME },
349  { "swap-server", 16, OT_ADDR_LIST },
350  { "root-path", 17, 0 },
351  { "extension-path", 18, 0 },
352  { "ip-forward-enable", 19, 1 },
353  { "non-local-source-routing", 20, 1 },
354  { "policy-filter", 21, OT_ADDR_LIST },
355  { "max-datagram-reassembly", 22, 2 },
356  { "default-ttl", 23, 1 },
357  { "mtu", 26, 2 },
358  { "all-subnets-local", 27, 1 },
359  { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
360  { "router-discovery", 31, 1 },
361  { "router-solicitation", 32, OT_ADDR_LIST },
362  { "static-route", 33, OT_ADDR_LIST },
363  { "trailer-encapsulation", 34, 1 },
364  { "arp-timeout", 35, 4 },
365  { "ethernet-encap", 36, 1 },
366  { "tcp-ttl", 37, 1 },
367  { "tcp-keepalive", 38, 4 },
368  { "nis-domain", 40, 0 },
369  { "nis-server", 41, OT_ADDR_LIST },
370  { "ntp-server", 42, OT_ADDR_LIST },
371  { "vendor-encap", 43, OT_INTERNAL },
372  { "netbios-ns", 44, OT_ADDR_LIST },
373  { "netbios-dd", 45, OT_ADDR_LIST },
374  { "netbios-nodetype", 46, 1 },
375  { "netbios-scope", 47, 0 },
376  { "x-windows-fs", 48, OT_ADDR_LIST },
377  { "x-windows-dm", 49, OT_ADDR_LIST },
378  { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
379  { "lease-time", 51, OT_INTERNAL },
380  { "option-overload", 52, OT_INTERNAL },
381  { "message-type", 53, OT_INTERNAL, },
382  { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
383  { "parameter-request", 55, OT_INTERNAL },
384  { "message", 56, OT_INTERNAL },
385  { "max-message-size", 57, OT_INTERNAL },
386  { "T1", 58, OT_INTERNAL },
387  { "T2", 59, OT_INTERNAL },
388  { "vendor-class", 60, 0 },
389  { "client-id", 61,OT_INTERNAL },
390  { "nis+-domain", 64, 0 },
391  { "nis+-server", 65, OT_ADDR_LIST },
392  { "tftp-server", 66, 0 },
393  { "bootfile-name", 67, 0 },
394  { "mobile-ip-home", 68, OT_ADDR_LIST },
395  { "smtp-server", 69, OT_ADDR_LIST },
396  { "pop3-server", 70, OT_ADDR_LIST },
397  { "nntp-server", 71, OT_ADDR_LIST },
398  { "irc-server", 74, OT_ADDR_LIST },
399  { "user-class", 77, 0 },
400  { "FQDN", 81, OT_INTERNAL },
401  { "agent-id", 82, OT_INTERNAL },
402  { "client-arch", 93, 2 },
403  { "client-interface-id", 94, 0 },
404  { "client-machine-id", 97, 0 },
405  { "subnet-select", 118, OT_INTERNAL },
406  { "domain-search", 119, 0 },
407  { "sip-server", 120, 0 },
408  { "classless-static-route", 121, 0 },
409  { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
410  { NULL, 0, 0 }
411};
412
413char *option_string(unsigned char opt, int *is_ip, int *is_name)
414{
415  int i;
416
417  for (i = 0; opttab[i].name; i++)
418    if (opttab[i].val == opt)
419      {
420	if (is_ip)
421	  *is_ip = !!(opttab[i].size & OT_ADDR_LIST);
422	if (is_name)
423	  *is_name = !!(opttab[i].size & OT_NAME);
424	return opttab[i].name;
425      }
426
427  return NULL;
428}
429
430#endif
431
432/* We hide metacharaters in quoted strings by mapping them into the ASCII control
433   character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
434   following sequence so that they map to themselves: it is therefore possible to call
435   unhide_metas repeatedly on string without breaking things.
436   The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
437   couple of other places.
438   Note that space is included here so that
439   --dhcp-option=3, string
440   has five characters, whilst
441   --dhcp-option=3," string"
442   has six.
443*/
444
445static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
446
447static char hide_meta(char c)
448{
449  unsigned int i;
450
451  for (i = 0; i < (sizeof(meta) - 1); i++)
452    if (c == meta[i])
453      return (char)i;
454
455  return c;
456}
457
458static char unhide_meta(char cr)
459{
460  unsigned int c = cr;
461
462  if (c < (sizeof(meta) - 1))
463    cr = meta[c];
464
465  return cr;
466}
467
468static void unhide_metas(char *cp)
469{
470  if (cp)
471    for(; *cp; cp++)
472      *cp = unhide_meta(*cp);
473}
474
475static void *opt_malloc(size_t size)
476{
477  void *ret;
478
479  if (mem_recover)
480    {
481      ret = whine_malloc(size);
482      if (!ret)
483	longjmp(mem_jmp, 1);
484    }
485  else
486    ret = safe_malloc(size);
487
488  return ret;
489}
490
491static char *opt_string_alloc(char *cp)
492{
493  char *ret = NULL;
494
495  if (cp && strlen(cp) != 0)
496    {
497      ret = opt_malloc(strlen(cp)+1);
498      strcpy(ret, cp);
499
500      /* restore hidden metachars */
501      unhide_metas(ret);
502    }
503
504  return ret;
505}
506
507
508/* find next comma, split string with zero and eliminate spaces.
509   return start of string following comma */
510
511static char *split_chr(char *s, char c)
512{
513  char *comma, *p;
514
515  if (!s || !(comma = strchr(s, c)))
516    return NULL;
517
518  p = comma;
519  *comma = ' ';
520
521  for (; isspace((int)*comma); comma++);
522
523  for (; (p >= s) && isspace((int)*p); p--)
524    *p = 0;
525
526  return comma;
527}
528
529static char *split(char *s)
530{
531  return split_chr(s, ',');
532}
533
534static char *canonicalise_opt(char *s)
535{
536  char *ret;
537  int nomem;
538
539  if (!s)
540    return 0;
541
542  unhide_metas(s);
543  if (!(ret = canonicalise(s, &nomem)) && nomem)
544    {
545      if (mem_recover)
546	longjmp(mem_jmp, 1);
547      else
548	die(_("could not get memory"), NULL, EC_NOMEM);
549    }
550
551  return ret;
552}
553
554static int atoi_check(char *a, int *res)
555{
556  char *p;
557
558  if (!a)
559    return 0;
560
561  unhide_metas(a);
562
563  for (p = a; *p; p++)
564     if (*p < '0' || *p > '9')
565       return 0;
566
567  *res = atoi(a);
568  return 1;
569}
570
571static int atoi_check16(char *a, int *res)
572{
573  if (!(atoi_check(a, res)) ||
574      *res < 0 ||
575      *res > 0xffff)
576    return 0;
577
578  return 1;
579}
580
581static void add_txt(char *name, char *txt)
582{
583  size_t len = strlen(txt);
584  struct txt_record *r = opt_malloc(sizeof(struct txt_record));
585
586  r->name = opt_string_alloc(name);
587  r->next = daemon->txt;
588  daemon->txt = r;
589  r->class = C_CHAOS;
590  r->txt = opt_malloc(len+1);
591  r->len = len+1;
592  *(r->txt) = len;
593  memcpy((r->txt)+1, txt, len);
594}
595
596static void do_usage(void)
597{
598  char buff[100];
599  int i, j;
600
601  struct {
602    char handle;
603    int val;
604  } tab[] = {
605    { '$', CACHESIZ },
606    { '*', EDNS_PKTSZ },
607    { '&', MAXLEASES },
608    { '!', FTABSIZ },
609    { '#', TFTP_MAX_CONNECTIONS },
610    { '\0', 0 }
611  };
612
613  printf(_("Usage: dnsmasq [options]\n\n"));
614#ifndef HAVE_GETOPT_LONG
615  printf(_("Use short options only on the command line.\n"));
616#endif
617  printf(_("Valid options are:\n"));
618
619  for (i = 0; usage[i].opt != 0; i++)
620    {
621      char *desc = usage[i].flagdesc;
622      char *eq = "=";
623
624      if (!desc || *desc == '[')
625	eq = "";
626
627      if (!desc)
628	desc = "";
629
630      for ( j = 0; opts[j].name; j++)
631	if (opts[j].val == usage[i].opt)
632	  break;
633      if (usage[i].opt < 256)
634	sprintf(buff, "-%c, ", usage[i].opt);
635      else
636	sprintf(buff, "    ");
637
638      sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
639      printf("%-36.36s", buff);
640
641      if (usage[i].arg)
642	{
643	  strcpy(buff, usage[i].arg);
644	  for (j = 0; tab[j].handle; j++)
645	    if (tab[j].handle == *(usage[i].arg))
646	      sprintf(buff, "%d", tab[j].val);
647	}
648      printf(_(usage[i].desc), buff);
649      printf("\n");
650    }
651}
652
653#ifdef HAVE_DHCP
654static void display_opts(void)
655{
656  int i;
657
658  printf(_("Known DHCP options:\n"));
659
660  for (i = 0; opttab[i].name; i++)
661    if (!(opttab[i].size & OT_INTERNAL))
662      printf("%3d %s\n", opttab[i].val, opttab[i].name);
663}
664
665/* This is too insanely large to keep in-line in the switch */
666static char *parse_dhcp_opt(char *arg, int flags)
667{
668  struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
669  char lenchar = 0, *cp;
670  int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
671  char *comma = NULL, *problem = NULL;
672  struct dhcp_netid *np = NULL;
673  unsigned char opt_len = 0;
674
675  new->len = 0;
676  new->flags = flags;
677  new->netid = NULL;
678  new->val = NULL;
679  new->opt = 0;
680
681  while (arg)
682    {
683      comma = split(arg);
684
685      for (cp = arg; *cp; cp++)
686	if (*cp < '0' || *cp > '9')
687	  break;
688
689      if (!*cp)
690	{
691	  new->opt = atoi(arg);
692	  opt_len = 0;
693	  break;
694	}
695
696      if (strstr(arg, "option:") == arg)
697	{
698	  for (i = 0; opttab[i].name; i++)
699	    if (!(opttab[i].size & OT_INTERNAL) &&
700		strcasecmp(opttab[i].name, arg+7) == 0)
701	      {
702		new->opt = opttab[i].val;
703		opt_len = opttab[i].size;
704		break;
705	      }
706	  /* option:<optname> must follow tag and vendor string. */
707	  break;
708	}
709      else if (strstr(arg, "vendor:") == arg)
710	{
711	  new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
712	  new->flags |= DHOPT_VENDOR;
713	}
714      else if (strstr(arg, "encap:") == arg)
715	{
716	  new->u.encap = atoi(arg+6);
717	  new->flags |= DHOPT_ENCAPSULATE;
718	}
719      else
720	{
721	  new->netid = opt_malloc(sizeof (struct dhcp_netid));
722	  /* allow optional "net:" for consistency */
723	  if (strstr(arg, "net:") == arg)
724	    new->netid->net = opt_string_alloc(arg+4);
725	  else
726	    new->netid->net = opt_string_alloc(arg);
727	  new->netid->next = np;
728	  np = new->netid;
729	}
730
731      arg = comma;
732    }
733
734  if (new->opt == 0)
735    problem = _("bad dhcp-option");
736  else if (comma)
737    {
738      /* characterise the value */
739      char c;
740      is_addr = is_hex = is_dec = is_string = 1;
741      addrs = digs = 1;
742      dots = 0;
743      for (cp = comma; (c = *cp); cp++)
744	if (c == ',')
745	  {
746	    addrs++;
747	    is_dec = is_hex = 0;
748	  }
749	else if (c == ':')
750	  {
751	    digs++;
752	    is_dec = is_addr = 0;
753	  }
754	else if (c == '/')
755	  {
756	    is_dec = is_hex = 0;
757	    if (cp == comma) /* leading / means a pathname */
758	      is_addr = 0;
759	  }
760	else if (c == '.')
761	  {
762	    is_dec = is_hex = 0;
763	    dots++;
764	  }
765	else if (c == '-')
766	  is_hex = is_addr = 0;
767	else if (c == ' ')
768	  is_dec = is_hex = 0;
769	else if (!(c >='0' && c <= '9'))
770	  {
771	    is_addr = 0;
772	    if (cp[1] == 0 && is_dec &&
773		(c == 'b' || c == 's' || c == 'i'))
774	      {
775		lenchar = c;
776		*cp = 0;
777	      }
778	    else
779	      is_dec = 0;
780	    if (!((c >='A' && c <= 'F') ||
781		  (c >='a' && c <= 'f') ||
782		  (c == '*' && (flags & DHOPT_MATCH))))
783	      is_hex = 0;
784	  }
785
786      /* We know that some options take addresses */
787
788      if (opt_len & OT_ADDR_LIST)
789	{
790	  is_string = is_dec = is_hex = 0;
791	  if (!is_addr || dots == 0)
792	    problem = _("bad IP address");
793	}
794
795      if (is_hex && digs > 1)
796	{
797	  new->len = digs;
798	  new->val = opt_malloc(new->len);
799	  parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
800	  new->flags |= DHOPT_HEX;
801	}
802      else if (is_dec)
803	{
804	  int i, val = atoi(comma);
805	  /* assume numeric arg is 1 byte except for
806	     options where it is known otherwise.
807	     For vendor class option, we have to hack. */
808	  if (opt_len != 0)
809	    new->len = opt_len;
810	  else if (val & 0xffff0000)
811	    new->len = 4;
812	  else if (val & 0xff00)
813	    new->len = 2;
814	  else
815	    new->len = 1;
816
817	  if (lenchar == 'b')
818	    new->len = 1;
819	  else if (lenchar == 's')
820	    new->len = 2;
821	  else if (lenchar == 'i')
822	    new->len = 4;
823
824	  new->val = opt_malloc(new->len);
825	  for (i=0; i<new->len; i++)
826	    new->val[i] = val>>((new->len - i - 1)*8);
827	}
828      else if (is_addr)
829	{
830	  struct in_addr in;
831	  unsigned char *op;
832	  char *slash;
833	  /* max length of address/subnet descriptor is five bytes,
834	     add one for the option 120 enc byte too */
835	  new->val = op = opt_malloc((5 * addrs) + 1);
836	  new->flags |= DHOPT_ADDR;
837
838	  if (!(new->flags & DHOPT_ENCAPSULATE) && new->opt == 120)
839	    {
840	      *(op++) = 1; /* RFC 3361 "enc byte" */
841	      new->flags &= ~DHOPT_ADDR;
842	    }
843	  while (addrs--)
844	    {
845	      cp = comma;
846	      comma = split(cp);
847	      slash = split_chr(cp, '/');
848	      in.s_addr = inet_addr(cp);
849	      if (!slash)
850		{
851		  memcpy(op, &in, INADDRSZ);
852		  op += INADDRSZ;
853		}
854	      else
855		{
856		  unsigned char *p = (unsigned char *)&in;
857		  int netsize = atoi(slash);
858		  *op++ = netsize;
859		  if (netsize > 0)
860		    *op++ = *p++;
861		  if (netsize > 8)
862		    *op++ = *p++;
863		  if (netsize > 16)
864		    *op++ = *p++;
865		  if (netsize > 24)
866		    *op++ = *p++;
867		  new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
868		}
869	    }
870	  new->len = op - new->val;
871	}
872      else if (is_string)
873	{
874	  /* text arg */
875	  if ((new->opt == 119 || new->opt == 120) && !(new->flags & DHOPT_ENCAPSULATE))
876	    {
877	      /* dns search, RFC 3397, or SIP, RFC 3361 */
878	      unsigned char *q, *r, *tail;
879	      unsigned char *p, *m = NULL, *newp;
880	      size_t newlen, len = 0;
881	      int header_size = (new->opt == 119) ? 0 : 1;
882
883	      arg = comma;
884	      comma = split(arg);
885
886	      while (arg && *arg)
887		{
888		  char *dom;
889		  if (!(dom = arg = canonicalise_opt(arg)))
890		    {
891		      problem = _("bad domain in dhcp-option");
892		      break;
893		    }
894
895		  newp = opt_malloc(len + strlen(arg) + 2 + header_size);
896		  if (m)
897		    memcpy(newp, m, header_size + len);
898		  m = newp;
899		  p = m + header_size;
900		  q = p + len;
901
902		  /* add string on the end in RFC1035 format */
903		  while (*arg)
904		    {
905		      unsigned char *cp = q++;
906		      int j;
907		      for (j = 0; *arg && (*arg != '.'); arg++, j++)
908			*q++ = *arg;
909		      *cp = j;
910		      if (*arg)
911			arg++;
912		    }
913		  *q++ = 0;
914		  free(dom);
915
916		  /* Now tail-compress using earlier names. */
917		  newlen = q - p;
918		  for (tail = p + len; *tail; tail += (*tail) + 1)
919		    for (r = p; r - p < (int)len; r += (*r) + 1)
920		      if (strcmp((char *)r, (char *)tail) == 0)
921			{
922			  PUTSHORT((r - p) | 0xc000, tail);
923			  newlen = tail - p;
924			  goto end;
925			}
926		end:
927		  len = newlen;
928
929		  arg = comma;
930		  comma = split(arg);
931		}
932
933	      /* RFC 3361, enc byte is zero for names */
934	      if (new->opt == 120)
935		m[0] = 0;
936	      new->len = (int) len + header_size;
937	      new->val = m;
938	    }
939	  else
940	    {
941	      new->len = strlen(comma);
942	      /* keep terminating zero on string */
943	      new->val = (unsigned char *)opt_string_alloc(comma);
944	      new->flags |= DHOPT_STRING;
945	    }
946	}
947    }
948
949  if ((new->len > 255) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
950    problem = _("dhcp-option too long");
951
952  if (!problem)
953    {
954      if (flags == DHOPT_MATCH)
955	{
956	  if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
957	      !new->netid ||
958	      new->netid->next)
959	    problem = _("illegal dhcp-match");
960	  else
961	    {
962	      new->next = daemon->dhcp_match;
963	      daemon->dhcp_match = new;
964	    }
965	}
966      else
967	{
968	  new->next = daemon->dhcp_opts;
969	  daemon->dhcp_opts = new;
970	}
971    }
972
973  return problem;
974}
975
976#endif
977
978static char *one_opt(int option, char *arg, char *gen_prob, int nest)
979{
980  int i;
981  char *comma, *problem = NULL;;
982
983  if (option == '?')
984    return gen_prob;
985
986  for (i=0; usage[i].opt != 0; i++)
987    if (usage[i].opt == option)
988      {
989	 int rept = usage[i].rept;
990
991	 if (nest == 0)
992	   {
993	     /* command line */
994	     if (rept == ARG_USED_CL)
995	       return _("illegal repeated flag");
996	     if (rept == ARG_ONE)
997	       usage[i].rept = ARG_USED_CL;
998	   }
999	 else
1000	   {
1001	     /* allow file to override command line */
1002	     if (rept == ARG_USED_FILE)
1003	       return _("illegal repeated keyword");
1004	     if (rept == ARG_USED_CL || rept == ARG_ONE)
1005	       usage[i].rept = ARG_USED_FILE;
1006	   }
1007
1008	 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1009	   {
1010	     daemon->options |= rept;
1011	     return NULL;
1012	   }
1013
1014	 break;
1015      }
1016
1017  switch (option)
1018    {
1019    case 'C': /* --conf-file */
1020      {
1021	char *file = opt_string_alloc(arg);
1022	if (file)
1023	  {
1024	    one_file(file, nest, 0);
1025	    free(file);
1026	  }
1027	break;
1028      }
1029
1030    case '7': /* --conf-dir */
1031      {
1032	DIR *dir_stream;
1033	struct dirent *ent;
1034	char *directory, *path;
1035	struct list {
1036	  char *suffix;
1037	  struct list *next;
1038	} *ignore_suffix = NULL, *li;
1039
1040	comma = split(arg);
1041	if (!(directory = opt_string_alloc(arg)))
1042	  break;
1043
1044	for (arg = comma; arg; arg = comma)
1045	  {
1046	    comma = split(arg);
1047	    li = opt_malloc(sizeof(struct list));
1048	    li->next = ignore_suffix;
1049	    ignore_suffix = li;
1050	    /* Have to copy: buffer is overwritten */
1051	    li->suffix = opt_string_alloc(arg);
1052	  };
1053
1054	if (!(dir_stream = opendir(directory)))
1055	  die(_("cannot access directory %s: %s"), directory, EC_FILE);
1056
1057	while ((ent = readdir(dir_stream)))
1058	  {
1059	    size_t len = strlen(ent->d_name);
1060	    struct stat buf;
1061
1062	    /* ignore emacs backups and dotfiles */
1063	    if (len == 0 ||
1064		ent->d_name[len - 1] == '~' ||
1065		(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1066		ent->d_name[0] == '.')
1067	      continue;
1068
1069	    for (li = ignore_suffix; li; li = li->next)
1070	      {
1071		/* check for proscribed suffices */
1072		size_t ls = strlen(li->suffix);
1073		if (len > ls &&
1074		    strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1075		  break;
1076	      }
1077	    if (li)
1078	      continue;
1079
1080	    path = opt_malloc(strlen(directory) + len + 2);
1081	    strcpy(path, directory);
1082	    strcat(path, "/");
1083	    strcat(path, ent->d_name);
1084
1085	    if (stat(path, &buf) == -1)
1086	      die(_("cannot access %s: %s"), path, EC_FILE);
1087	    /* only reg files allowed. */
1088	    if (!S_ISREG(buf.st_mode))
1089	      continue;
1090
1091	    /* dir is one level, so files must be readable */
1092	    one_file(path, nest + 1, 0);
1093	    free(path);
1094	  }
1095
1096	closedir(dir_stream);
1097	free(directory);
1098	for(; ignore_suffix; ignore_suffix = li)
1099	  {
1100	    li = ignore_suffix->next;
1101	    free(ignore_suffix->suffix);
1102	    free(ignore_suffix);
1103	  }
1104
1105	break;
1106      }
1107
1108    case '8': /* --log-facility */
1109      /* may be a filename */
1110      if (strchr(arg, '/'))
1111	daemon->log_file = opt_string_alloc(arg);
1112      else
1113	{
1114#ifdef __ANDROID__
1115	    problem = "Android does not support log facilities";
1116#else
1117	  for (i = 0; facilitynames[i].c_name; i++)
1118	    if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1119	      break;
1120
1121	  if (facilitynames[i].c_name)
1122	    daemon->log_fac = facilitynames[i].c_val;
1123	  else
1124	    problem = "bad log facility";
1125#endif
1126	}
1127      break;
1128
1129    case 'x': /* --pid-file */
1130      daemon->runfile = opt_string_alloc(arg);
1131      break;
1132
1133    case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1134      if (daemon->dhcp_hosts_file)
1135	problem = _("only one dhcp-hostsfile allowed");
1136      else
1137	daemon->dhcp_hosts_file = opt_string_alloc(arg);
1138      break;
1139
1140    case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1141      if (daemon->dhcp_opts_file)
1142	problem = _("only one dhcp-optsfile allowed");
1143      else
1144	daemon->dhcp_opts_file = opt_string_alloc(arg);
1145      break;
1146
1147    case 'r': /* --resolv-file */
1148      {
1149	char *name = opt_string_alloc(arg);
1150	struct resolvc *new, *list = daemon->resolv_files;
1151
1152	if (list && list->is_default)
1153	  {
1154	    /* replace default resolv file - possibly with nothing */
1155	    if (name)
1156	      {
1157		list->is_default = 0;
1158		list->name = name;
1159	      }
1160	    else
1161	      list = NULL;
1162	  }
1163	else if (name)
1164	  {
1165	    new = opt_malloc(sizeof(struct resolvc));
1166	    new->next = list;
1167	    new->name = name;
1168	    new->is_default = 0;
1169	    new->mtime = 0;
1170	    new->logged = 0;
1171	    list = new;
1172	  }
1173	daemon->resolv_files = list;
1174	break;
1175      }
1176
1177    case 'm':  /* --mx-host */
1178      {
1179	int pref = 1;
1180	struct mx_srv_record *new;
1181	char *name, *target = NULL;
1182
1183	if ((comma = split(arg)))
1184	  {
1185	    char *prefstr;
1186	    if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1187	      problem = _("bad MX preference");
1188	  }
1189
1190	if (!(name = canonicalise_opt(arg)) ||
1191	    (comma && !(target = canonicalise_opt(comma))))
1192	  problem = _("bad MX name");
1193
1194	new = opt_malloc(sizeof(struct mx_srv_record));
1195	new->next = daemon->mxnames;
1196	daemon->mxnames = new;
1197	new->issrv = 0;
1198	new->name = name;
1199	new->target = target; /* may be NULL */
1200	new->weight = pref;
1201	break;
1202      }
1203
1204    case 't': /*  --mx-target */
1205      if (!(daemon->mxtarget = canonicalise_opt(arg)))
1206	problem = _("bad MX target");
1207      break;
1208
1209#ifdef HAVE_DHCP
1210    case 'l':  /* --dhcp-leasefile */
1211      daemon->lease_file = opt_string_alloc(arg);
1212      break;
1213
1214    case '6': /* --dhcp-script */
1215#  if defined(NO_FORK)
1216      problem = _("cannot run scripts under uClinux");
1217#  elif !defined(HAVE_SCRIPT)
1218      problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1219#  else
1220      daemon->lease_change_command = opt_string_alloc(arg);
1221#  endif
1222      break;
1223#endif
1224
1225    case 'H': /* --addn-hosts */
1226      {
1227	struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1228	static int hosts_index = 1;
1229	new->fname = opt_string_alloc(arg);
1230	new->index = hosts_index++;
1231	new->flags = 0;
1232	new->next = daemon->addn_hosts;
1233	daemon->addn_hosts = new;
1234	break;
1235      }
1236
1237    case 's': /* --domain */
1238      if (strcmp (arg, "#") == 0)
1239	daemon->options |= OPT_RESOLV_DOMAIN;
1240      else
1241	{
1242	  char *d;
1243	  comma = split(arg);
1244	  if (!(d = canonicalise_opt(arg)))
1245	    option = '?';
1246	  else
1247	    {
1248	      if (comma)
1249		{
1250		  struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
1251		  unhide_metas(comma);
1252		  if ((arg = split_chr(comma, '/')))
1253		    {
1254		      int mask;
1255		      if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1256			  !atoi_check(arg, &mask))
1257			option = '?';
1258		      else
1259			{
1260			  mask = (1 << (32 - mask)) - 1;
1261			  new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1262			  new->end.s_addr = new->start.s_addr | htonl(mask);
1263			}
1264		    }
1265		  else if ((arg = split(comma)))
1266		    {
1267		      if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1268			  (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
1269			option = '?';
1270		    }
1271		  else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1272		    option = '?';
1273
1274		  new->domain = d;
1275		  new->next = daemon->cond_domain;
1276		  daemon->cond_domain = new;
1277		}
1278	      else
1279		daemon->domain_suffix = d;
1280	    }
1281	}
1282      break;
1283
1284    case 'u':  /* --user */
1285      daemon->username = opt_string_alloc(arg);
1286      break;
1287
1288    case 'g':  /* --group */
1289      daemon->groupname = opt_string_alloc(arg);
1290      daemon->group_set = 1;
1291      break;
1292
1293#ifdef HAVE_DHCP
1294    case LOPT_SCRIPTUSR: /* --scriptuser */
1295      daemon->scriptuser = opt_string_alloc(arg);
1296      break;
1297#endif
1298
1299    case 'i':  /* --interface */
1300      do {
1301	struct iname *new = opt_malloc(sizeof(struct iname));
1302	comma = split(arg);
1303	new->next = daemon->if_names;
1304	daemon->if_names = new;
1305	/* new->name may be NULL if someone does
1306	   "interface=" to disable all interfaces except loop. */
1307	new->name = opt_string_alloc(arg);
1308	new->isloop = new->used = 0;
1309	arg = comma;
1310      } while (arg);
1311      break;
1312
1313    case 'I':  /* --except-interface */
1314    case '2':  /* --no-dhcp-interface */
1315      do {
1316	struct iname *new = opt_malloc(sizeof(struct iname));
1317	comma = split(arg);
1318	new->name = opt_string_alloc(arg);
1319	if (option == 'I')
1320	  {
1321	    new->next = daemon->if_except;
1322	    daemon->if_except = new;
1323	  }
1324	else
1325	  {
1326	    new->next = daemon->dhcp_except;
1327	    daemon->dhcp_except = new;
1328	  }
1329	arg = comma;
1330      } while (arg);
1331      break;
1332
1333    case 'B':  /* --bogus-nxdomain */
1334      {
1335	struct in_addr addr;
1336	unhide_metas(arg);
1337	if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1338	  {
1339	    struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1340	    baddr->next = daemon->bogus_addr;
1341	    daemon->bogus_addr = baddr;
1342	    baddr->addr = addr;
1343	  }
1344	else
1345	  option = '?'; /* error */
1346	break;
1347      }
1348
1349    case 'a':  /* --listen-address */
1350      do {
1351	struct iname *new = opt_malloc(sizeof(struct iname));
1352	comma = split(arg);
1353	unhide_metas(arg);
1354	new->next = daemon->if_addrs;
1355	if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1356	  {
1357	    new->addr.sa.sa_family = AF_INET;
1358#ifdef HAVE_SOCKADDR_SA_LEN
1359	    new->addr.in.sin_len = sizeof(new->addr.in);
1360#endif
1361	  }
1362#ifdef HAVE_IPV6
1363	else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1364	  {
1365	    new->addr.sa.sa_family = AF_INET6;
1366	    new->addr.in6.sin6_flowinfo = 0;
1367	    new->addr.in6.sin6_scope_id = 0;
1368#ifdef HAVE_SOCKADDR_SA_LEN
1369	    new->addr.in6.sin6_len = sizeof(new->addr.in6);
1370#endif
1371	  }
1372#endif
1373	else
1374	  {
1375	    option = '?'; /* error */
1376	    break;
1377	  }
1378
1379	daemon->if_addrs = new;
1380	arg = comma;
1381      } while (arg);
1382      break;
1383
1384    case 'S':        /*  --server */
1385    case LOPT_LOCAL: /*  --local */
1386    case 'A':        /*  --address */
1387      {
1388	struct server *serv, *newlist = NULL;
1389
1390	unhide_metas(arg);
1391
1392	if (arg && *arg == '/')
1393	  {
1394	    char *end;
1395	    arg++;
1396	    while ((end = split_chr(arg, '/')))
1397	      {
1398		char *domain = NULL;
1399		/* # matches everything and becomes a zero length domain string */
1400		if (strcmp(arg, "#") == 0)
1401		  domain = "";
1402		else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1403		  option = '?';
1404		serv = opt_malloc(sizeof(struct server));
1405		memset(serv, 0, sizeof(struct server));
1406		serv->next = newlist;
1407		newlist = serv;
1408		serv->domain = domain;
1409		serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1410		arg = end;
1411	      }
1412	    if (!newlist)
1413	      {
1414		option = '?';
1415		break;
1416	      }
1417
1418	  }
1419	else
1420	  {
1421	    newlist = opt_malloc(sizeof(struct server));
1422	    memset(newlist, 0, sizeof(struct server));
1423	  }
1424
1425	if (option == 'A')
1426	  {
1427	    newlist->flags |= SERV_LITERAL_ADDRESS;
1428	    if (!(newlist->flags & SERV_TYPE))
1429	      option = '?';
1430	  }
1431
1432	if (!arg || !*arg)
1433	  {
1434	    newlist->flags |= SERV_NO_ADDR; /* no server */
1435	    if (newlist->flags & SERV_LITERAL_ADDRESS)
1436	      option = '?';
1437	  }
1438	else
1439	  {
1440	    int source_port = 0, serv_port = NAMESERVER_PORT;
1441	    char *portno, *source;
1442
1443	    if ((source = split_chr(arg, '@')) && /* is there a source. */
1444		(portno = split_chr(source, '#')) &&
1445		!atoi_check16(portno, &source_port))
1446	      problem = _("bad port");
1447
1448	    if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1449		!atoi_check16(portno, &serv_port))
1450	      problem = _("bad port");
1451
1452	    if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
1453	      {
1454		newlist->addr.in.sin_port = htons(serv_port);
1455		newlist->source_addr.in.sin_port = htons(source_port);
1456		newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
1457#ifdef HAVE_SOCKADDR_SA_LEN
1458		newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
1459#endif
1460		if (source)
1461		  {
1462		    newlist->flags |= SERV_HAS_SOURCE;
1463		    if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
1464		      {
1465#if defined(SO_BINDTODEVICE)
1466			newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1467			strncpy(newlist->interface, source, IF_NAMESIZE);
1468#else
1469			problem = _("interface binding not supported");
1470#endif
1471		      }
1472		  }
1473		else
1474		  newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1475	      }
1476#ifdef HAVE_IPV6
1477	    else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
1478	      {
1479		newlist->addr.in6.sin6_port = htons(serv_port);
1480		newlist->source_addr.in6.sin6_port = htons(source_port);
1481		newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
1482#ifdef HAVE_SOCKADDR_SA_LEN
1483		newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
1484#endif
1485		if (source)
1486		  {
1487		     newlist->flags |= SERV_HAS_SOURCE;
1488		     if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
1489		      {
1490#if defined(SO_BINDTODEVICE)
1491			newlist->source_addr.in6.sin6_addr = in6addr_any;
1492			strncpy(newlist->interface, source, IF_NAMESIZE);
1493#else
1494			problem = _("interface binding not supported");
1495#endif
1496		      }
1497		  }
1498		else
1499		  newlist->source_addr.in6.sin6_addr = in6addr_any;
1500	      }
1501#endif
1502	    else
1503	      option = '?'; /* error */
1504
1505	  }
1506
1507	serv = newlist;
1508	while (serv->next)
1509	  {
1510	    serv->next->flags = serv->flags;
1511	    serv->next->addr = serv->addr;
1512	    serv->next->source_addr = serv->source_addr;
1513	    serv = serv->next;
1514	  }
1515	serv->next = daemon->servers;
1516	daemon->servers = newlist;
1517	break;
1518      }
1519
1520    case 'c':  /* --cache-size */
1521      {
1522	int size;
1523
1524	if (!atoi_check(arg, &size))
1525	  option = '?';
1526	else
1527	  {
1528	    /* zero is OK, and means no caching. */
1529
1530	    if (size < 0)
1531	      size = 0;
1532	    else if (size > 10000)
1533	      size = 10000;
1534
1535	    daemon->cachesize = size;
1536	  }
1537	break;
1538      }
1539
1540    case 'p':  /* --port */
1541      if (!atoi_check16(arg, &daemon->port))
1542	option = '?';
1543      break;
1544
1545    case LOPT_MINPORT:  /* --min-port */
1546      if (!atoi_check16(arg, &daemon->min_port))
1547	option = '?';
1548      break;
1549
1550    case '0':  /* --dns-forward-max */
1551      if (!atoi_check(arg, &daemon->ftabsize))
1552	option = '?';
1553      break;
1554
1555    case LOPT_MAX_LOGS:  /* --log-async */
1556      daemon->max_logs = LOG_MAX; /* default */
1557      if (arg && !atoi_check(arg, &daemon->max_logs))
1558	option = '?';
1559      else if (daemon->max_logs > 100)
1560	daemon->max_logs = 100;
1561      break;
1562
1563    case 'P': /* --edns-packet-max */
1564      {
1565	int i;
1566	if (!atoi_check(arg, &i))
1567	  option = '?';
1568	daemon->edns_pktsz = (unsigned short)i;
1569	break;
1570      }
1571
1572    case 'Q':  /* --query-port */
1573      if (!atoi_check16(arg, &daemon->query_port))
1574	option = '?';
1575      /* if explicitly set to zero, use single OS ephemeral port
1576	 and disable random ports */
1577      if (daemon->query_port == 0)
1578	daemon->osport = 1;
1579      break;
1580
1581    case 'T':         /* --local-ttl */
1582    case LOPT_NEGTTL: /* --neg-ttl */
1583      {
1584	int ttl;
1585	if (!atoi_check(arg, &ttl))
1586	  option = '?';
1587	else if (option == LOPT_NEGTTL)
1588	  daemon->neg_ttl = (unsigned long)ttl;
1589	else
1590	  daemon->local_ttl = (unsigned long)ttl;
1591	break;
1592      }
1593
1594#ifdef HAVE_DHCP
1595    case 'X': /* --dhcp-lease-max */
1596      if (!atoi_check(arg, &daemon->dhcp_max))
1597	option = '?';
1598      break;
1599#endif
1600
1601#ifdef HAVE_TFTP
1602    case LOPT_TFTP_MAX:  /*  --tftp-max */
1603      if (!atoi_check(arg, &daemon->tftp_max))
1604	option = '?';
1605      break;
1606
1607    case LOPT_PREFIX: /* --tftp-prefix */
1608      daemon->tftp_prefix = opt_string_alloc(arg);
1609      break;
1610
1611    case LOPT_TFTPPORTS: /* --tftp-port-range */
1612      if (!(comma = split(arg)) ||
1613	  !atoi_check16(arg, &daemon->start_tftp_port) ||
1614	  !atoi_check16(comma, &daemon->end_tftp_port))
1615	problem = _("bad port range");
1616
1617      if (daemon->start_tftp_port > daemon->end_tftp_port)
1618	{
1619	  int tmp = daemon->start_tftp_port;
1620	  daemon->start_tftp_port = daemon->end_tftp_port;
1621	  daemon->end_tftp_port = tmp;
1622	}
1623
1624      break;
1625#endif
1626
1627    case LOPT_BRIDGE:   /* --bridge-interface */
1628      {
1629	struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
1630	if (!(comma = split(arg)))
1631	  {
1632	    problem = _("bad bridge-interface");
1633	    break;
1634	  }
1635
1636	strncpy(new->iface, arg, IF_NAMESIZE);
1637	new->alias = NULL;
1638	new->next = daemon->bridges;
1639	daemon->bridges = new;
1640
1641	do {
1642	  arg = comma;
1643	  comma = split(arg);
1644	  if (strlen(arg) != 0)
1645	    {
1646	      struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
1647	      b->next = new->alias;
1648	      new->alias = b;
1649	      strncpy(b->iface, arg, IF_NAMESIZE);
1650	    }
1651	} while (comma);
1652
1653	break;
1654      }
1655
1656#ifdef HAVE_DHCP
1657    case 'F':  /* --dhcp-range */
1658      {
1659	int k, leasepos = 2;
1660	char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
1661	struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
1662
1663	new->next = daemon->dhcp;
1664	new->lease_time = DEFLEASE;
1665	new->addr_epoch = 0;
1666	new->netmask.s_addr = 0;
1667	new->broadcast.s_addr = 0;
1668	new->router.s_addr = 0;
1669	new->netid.net = NULL;
1670	new->filter = NULL;
1671	new->flags = 0;
1672
1673	gen_prob = _("bad dhcp-range");
1674
1675	if (!arg)
1676	  {
1677	    option = '?';
1678	    break;
1679	  }
1680
1681	while(1)
1682	  {
1683	    for (cp = arg; *cp; cp++)
1684	      if (!(*cp == ' ' || *cp == '.' ||  (*cp >='0' && *cp <= '9')))
1685		break;
1686
1687	    if (*cp != ',' && (comma = split(arg)))
1688	      {
1689		if (strstr(arg, "net:") == arg)
1690		  {
1691		    struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
1692		    tt->net = opt_string_alloc(arg+4);
1693		    tt->next = new->filter;
1694		    new->filter = tt;
1695		  }
1696		else
1697		  {
1698		    if (new->netid.net)
1699		      problem = _("only one netid tag allowed");
1700		    else
1701		      new->netid.net = opt_string_alloc(arg);
1702		  }
1703		arg = comma;
1704	      }
1705	    else
1706	      {
1707		a[0] = arg;
1708		break;
1709	      }
1710	  }
1711
1712	for (k = 1; k < 5; k++)
1713	  if (!(a[k] = split(a[k-1])))
1714	    break;
1715
1716	if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
1717	  option = '?';
1718	else if (strcmp(a[1], "static") == 0)
1719	  {
1720	    new->end = new->start;
1721	    new->flags |= CONTEXT_STATIC;
1722	  }
1723	else if (strcmp(a[1], "proxy") == 0)
1724	  {
1725	    new->end = new->start;
1726	    new->flags |= CONTEXT_PROXY;
1727	  }
1728	else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
1729	  option = '?';
1730
1731	if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
1732	  {
1733	    struct in_addr tmp = new->start;
1734	    new->start = new->end;
1735	    new->end = tmp;
1736	  }
1737
1738	if (option != '?' && k >= 3 && strchr(a[2], '.') &&
1739	    ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
1740	  {
1741	    new->flags |= CONTEXT_NETMASK;
1742	    leasepos = 3;
1743	    if (!is_same_net(new->start, new->end, new->netmask))
1744	      problem = _("inconsistent DHCP range");
1745	  }
1746	daemon->dhcp = new;
1747
1748	if (k >= 4 && strchr(a[3], '.') &&
1749	    ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
1750	  {
1751	    new->flags |= CONTEXT_BRDCAST;
1752	    leasepos = 4;
1753	  }
1754
1755	if (k >= leasepos+1)
1756	  {
1757	    if (strcmp(a[leasepos], "infinite") == 0)
1758	      new->lease_time = 0xffffffff;
1759	    else
1760	      {
1761		int fac = 1;
1762		if (strlen(a[leasepos]) > 0)
1763		  {
1764		    switch (a[leasepos][strlen(a[leasepos]) - 1])
1765		      {
1766		      case 'd':
1767		      case 'D':
1768			fac *= 24;
1769			/* fall though */
1770		      case 'h':
1771		      case 'H':
1772			fac *= 60;
1773			/* fall through */
1774		      case 'm':
1775		      case 'M':
1776			fac *= 60;
1777			/* fall through */
1778		      case 's':
1779		      case 'S':
1780			a[leasepos][strlen(a[leasepos]) - 1] = 0;
1781		      }
1782
1783		    new->lease_time = atoi(a[leasepos]) * fac;
1784		    /* Leases of a minute or less confuse
1785		       some clients, notably Apple's */
1786		    if (new->lease_time < 120)
1787		      new->lease_time = 120;
1788		  }
1789	      }
1790	  }
1791	break;
1792      }
1793
1794    case LOPT_BANK:
1795    case 'G':  /* --dhcp-host */
1796      {
1797	int j, k = 0;
1798	char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
1799	struct dhcp_config *new;
1800	struct in_addr in;
1801
1802	new = opt_malloc(sizeof(struct dhcp_config));
1803
1804	new->next = daemon->dhcp_conf;
1805	new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
1806	new->hwaddr = NULL;
1807
1808	if ((a[0] = arg))
1809	  for (k = 1; k < 6; k++)
1810	    if (!(a[k] = split(a[k-1])))
1811	      break;
1812
1813	for (j = 0; j < k; j++)
1814	  if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
1815	    {
1816	      char *arg = a[j];
1817
1818	      if ((arg[0] == 'i' || arg[0] == 'I') &&
1819		  (arg[1] == 'd' || arg[1] == 'D') &&
1820		  arg[2] == ':')
1821		{
1822		  if (arg[3] == '*')
1823		    new->flags |= CONFIG_NOCLID;
1824		  else
1825		    {
1826		      int len;
1827		      arg += 3; /* dump id: */
1828		      if (strchr(arg, ':'))
1829			len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
1830		      else
1831			{
1832			  unhide_metas(arg);
1833			  len = (int) strlen(arg);
1834			}
1835
1836		      if ((new->clid = opt_malloc(len)))
1837			{
1838			  new->flags |= CONFIG_CLID;
1839			  new->clid_len = len;
1840			  memcpy(new->clid, arg, len);
1841			}
1842		    }
1843		}
1844	      else if (strstr(arg, "net:") == arg)
1845		{
1846		  int len = strlen(arg + 4) + 1;
1847		  if ((new->netid.net = opt_malloc(len)))
1848		    {
1849		      new->flags |= CONFIG_NETID;
1850		      strcpy(new->netid.net, arg+4);
1851		      unhide_metas(new->netid.net);
1852		    }
1853		}
1854	      else
1855		{
1856		  struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
1857		  newhw->next = new->hwaddr;
1858		  new->hwaddr = newhw;
1859		  newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
1860						&newhw->wildcard_mask, &newhw->hwaddr_type);
1861		}
1862	    }
1863	  else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
1864	    {
1865	      new->addr = in;
1866	      new->flags |= CONFIG_ADDR;
1867	    }
1868	  else
1869	    {
1870	      char *cp, *lastp = NULL, last = 0;
1871	      int fac = 1;
1872
1873	      if (strlen(a[j]) > 1)
1874		{
1875		  lastp = a[j] + strlen(a[j]) - 1;
1876		  last = *lastp;
1877		  switch (last)
1878		    {
1879		    case 'd':
1880		    case 'D':
1881		      fac *= 24;
1882		      /* fall through */
1883		    case 'h':
1884		    case 'H':
1885		      fac *= 60;
1886		      /* fall through */
1887		    case 'm':
1888		    case 'M':
1889		      fac *= 60;
1890		      /* fall through */
1891		    case 's':
1892		    case 'S':
1893		      *lastp = 0;
1894		    }
1895		}
1896
1897	      for (cp = a[j]; *cp; cp++)
1898		if (!isdigit((int)*cp) && *cp != ' ')
1899		  break;
1900
1901	      if (*cp)
1902		{
1903		  if (lastp)
1904		    *lastp = last;
1905		  if (strcmp(a[j], "infinite") == 0)
1906		    {
1907		      new->lease_time = 0xffffffff;
1908		      new->flags |= CONFIG_TIME;
1909		    }
1910		  else if (strcmp(a[j], "ignore") == 0)
1911		    new->flags |= CONFIG_DISABLE;
1912		  else
1913		    {
1914		      if (!(new->hostname = canonicalise_opt(a[j])) ||
1915			  !legal_hostname(new->hostname))
1916			problem = _("bad DHCP host name");
1917		      else
1918			new->flags |= CONFIG_NAME;
1919		      new->domain = NULL;
1920		    }
1921		}
1922	      else
1923		{
1924		  new->lease_time = atoi(a[j]) * fac;
1925		  /* Leases of a minute or less confuse
1926		     some clients, notably Apple's */
1927		  if (new->lease_time < 120)
1928		    new->lease_time = 120;
1929		  new->flags |= CONFIG_TIME;
1930		}
1931	    }
1932
1933	daemon->dhcp_conf = new;
1934	break;
1935      }
1936
1937    case 'O':           /* --dhcp-option */
1938    case LOPT_FORCE:    /* --dhcp-option-force */
1939    case LOPT_OPTS:
1940    case LOPT_MATCH:    /* --dhcp-match */
1941      problem = parse_dhcp_opt(arg,
1942			       option == LOPT_FORCE ? DHOPT_FORCE :
1943			       (option == LOPT_MATCH ? DHOPT_MATCH :
1944			       (option == LOPT_OPTS ? DHOPT_BANK : 0)));
1945      break;
1946
1947    case 'M': /* --dhcp-boot */
1948      {
1949	struct dhcp_netid *id = NULL;
1950	while (arg && strstr(arg, "net:") == arg)
1951	  {
1952	    struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
1953	    newid->next = id;
1954	    id = newid;
1955	    comma = split(arg);
1956	    newid->net = opt_string_alloc(arg+4);
1957	    arg = comma;
1958	  };
1959
1960	if (!arg)
1961	  option = '?';
1962	else
1963	  {
1964	    char *dhcp_file, *dhcp_sname = NULL;
1965	    struct in_addr dhcp_next_server;
1966	    comma = split(arg);
1967	    dhcp_file = opt_string_alloc(arg);
1968	    dhcp_next_server.s_addr = 0;
1969	    if (comma)
1970	      {
1971		arg = comma;
1972		comma = split(arg);
1973		dhcp_sname = opt_string_alloc(arg);
1974		if (comma)
1975		  {
1976		    unhide_metas(comma);
1977		    if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1978		      option = '?';
1979		  }
1980	      }
1981	    if (option != '?')
1982	      {
1983		struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
1984		new->file = dhcp_file;
1985		new->sname = dhcp_sname;
1986		new->next_server = dhcp_next_server;
1987		new->netid = id;
1988		new->next = daemon->boot_config;
1989		daemon->boot_config = new;
1990	      }
1991	  }
1992
1993	break;
1994      }
1995
1996    case LOPT_PXE_PROMT:  /* --pxe-prompt */
1997       {
1998	 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
1999	 int timeout;
2000
2001	 new->netid = NULL;
2002	 new->opt = 10; /* PXE_MENU_PROMPT */
2003
2004	 while (arg && strstr(arg, "net:") == arg)
2005	   {
2006	     struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2007	     comma = split(arg);
2008	     nn->next = new->netid;
2009	     new->netid = nn;
2010	     nn->net = opt_string_alloc(arg+4);
2011	     arg = comma;
2012	   }
2013
2014	 if (!arg)
2015	   option = '?';
2016	 else
2017	   {
2018	     comma = split(arg);
2019	     unhide_metas(arg);
2020	     new->len = strlen(arg) + 1;
2021	     new->val = opt_malloc(new->len);
2022	     memcpy(new->val + 1, arg, new->len - 1);
2023
2024	     new->u.vendor_class = (unsigned char *)"PXEClient";
2025	     new->flags = DHOPT_VENDOR;
2026
2027	     if (comma && atoi_check(comma, &timeout))
2028	       *(new->val) = timeout;
2029	     else
2030	       *(new->val) = 255;
2031
2032	     new->next = daemon->dhcp_opts;
2033	     daemon->dhcp_opts = new;
2034	     daemon->enable_pxe = 1;
2035	   }
2036
2037	 break;
2038       }
2039
2040    case LOPT_PXE_SERV:  /* --pxe-service */
2041       {
2042	 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2043	 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2044			 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2045	 static int boottype = 32768;
2046
2047	 new->netid = NULL;
2048	 new->server.s_addr = 0;
2049
2050	 while (arg && strstr(arg, "net:") == arg)
2051	   {
2052	     struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2053	     comma = split(arg);
2054	     nn->next = new->netid;
2055	     new->netid = nn;
2056	     nn->net = opt_string_alloc(arg+4);
2057	     arg = comma;
2058	   }
2059
2060	 if (arg && (comma = split(arg)))
2061	   {
2062	     for (i = 0; CSA[i]; i++)
2063	       if (strcasecmp(CSA[i], arg) == 0)
2064		 break;
2065
2066	     if (CSA[i] || atoi_check(arg, &i))
2067	       {
2068		 arg = comma;
2069		 comma = split(arg);
2070
2071		 new->CSA = i;
2072		 new->menu = opt_string_alloc(arg);
2073
2074		 if (comma)
2075		   {
2076		     arg = comma;
2077		     comma = split(arg);
2078		     if (atoi_check(arg, &i))
2079		       {
2080			 new->type = i;
2081			 new->basename = NULL;
2082		       }
2083		     else
2084		       {
2085			 new->type = boottype++;
2086			 new->basename = opt_string_alloc(arg);
2087		       }
2088
2089		     if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
2090		       option = '?';
2091
2092		     /* Order matters */
2093		     new->next = NULL;
2094		     if (!daemon->pxe_services)
2095		       daemon->pxe_services = new;
2096		     else
2097		       {
2098			 struct pxe_service *s;
2099			 for (s = daemon->pxe_services; s->next; s = s->next);
2100			 s->next = new;
2101		       }
2102
2103		     daemon->enable_pxe = 1;
2104		     break;
2105		   }
2106	       }
2107	   }
2108
2109	 option = '?';
2110	 break;
2111       }
2112
2113    case '4':  /* --dhcp-mac */
2114      {
2115	if (!(comma = split(arg)))
2116	  option = '?';
2117	else
2118	  {
2119	    struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2120	    if (strstr(arg, "net:") == arg)
2121	      new->netid.net = opt_string_alloc(arg+4);
2122	    else
2123	      new->netid.net = opt_string_alloc(arg);
2124	    unhide_metas(comma);
2125	    new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2126	    new->next = daemon->dhcp_macs;
2127	    daemon->dhcp_macs = new;
2128	  }
2129      }
2130      break;
2131
2132    case 'U':           /* --dhcp-vendorclass */
2133    case 'j':           /* --dhcp-userclass */
2134    case LOPT_CIRCUIT:  /* --dhcp-circuitid */
2135    case LOPT_REMOTE:   /* --dhcp-remoteid */
2136    case LOPT_SUBSCR:   /* --dhcp-subscrid */
2137      {
2138	if (!(comma = split(arg)))
2139	  option = '?';
2140	else
2141	  {
2142	    char *p;
2143	    int dig = 0;
2144	    struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2145	    if (strstr(arg, "net:") == arg)
2146	      new->netid.net = opt_string_alloc(arg+4);
2147	    else
2148	      new->netid.net = opt_string_alloc(arg);
2149	    /* check for hex string - must digits may include : must not have nothing else,
2150	       only allowed for agent-options. */
2151	    for (p = comma; *p; p++)
2152	      if (isxdigit((int)*p))
2153		dig = 1;
2154	      else if (*p != ':')
2155		break;
2156	    unhide_metas(comma);
2157	    if (option == 'U' || option == 'j' || *p || !dig)
2158	      {
2159		new->len = strlen(comma);
2160		new->data = opt_malloc(new->len);
2161		memcpy(new->data, comma, new->len);
2162	      }
2163	    else
2164	      {
2165		new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2166		new->data = opt_malloc(new->len);
2167		memcpy(new->data, comma, new->len);
2168	      }
2169
2170	    switch (option)
2171	      {
2172	      case 'j':
2173		new->match_type = MATCH_USER;
2174		break;
2175	      case 'U':
2176		new->match_type = MATCH_VENDOR;
2177		break;
2178	      case LOPT_CIRCUIT:
2179		new->match_type = MATCH_CIRCUIT;
2180		break;
2181	      case LOPT_REMOTE:
2182		new->match_type = MATCH_REMOTE;
2183		break;
2184	      case LOPT_SUBSCR:
2185		new->match_type = MATCH_SUBSCRIBER;
2186		break;
2187	      }
2188	    new->next = daemon->dhcp_vendors;
2189	    daemon->dhcp_vendors = new;
2190	  }
2191	break;
2192      }
2193
2194    case LOPT_ALTPORT:   /* --dhcp-alternate-port */
2195      if (!arg)
2196	{
2197	  daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2198	  daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2199	}
2200      else
2201	{
2202	  comma = split(arg);
2203	  if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2204	      (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
2205	    problem = _("invalid port number");
2206	  if (!comma)
2207	    daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2208	}
2209      break;
2210
2211    case 'J':            /* --dhcp-ignore */
2212    case LOPT_NO_NAMES:  /* --dhcp-ignore-names */
2213    case LOPT_BROADCAST: /* --dhcp-broadcast */
2214    case '3':            /* --bootp-dynamic */
2215      {
2216	struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
2217	struct dhcp_netid *list = NULL;
2218	if (option == 'J')
2219	  {
2220	    new->next = daemon->dhcp_ignore;
2221	    daemon->dhcp_ignore = new;
2222	  }
2223	else if (option == LOPT_BROADCAST)
2224	  {
2225	    new->next = daemon->force_broadcast;
2226	    daemon->force_broadcast = new;
2227	  }
2228	else if (option == '3')
2229	  {
2230	    new->next = daemon->bootp_dynamic;
2231	    daemon->bootp_dynamic = new;
2232	  }
2233	else
2234	  {
2235	    new->next = daemon->dhcp_ignore_names;
2236	    daemon->dhcp_ignore_names = new;
2237	  }
2238
2239	while (arg) {
2240	  struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
2241	  comma = split(arg);
2242	  member->next = list;
2243	  list = member;
2244	  if (strstr(arg, "net:") == arg)
2245	    member->net = opt_string_alloc(arg+4);
2246	  else
2247	    member->net = opt_string_alloc(arg);
2248	  arg = comma;
2249	}
2250
2251	new->list = list;
2252	break;
2253      }
2254#endif
2255
2256    case 'V':  /* --alias */
2257      {
2258	char *dash, *a[3] = { NULL, NULL, NULL };
2259	int k = 0;
2260	struct doctor *new = opt_malloc(sizeof(struct doctor));
2261	new->next = daemon->doctors;
2262	daemon->doctors = new;
2263	new->mask.s_addr = 0xffffffff;
2264	new->end.s_addr = 0;
2265
2266	if ((a[0] = arg))
2267	  for (k = 1; k < 3; k++)
2268	    {
2269	      if (!(a[k] = split(a[k-1])))
2270		break;
2271	      unhide_metas(a[k]);
2272	    }
2273
2274	dash = split_chr(a[0], '-');
2275
2276	if ((k < 2) ||
2277	    ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
2278	    ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
2279	  option = '?';
2280
2281	if (k == 3)
2282	  new->mask.s_addr = inet_addr(a[2]);
2283
2284	if (dash &&
2285	    ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
2286	     !is_same_net(new->in, new->end, new->mask) ||
2287	     ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
2288	  problem = _("invalid alias range");
2289
2290	break;
2291      }
2292
2293    case LOPT_INTNAME:  /* --interface-name */
2294      {
2295	struct interface_name *new, **up;
2296	char *domain = NULL;
2297
2298	comma = split(arg);
2299
2300	if (!comma || !(domain = canonicalise_opt(arg)))
2301	  problem = _("bad interface name");
2302
2303	new = opt_malloc(sizeof(struct interface_name));
2304	new->next = NULL;
2305	/* Add to the end of the list, so that first name
2306	   of an interface is used for PTR lookups. */
2307	for (up = &daemon->int_names; *up; up = &((*up)->next));
2308	*up = new;
2309	new->name = domain;
2310	new->intr = opt_string_alloc(comma);
2311	break;
2312      }
2313
2314    case LOPT_CNAME: /* --cname */
2315      {
2316	struct cname *new;
2317
2318	if (!(comma = split(arg)))
2319	  option = '?';
2320	else
2321	  {
2322	    char *alias = canonicalise_opt(arg);
2323	    char *target = canonicalise_opt(comma);
2324
2325	    if (!alias || !target)
2326	      problem = _("bad CNAME");
2327	    else
2328	      {
2329		for (new = daemon->cnames; new; new = new->next)
2330		  if (hostname_isequal(new->alias, arg))
2331		    problem = _("duplicate CNAME");
2332		new = opt_malloc(sizeof(struct cname));
2333		new->next = daemon->cnames;
2334		daemon->cnames = new;
2335		new->alias = alias;
2336		new->target = target;
2337	      }
2338	  }
2339	break;
2340      }
2341
2342    case LOPT_PTR:  /* --ptr-record */
2343      {
2344	struct ptr_record *new;
2345	char *dom, *target = NULL;
2346
2347	comma = split(arg);
2348
2349	if (!(dom = canonicalise_opt(arg)) ||
2350	    (comma && !(target = canonicalise_opt(comma))))
2351	  problem = _("bad PTR record");
2352	else
2353	  {
2354	    new = opt_malloc(sizeof(struct ptr_record));
2355	    new->next = daemon->ptr;
2356	    daemon->ptr = new;
2357	    new->name = dom;
2358	    new->ptr = target;
2359	  }
2360	break;
2361      }
2362
2363    case LOPT_NAPTR: /* --naptr-record */
2364      {
2365	char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2366	int k = 0;
2367	struct naptr *new;
2368	int order, pref;
2369	char *name, *replace = NULL;
2370
2371	if ((a[0] = arg))
2372	  for (k = 1; k < 7; k++)
2373	    if (!(a[k] = split(a[k-1])))
2374	      break;
2375
2376
2377	if (k < 6 ||
2378	    !(name = canonicalise_opt(a[0])) ||
2379	    !atoi_check16(a[1], &order) ||
2380	    !atoi_check16(a[2], &pref) ||
2381	    (k == 7 && !(replace = canonicalise_opt(a[6]))))
2382	  problem = _("bad NAPTR record");
2383	else
2384	  {
2385	    new = opt_malloc(sizeof(struct naptr));
2386	    new->next = daemon->naptr;
2387	    daemon->naptr = new;
2388	    new->name = name;
2389	    new->flags = opt_string_alloc(a[3]);
2390	    new->services = opt_string_alloc(a[4]);
2391	    new->regexp = opt_string_alloc(a[5]);
2392	    new->replace = replace;
2393	    new->order = order;
2394	    new->pref = pref;
2395	  }
2396	break;
2397      }
2398
2399    case 'Y':  /* --txt-record */
2400      {
2401	struct txt_record *new;
2402	unsigned char *p, *q;
2403
2404	if ((comma = split(arg)))
2405	  comma--;
2406
2407	gen_prob = _("TXT record string too long");
2408
2409	if ((q = (unsigned char *)comma))
2410	  while (1)
2411	    {
2412	      size_t len;
2413	      if ((p = (unsigned char *)strchr((char*)q+1, ',')))
2414		{
2415		  if ((len = p - q - 1) > 255)
2416		    option = '?';
2417		  *q = len;
2418		  for (q = q+1; q < p; q++)
2419		    *q = unhide_meta(*q);
2420		}
2421	      else
2422		{
2423		  if ((len = strlen((char *)q+1)) > 255)
2424		    option = '?';
2425		  *q = len;
2426		  for (q = q+1; *q; q++)
2427		    *q = unhide_meta(*q);
2428		  break;
2429		}
2430	    }
2431
2432	new = opt_malloc(sizeof(struct txt_record));
2433	new->next = daemon->txt;
2434	daemon->txt = new;
2435	new->class = C_IN;
2436	if (comma)
2437	  {
2438	    new->len = q - ((unsigned char *)comma);
2439	    new->txt = opt_malloc(new->len);
2440	    memcpy(new->txt, comma, new->len);
2441	  }
2442	else
2443	  {
2444	    static char empty[] = "";
2445	    new->len = 1;
2446	    new->txt = empty;
2447	  }
2448
2449	/* ensure arg is terminated */
2450	if (comma)
2451	  *comma = 0;
2452
2453	if (!(new->name = canonicalise_opt(arg)))
2454	  {
2455	    problem = _("bad TXT record");
2456	    break;
2457	  }
2458
2459	break;
2460      }
2461
2462    case 'W':  /* --srv-host */
2463      {
2464	int port = 1, priority = 0, weight = 0;
2465	char *name, *target = NULL;
2466	struct mx_srv_record *new;
2467
2468	comma = split(arg);
2469
2470	if (!(name = canonicalise_opt(arg)))
2471	  problem = _("bad SRV record");
2472
2473	if (comma)
2474	  {
2475	    arg = comma;
2476	    comma = split(arg);
2477	    if (!(target = canonicalise_opt(arg))
2478)	      problem = _("bad SRV target");
2479
2480	    if (comma)
2481	      {
2482		arg = comma;
2483		comma = split(arg);
2484		if (!atoi_check16(arg, &port))
2485		  problem = _("invalid port number");
2486
2487		if (comma)
2488		  {
2489		    arg = comma;
2490		    comma = split(arg);
2491		    if (!atoi_check16(arg, &priority))
2492		      problem = _("invalid priority");
2493
2494		    if (comma)
2495		      {
2496			arg = comma;
2497			comma = split(arg);
2498			if (!atoi_check16(arg, &weight))
2499			  problem = _("invalid weight");
2500		      }
2501		  }
2502	      }
2503	  }
2504
2505	new = opt_malloc(sizeof(struct mx_srv_record));
2506	new->next = daemon->mxnames;
2507	daemon->mxnames = new;
2508	new->issrv = 1;
2509	new->name = name;
2510	new->target = target;
2511	new->srvport = port;
2512	new->priority = priority;
2513	new->weight = weight;
2514	break;
2515      }
2516
2517    default:
2518      return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2519
2520    }
2521
2522  if (problem)
2523    return problem;
2524
2525  if (option == '?')
2526    return gen_prob;
2527
2528  return NULL;
2529}
2530
2531static void one_file(char *file, int nest, int hard_opt)
2532{
2533  volatile int lineno = 0;
2534  int i, option;
2535  FILE *f;
2536  char *p, *arg, *start, *buff = daemon->namebuff;
2537  static struct fileread {
2538    dev_t dev;
2539    ino_t ino;
2540    struct fileread *next;
2541  } *filesread = NULL;
2542  struct stat statbuf;
2543
2544  /* ignore repeated files. */
2545  if (hard_opt == 0 && stat(file, &statbuf) == 0)
2546    {
2547      struct fileread *r;
2548
2549      for (r = filesread; r; r = r->next)
2550	if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
2551	  return;
2552
2553      r = safe_malloc(sizeof(struct fileread));
2554      r->next = filesread;
2555      filesread = r;
2556      r->dev = statbuf.st_dev;
2557      r->ino = statbuf.st_ino;
2558    }
2559
2560  if (nest > 20)
2561    die(_("files nested too deep in %s"), file, EC_BADCONF);
2562
2563  if (!(f = fopen(file, "r")))
2564    {
2565      if (errno == ENOENT && nest == 0)
2566	return; /* No conffile, all done. */
2567      else
2568	{
2569	  char *str = _("cannot read %s: %s");
2570	  if (hard_opt != 0)
2571	    {
2572	      my_syslog(LOG_ERR, str, file, strerror(errno));
2573	      return;
2574	    }
2575	  else
2576	    die(str, file, EC_FILE);
2577	}
2578    }
2579
2580  while (fgets(buff, MAXDNAME, f))
2581    {
2582      int white;
2583      unsigned int lastquote;
2584      char *errmess;
2585
2586      /* Memory allocation failure longjmps here if mem_recover == 1 */
2587      if (hard_opt)
2588	{
2589	  if (setjmp(mem_jmp))
2590	    continue;
2591	  mem_recover = 1;
2592	}
2593
2594      lineno++;
2595      errmess = NULL;
2596
2597      /* Implement quotes, inside quotes we allow \\ \" \n and \t
2598	 metacharacters get hidden also strip comments */
2599
2600      for (white = 1, lastquote = 0, p = buff; *p; p++)
2601	{
2602	  if (*p == '"')
2603	    {
2604	      memmove(p, p+1, strlen(p+1)+1);
2605	      for(; *p && *p != '"'; p++)
2606		{
2607		  if (*p == '\\' && strchr("\"tnebr\\", p[1]))
2608		    {
2609		      if (p[1] == 't')
2610			p[1] = '\t';
2611		      else if (p[1] == 'n')
2612			p[1] = '\n';
2613		      else if (p[1] == 'b')
2614			p[1] = '\b';
2615		      else if (p[1] == 'r')
2616			p[1] = '\r';
2617		      else if (p[1] == 'e') /* escape */
2618			p[1] = '\033';
2619		      memmove(p, p+1, strlen(p+1)+1);
2620		    }
2621		  *p = hide_meta(*p);
2622		}
2623	      if (*p == '"')
2624		{
2625		  memmove(p, p+1, strlen(p+1)+1);
2626		  lastquote = p - buff;
2627		}
2628	      else
2629		{
2630		  errmess = _("missing \"");
2631		  goto oops;
2632		}
2633	    }
2634
2635	  if (white && *p == '#')
2636	    {
2637	      *p = 0;
2638	      break;
2639	    }
2640	  white = isspace((int)unhide_meta(*p));
2641	}
2642
2643      /* fgets gets end of line char too. */
2644      while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1])))
2645	buff[strlen(buff)-1] = 0;
2646
2647      if (*buff == 0)
2648	continue;
2649
2650      if (hard_opt != 0)
2651	arg = buff;
2652      else if ((p=strchr(buff, '=')))
2653	{
2654	  /* allow spaces around "=" */
2655	  arg = p+1;
2656	  for (; p >= buff && (isspace((int)*p) || *p == '='); p--)
2657	    *p = 0;
2658	}
2659      else
2660	arg = NULL;
2661
2662      if (hard_opt != 0)
2663	option = hard_opt;
2664      else
2665	{
2666	  /* skip leading space */
2667	  for (start = buff; *start && isspace((int)*start); start++);
2668
2669	  for (option = 0, i = 0; opts[i].name; i++)
2670	    if (strcmp(opts[i].name, start) == 0)
2671	      {
2672		option = opts[i].val;
2673		break;
2674	      }
2675
2676	  if (!option)
2677	    errmess = _("bad option");
2678	  else if (opts[i].has_arg == 0 && arg)
2679	    errmess = _("extraneous parameter");
2680	  else if (opts[i].has_arg == 1 && !arg)
2681	    errmess = _("missing parameter");
2682	}
2683
2684      if (!errmess)
2685	{
2686	  if (arg)
2687	    for (; isspace((int)*arg); arg++);
2688
2689	  errmess = one_opt(option, arg, _("error"), nest + 1);
2690	}
2691
2692      if (errmess)
2693	{
2694	oops:
2695	  sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
2696	  if (hard_opt != 0)
2697	    my_syslog(LOG_ERR, buff, file);
2698	  else
2699	    die(buff, file, EC_BADCONF);
2700	}
2701    }
2702
2703  mem_recover = 1;
2704  fclose(f);
2705}
2706
2707#ifdef HAVE_DHCP
2708void reread_dhcp(void)
2709{
2710  if (daemon->dhcp_hosts_file)
2711    {
2712      struct dhcp_config *configs, *cp, **up;
2713
2714      /* remove existing... */
2715      for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
2716	{
2717	  cp = configs->next;
2718
2719	  if (configs->flags & CONFIG_BANK)
2720	    {
2721	      struct hwaddr_config *mac, *tmp;
2722
2723	      for (mac = configs->hwaddr; mac; mac = tmp)
2724		{
2725		  tmp = mac->next;
2726		  free(mac);
2727		}
2728	      if (configs->flags & CONFIG_CLID)
2729		free(configs->clid);
2730	      if (configs->flags & CONFIG_NETID)
2731		free(configs->netid.net);
2732	      if (configs->flags & CONFIG_NAME)
2733		free(configs->hostname);
2734
2735
2736	      *up = configs->next;
2737	      free(configs);
2738	    }
2739	  else
2740	    up = &configs->next;
2741	}
2742
2743      one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
2744      my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
2745    }
2746
2747  if (daemon->dhcp_opts_file)
2748    {
2749      struct dhcp_opt *opts, *cp, **up;
2750      struct dhcp_netid *id, *next;
2751
2752      for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
2753	{
2754	  cp = opts->next;
2755
2756	  if (opts->flags & DHOPT_BANK)
2757	    {
2758	      if ((opts->flags & DHOPT_VENDOR))
2759		free(opts->u.vendor_class);
2760	      free(opts->val);
2761	      for (id = opts->netid; id; id = next)
2762		{
2763		  next = id->next;
2764		  free(id->net);
2765		  free(id);
2766		}
2767	      *up = opts->next;
2768	      free(opts);
2769	    }
2770	  else
2771	    up = &opts->next;
2772	}
2773
2774      one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
2775      my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
2776    }
2777}
2778#endif
2779
2780void read_opts(int argc, char **argv, char *compile_opts)
2781{
2782  char *buff = opt_malloc(MAXDNAME);
2783  int option, nest = 0, testmode = 0;
2784  char *errmess, *arg, *conffile = CONFFILE;
2785
2786  opterr = 0;
2787
2788  daemon = opt_malloc(sizeof(struct daemon));
2789  memset(daemon, 0, sizeof(struct daemon));
2790  daemon->namebuff = buff;
2791
2792  /* Set defaults - everything else is zero or NULL */
2793  daemon->cachesize = CACHESIZ;
2794  daemon->ftabsize = FTABSIZ;
2795  daemon->port = NAMESERVER_PORT;
2796  daemon->dhcp_client_port = DHCP_CLIENT_PORT;
2797  daemon->dhcp_server_port = DHCP_SERVER_PORT;
2798  daemon->default_resolv.is_default = 1;
2799  daemon->default_resolv.name = RESOLVFILE;
2800  daemon->resolv_files = &daemon->default_resolv;
2801  daemon->username = CHUSER;
2802  daemon->runfile =  RUNFILE;
2803  daemon->dhcp_max = MAXLEASES;
2804  daemon->tftp_max = TFTP_MAX_CONNECTIONS;
2805  daemon->edns_pktsz = EDNS_PKTSZ;
2806  daemon->log_fac = -1;
2807  add_txt("version.bind", "dnsmasq-" VERSION );
2808  add_txt("authors.bind", "Simon Kelley");
2809  add_txt("copyright.bind", COPYRIGHT);
2810
2811  while (1)
2812    {
2813#ifdef HAVE_GETOPT_LONG
2814      option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
2815#else
2816      option = getopt(argc, argv, OPTSTRING);
2817#endif
2818
2819      if (option == -1)
2820	break;
2821
2822      /* Copy optarg so that argv doesn't get changed */
2823      if (optarg)
2824	{
2825	  strncpy(buff, optarg, MAXDNAME);
2826	  buff[MAXDNAME-1] = 0;
2827	  arg = buff;
2828	}
2829      else
2830	arg = NULL;
2831
2832      /* command-line only stuff */
2833      if (option == LOPT_TEST)
2834	testmode = 1;
2835      else if (option == 'w')
2836	{
2837	  if (argc != 3 ||  strcmp(argv[2], "dhcp") != 0)
2838	    do_usage();
2839#ifdef HAVE_DHCP
2840	  else
2841	    display_opts();
2842#endif
2843	  exit(0);
2844	}
2845      else if (option == 'v')
2846	{
2847	  printf(_("Dnsmasq version %s  %s\n"), VERSION, COPYRIGHT);
2848	  printf(_("Compile time options %s\n\n"), compile_opts);
2849	  printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
2850	  printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
2851	  printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
2852          exit(0);
2853        }
2854      else if (option == 'C')
2855	{
2856	  conffile = opt_string_alloc(arg);
2857	  nest++;
2858	}
2859      else
2860	{
2861#ifdef HAVE_GETOPT_LONG
2862	  errmess = one_opt(option, arg, _("try --help"), 0);
2863#else
2864	  errmess = one_opt(option, arg, _("try -w"), 0);
2865#endif
2866	  if (errmess)
2867	    die(_("bad command line options: %s"), errmess, EC_BADCONF);
2868	}
2869    }
2870
2871  if (conffile)
2872    one_file(conffile, nest, 0);
2873
2874  /* port might not be known when the address is parsed - fill in here */
2875  if (daemon->servers)
2876    {
2877      struct server *tmp;
2878      for (tmp = daemon->servers; tmp; tmp = tmp->next)
2879	if (!(tmp->flags & SERV_HAS_SOURCE))
2880	  {
2881	    if (tmp->source_addr.sa.sa_family == AF_INET)
2882	      tmp->source_addr.in.sin_port = htons(daemon->query_port);
2883#ifdef HAVE_IPV6
2884	    else if (tmp->source_addr.sa.sa_family == AF_INET6)
2885	      tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
2886#endif
2887	  }
2888    }
2889
2890  if (daemon->if_addrs)
2891    {
2892      struct iname *tmp;
2893      for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
2894	if (tmp->addr.sa.sa_family == AF_INET)
2895	  tmp->addr.in.sin_port = htons(daemon->port);
2896#ifdef HAVE_IPV6
2897	else if (tmp->addr.sa.sa_family == AF_INET6)
2898	  tmp->addr.in6.sin6_port = htons(daemon->port);
2899#endif /* IPv6 */
2900    }
2901
2902  /* only one of these need be specified: the other defaults to the host-name */
2903  if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
2904    {
2905      struct mx_srv_record *mx;
2906
2907      if (gethostname(buff, MAXDNAME) == -1)
2908	die(_("cannot get host-name: %s"), NULL, EC_MISC);
2909
2910      for (mx = daemon->mxnames; mx; mx = mx->next)
2911	if (!mx->issrv && hostname_isequal(mx->name, buff))
2912	  break;
2913
2914      if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
2915	{
2916	  mx = opt_malloc(sizeof(struct mx_srv_record));
2917	  mx->next = daemon->mxnames;
2918	  mx->issrv = 0;
2919	  mx->target = NULL;
2920	  mx->name = opt_string_alloc(buff);
2921	  daemon->mxnames = mx;
2922	}
2923
2924      if (!daemon->mxtarget)
2925	daemon->mxtarget = opt_string_alloc(buff);
2926
2927      for (mx = daemon->mxnames; mx; mx = mx->next)
2928	if (!mx->issrv && !mx->target)
2929	  mx->target = daemon->mxtarget;
2930    }
2931
2932  if (!(daemon->options & OPT_NO_RESOLV) &&
2933      daemon->resolv_files &&
2934      daemon->resolv_files->next &&
2935      (daemon->options & OPT_NO_POLL))
2936    die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
2937
2938  if (daemon->options & OPT_RESOLV_DOMAIN)
2939    {
2940      char *line;
2941      FILE *f;
2942
2943      if ((daemon->options & OPT_NO_RESOLV) ||
2944	  !daemon->resolv_files ||
2945	  (daemon->resolv_files)->next)
2946	die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
2947
2948      if (!(f = fopen((daemon->resolv_files)->name, "r")))
2949	die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
2950
2951      while ((line = fgets(buff, MAXDNAME, f)))
2952	{
2953	  char *token = strtok(line, " \t\n\r");
2954
2955	  if (!token || strcmp(token, "search") != 0)
2956	    continue;
2957
2958	  if ((token = strtok(NULL, " \t\n\r")) &&
2959	      (daemon->domain_suffix = canonicalise_opt(token)))
2960	    break;
2961	}
2962
2963      fclose(f);
2964
2965      if (!daemon->domain_suffix)
2966	die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
2967    }
2968
2969  if (daemon->domain_suffix)
2970    {
2971       /* add domain for any srv record without one. */
2972      struct mx_srv_record *srv;
2973
2974      for (srv = daemon->mxnames; srv; srv = srv->next)
2975	if (srv->issrv &&
2976	    strchr(srv->name, '.') &&
2977	    strchr(srv->name, '.') == strrchr(srv->name, '.'))
2978	  {
2979	    strcpy(buff, srv->name);
2980	    strcat(buff, ".");
2981	    strcat(buff, daemon->domain_suffix);
2982	    free(srv->name);
2983	    srv->name = opt_string_alloc(buff);
2984	  }
2985    }
2986  else if (daemon->options & OPT_DHCP_FQDN)
2987    die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
2988
2989  if (testmode)
2990    {
2991      fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
2992      exit(0);
2993    }
2994}
2995