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