• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 static volatile int mem_recover = 0;
23 static jmp_buf mem_jmp;
24 static void one_file(char *file, int nest, int hard_opt);
25 
26 /* Solaris headers don't have facility names. */
27 #ifdef HAVE_SOLARIS_NETWORK
28 static 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
56 struct 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
107 static const struct option opts[] =
108 #else
109 static 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 
221 static 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 
336 static 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 
option_string(unsigned char opt,int * is_ip,int * is_name)413 char *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 
445 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
446 
hide_meta(char c)447 static 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 
unhide_meta(char cr)458 static 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 
unhide_metas(char * cp)468 static void unhide_metas(char *cp)
469 {
470   if (cp)
471     for(; *cp; cp++)
472       *cp = unhide_meta(*cp);
473 }
474 
opt_malloc(size_t size)475 static 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 
opt_string_alloc(char * cp)491 static 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 
split_chr(char * s,char c)511 static 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 
split(char * s)529 static char *split(char *s)
530 {
531   return split_chr(s, ',');
532 }
533 
canonicalise_opt(char * s)534 static 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 
atoi_check(char * a,int * res)554 static 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 
atoi_check16(char * a,int * res)571 static 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 
add_txt(char * name,char * txt)581 static 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 
do_usage(void)596 static 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
display_opts(void)654 static 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 */
parse_dhcp_opt(char * arg,int flags)666 static 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 
one_opt(int option,char * arg,char * gen_prob,int nest)978 static 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 
one_file(char * file,int nest,int hard_opt)2531 static 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
reread_dhcp(void)2708 void 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 
read_opts(int argc,char ** argv,char * compile_opts)2780 void 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