• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 dated June, 1991, or
6    (at your option) version 3 dated 29 June, 2007.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16 
17 /* define this to get facilitynames */
18 #define SYSLOG_NAMES
19 #include "dnsmasq.h"
20 #include <setjmp.h>
21 
22 static volatile int mem_recover = 0;
23 static jmp_buf mem_jmp;
24 static void one_file(char *file, int nest, int hard_opt);
25 
26 /* Solaris headers don't have facility names. */
27 #ifdef HAVE_SOLARIS_NETWORK
28 static const struct {
29   char *c_name;
30   unsigned int c_val;
31 }  facilitynames[] = {
32   { "kern",   LOG_KERN },
33   { "user",   LOG_USER },
34   { "mail",   LOG_MAIL },
35   { "daemon", LOG_DAEMON },
36   { "auth",   LOG_AUTH },
37   { "syslog", LOG_SYSLOG },
38   { "lpr",    LOG_LPR },
39   { "news",   LOG_NEWS },
40   { "uucp",   LOG_UUCP },
41   { "audit",  LOG_AUDIT },
42   { "cron",   LOG_CRON },
43   { "local0", LOG_LOCAL0 },
44   { "local1", LOG_LOCAL1 },
45   { "local2", LOG_LOCAL2 },
46   { "local3", LOG_LOCAL3 },
47   { "local4", LOG_LOCAL4 },
48   { "local5", LOG_LOCAL5 },
49   { "local6", LOG_LOCAL6 },
50   { "local7", LOG_LOCAL7 },
51   { NULL, 0 }
52 };
53 #endif
54 
55 #ifndef HAVE_GETOPT_LONG
56 struct myoption {
57   const char *name;
58   int has_arg;
59   int *flag;
60   int val;
61 };
62 #endif
63 
64 #define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
65 
66 /* options which don't have a one-char version */
67 #define LOPT_RELOAD    256
68 #define LOPT_NO_NAMES  257
69 #define LOPT_TFTP      258
70 #define LOPT_SECURE    259
71 #define LOPT_PREFIX    260
72 #define LOPT_PTR       261
73 #define LOPT_BRIDGE    262
74 #define LOPT_TFTP_MAX  263
75 #define LOPT_FORCE     264
76 #define LOPT_NOBLOCK   265
77 #define LOPT_LOG_OPTS  266
78 #define LOPT_MAX_LOGS  267
79 #define LOPT_CIRCUIT   268
80 #define LOPT_REMOTE    269
81 #define LOPT_SUBSCR    270
82 #define LOPT_INTNAME   271
83 #define LOPT_BANK      272
84 #define LOPT_DHCP_HOST 273
85 #define LOPT_APREF     274
86 #define LOPT_OVERRIDE  275
87 #define LOPT_TFTPPORTS 276
88 #define LOPT_REBIND    277
89 #define LOPT_NOLAST    278
90 #define LOPT_OPTS      279
91 #define LOPT_DHCP_OPTS 280
92 #define LOPT_MATCH     281
93 #define LOPT_BROADCAST 282
94 #define LOPT_NEGTTL    283
95 #define LOPT_ALTPORT   284
96 #define LOPT_SCRIPTUSR 285
97 #define LOPT_LOCAL     286
98 #define LOPT_NAPTR     287
99 #define LOPT_MINPORT   288
100 #define LOPT_DHCP_FQDN 289
101 #define LOPT_CNAME     290
102 #define LOPT_PXE_PROMT 291
103 #define LOPT_PXE_SERV  292
104 #define LOPT_TEST      293
105 #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     { '\0', 0 }
615   };
616 
617   printf(_("Usage: dnsmasq [options]\n\n"));
618 #ifndef HAVE_GETOPT_LONG
619   printf(_("Use short options only on the command line.\n"));
620 #endif
621   printf(_("Valid options are:\n"));
622 
623   for (i = 0; usage[i].opt != 0; i++)
624     {
625       char *desc = usage[i].flagdesc;
626       char *eq = "=";
627 
628       if (!desc || *desc == '[')
629 	eq = "";
630 
631       if (!desc)
632 	desc = "";
633 
634       for ( j = 0; opts[j].name; j++)
635 	if (opts[j].val == usage[i].opt)
636 	  break;
637       if (usage[i].opt < 256)
638 	sprintf(buff, "-%c, ", usage[i].opt);
639       else
640 	sprintf(buff, "    ");
641 
642       sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
643       printf("%-36.36s", buff);
644 
645       if (usage[i].arg)
646 	{
647 	  strcpy(buff, usage[i].arg);
648 	  for (j = 0; tab[j].handle; j++)
649 	    if (tab[j].handle == *(usage[i].arg))
650 	      sprintf(buff, "%d", tab[j].val);
651 	}
652       printf(_(usage[i].desc), buff);
653       printf("\n");
654     }
655 }
656 
657 #ifdef HAVE_DHCP
display_opts(void)658 static void display_opts(void)
659 {
660   int i;
661 
662   printf(_("Known DHCP options:\n"));
663 
664   for (i = 0; opttab[i].name; i++)
665     if (!(opttab[i].size & OT_INTERNAL))
666       printf("%3d %s\n", opttab[i].val, opttab[i].name);
667 }
668 
669 /* This is too insanely large to keep in-line in the switch */
parse_dhcp_opt(char * arg,int flags)670 static char *parse_dhcp_opt(char *arg, int flags)
671 {
672   struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
673   char lenchar = 0, *cp;
674   int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
675   char *comma = NULL, *problem = NULL;
676   struct dhcp_netid *np = NULL;
677   unsigned char opt_len = 0;
678 
679   new->len = 0;
680   new->flags = flags;
681   new->netid = NULL;
682   new->val = NULL;
683   new->opt = 0;
684 
685   while (arg)
686     {
687       comma = split(arg);
688 
689       for (cp = arg; *cp; cp++)
690 	if (*cp < '0' || *cp > '9')
691 	  break;
692 
693       if (!*cp)
694 	{
695 	  new->opt = atoi(arg);
696 	  opt_len = 0;
697 	  break;
698 	}
699 
700       if (strstr(arg, "option:") == arg)
701 	{
702 	  for (i = 0; opttab[i].name; i++)
703 	    if (!(opttab[i].size & OT_INTERNAL) &&
704 		strcasecmp(opttab[i].name, arg+7) == 0)
705 	      {
706 		new->opt = opttab[i].val;
707 		opt_len = opttab[i].size;
708 		break;
709 	      }
710 	  /* option:<optname> must follow tag and vendor string. */
711 	  break;
712 	}
713       else if (strstr(arg, "vendor:") == arg)
714 	{
715 	  new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
716 	  new->flags |= DHOPT_VENDOR;
717 	}
718       else if (strstr(arg, "encap:") == arg)
719 	{
720 	  new->u.encap = atoi(arg+6);
721 	  new->flags |= DHOPT_ENCAPSULATE;
722 	}
723       else
724 	{
725 	  new->netid = opt_malloc(sizeof (struct dhcp_netid));
726 	  /* allow optional "net:" for consistency */
727 	  if (strstr(arg, "net:") == arg)
728 	    new->netid->net = opt_string_alloc(arg+4);
729 	  else
730 	    new->netid->net = opt_string_alloc(arg);
731 	  new->netid->next = np;
732 	  np = new->netid;
733 	}
734 
735       arg = comma;
736     }
737 
738   if (new->opt == 0)
739     problem = _("bad dhcp-option");
740   else if (comma)
741     {
742       /* characterise the value */
743       char c;
744       is_addr = is_hex = is_dec = is_string = 1;
745       addrs = digs = 1;
746       dots = 0;
747       for (cp = comma; (c = *cp); cp++)
748 	if (c == ',')
749 	  {
750 	    addrs++;
751 	    is_dec = is_hex = 0;
752 	  }
753 	else if (c == ':')
754 	  {
755 	    digs++;
756 	    is_dec = is_addr = 0;
757 	  }
758 	else if (c == '/')
759 	  {
760 	    is_dec = is_hex = 0;
761 	    if (cp == comma) /* leading / means a pathname */
762 	      is_addr = 0;
763 	  }
764 	else if (c == '.')
765 	  {
766 	    is_dec = is_hex = 0;
767 	    dots++;
768 	  }
769 	else if (c == '-')
770 	  is_hex = is_addr = 0;
771 	else if (c == ' ')
772 	  is_dec = is_hex = 0;
773 	else if (!(c >='0' && c <= '9'))
774 	  {
775 	    is_addr = 0;
776 	    if (cp[1] == 0 && is_dec &&
777 		(c == 'b' || c == 's' || c == 'i'))
778 	      {
779 		lenchar = c;
780 		*cp = 0;
781 	      }
782 	    else
783 	      is_dec = 0;
784 	    if (!((c >='A' && c <= 'F') ||
785 		  (c >='a' && c <= 'f') ||
786 		  (c == '*' && (flags & DHOPT_MATCH))))
787 	      is_hex = 0;
788 	  }
789 
790       /* We know that some options take addresses */
791 
792       if (opt_len & OT_ADDR_LIST)
793 	{
794 	  is_string = is_dec = is_hex = 0;
795 	  if (!is_addr || dots == 0)
796 	    problem = _("bad IP address");
797 	}
798 
799       if (is_hex && digs > 1)
800 	{
801 	  new->len = digs;
802 	  new->val = opt_malloc(new->len);
803 	  parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
804 	  new->flags |= DHOPT_HEX;
805 	}
806       else if (is_dec)
807 	{
808 	  int i, val = atoi(comma);
809 	  /* assume numeric arg is 1 byte except for
810 	     options where it is known otherwise.
811 	     For vendor class option, we have to hack. */
812 	  if (opt_len != 0)
813 	    new->len = opt_len;
814 	  else if (val & 0xffff0000)
815 	    new->len = 4;
816 	  else if (val & 0xff00)
817 	    new->len = 2;
818 	  else
819 	    new->len = 1;
820 
821 	  if (lenchar == 'b')
822 	    new->len = 1;
823 	  else if (lenchar == 's')
824 	    new->len = 2;
825 	  else if (lenchar == 'i')
826 	    new->len = 4;
827 
828 	  new->val = opt_malloc(new->len);
829 	  for (i=0; i<new->len; i++)
830 	    new->val[i] = val>>((new->len - i - 1)*8);
831 	}
832       else if (is_addr)
833 	{
834 	  struct in_addr in;
835 	  unsigned char *op;
836 	  char *slash;
837 	  /* max length of address/subnet descriptor is five bytes,
838 	     add one for the option 120 enc byte too */
839 	  new->val = op = opt_malloc((5 * addrs) + 1);
840 	  new->flags |= DHOPT_ADDR;
841 
842 	  if (!(new->flags & DHOPT_ENCAPSULATE) && new->opt == 120)
843 	    {
844 	      *(op++) = 1; /* RFC 3361 "enc byte" */
845 	      new->flags &= ~DHOPT_ADDR;
846 	    }
847 	  while (addrs--)
848 	    {
849 	      cp = comma;
850 	      comma = split(cp);
851 	      slash = split_chr(cp, '/');
852 	      in.s_addr = inet_addr(cp);
853 	      if (!slash)
854 		{
855 		  memcpy(op, &in, INADDRSZ);
856 		  op += INADDRSZ;
857 		}
858 	      else
859 		{
860 		  unsigned char *p = (unsigned char *)&in;
861 		  int netsize = atoi(slash);
862 		  *op++ = netsize;
863 		  if (netsize > 0)
864 		    *op++ = *p++;
865 		  if (netsize > 8)
866 		    *op++ = *p++;
867 		  if (netsize > 16)
868 		    *op++ = *p++;
869 		  if (netsize > 24)
870 		    *op++ = *p++;
871 		  new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
872 		}
873 	    }
874 	  new->len = op - new->val;
875 	}
876       else if (is_string)
877 	{
878 	  /* text arg */
879 	  if ((new->opt == 119 || new->opt == 120) && !(new->flags & DHOPT_ENCAPSULATE))
880 	    {
881 	      /* dns search, RFC 3397, or SIP, RFC 3361 */
882 	      unsigned char *q, *r, *tail;
883 	      unsigned char *p, *m = NULL, *newp;
884 	      size_t newlen, len = 0;
885 	      int header_size = (new->opt == 119) ? 0 : 1;
886 
887 	      arg = comma;
888 	      comma = split(arg);
889 
890 	      while (arg && *arg)
891 		{
892 		  char *dom;
893 		  if (!(dom = arg = canonicalise_opt(arg)))
894 		    {
895 		      problem = _("bad domain in dhcp-option");
896 		      break;
897 		    }
898 
899 		  newp = opt_malloc(len + strlen(arg) + 2 + header_size);
900 		  if (m)
901 		    memcpy(newp, m, header_size + len);
902 		  m = newp;
903 		  p = m + header_size;
904 		  q = p + len;
905 
906 		  /* add string on the end in RFC1035 format */
907 		  while (*arg)
908 		    {
909 		      unsigned char *cp = q++;
910 		      int j;
911 		      for (j = 0; *arg && (*arg != '.'); arg++, j++)
912 			*q++ = *arg;
913 		      *cp = j;
914 		      if (*arg)
915 			arg++;
916 		    }
917 		  *q++ = 0;
918 		  free(dom);
919 
920 		  /* Now tail-compress using earlier names. */
921 		  newlen = q - p;
922 		  for (tail = p + len; *tail; tail += (*tail) + 1)
923 		    for (r = p; r - p < (int)len; r += (*r) + 1)
924 		      if (strcmp((char *)r, (char *)tail) == 0)
925 			{
926 			  PUTSHORT((r - p) | 0xc000, tail);
927 			  newlen = tail - p;
928 			  goto end;
929 			}
930 		end:
931 		  len = newlen;
932 
933 		  arg = comma;
934 		  comma = split(arg);
935 		}
936 
937 	      /* RFC 3361, enc byte is zero for names */
938 	      if (new->opt == 120)
939 		m[0] = 0;
940 	      new->len = (int) len + header_size;
941 	      new->val = m;
942 	    }
943 	  else
944 	    {
945 	      new->len = strlen(comma);
946 	      /* keep terminating zero on string */
947 	      new->val = (unsigned char *)opt_string_alloc(comma);
948 	      new->flags |= DHOPT_STRING;
949 	    }
950 	}
951     }
952 
953   if ((new->len > 255) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
954     problem = _("dhcp-option too long");
955 
956   if (!problem)
957     {
958       if (flags == DHOPT_MATCH)
959 	{
960 	  if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
961 	      !new->netid ||
962 	      new->netid->next)
963 	    problem = _("illegal dhcp-match");
964 	  else
965 	    {
966 	      new->next = daemon->dhcp_match;
967 	      daemon->dhcp_match = new;
968 	    }
969 	}
970       else
971 	{
972 	  new->next = daemon->dhcp_opts;
973 	  daemon->dhcp_opts = new;
974 	}
975     }
976 
977   return problem;
978 }
979 
980 #endif
981 
one_opt(int option,char * arg,char * gen_prob,int nest)982 static char *one_opt(int option, char *arg, char *gen_prob, int nest)
983 {
984   int i;
985   char *comma, *problem = NULL;;
986 
987   if (option == '?')
988     return gen_prob;
989 
990   for (i=0; usage[i].opt != 0; i++)
991     if (usage[i].opt == option)
992       {
993 	 int rept = usage[i].rept;
994 
995 	 if (nest == 0)
996 	   {
997 	     /* command line */
998 	     if (rept == ARG_USED_CL)
999 	       return _("illegal repeated flag");
1000 	     if (rept == ARG_ONE)
1001 	       usage[i].rept = ARG_USED_CL;
1002 	   }
1003 	 else
1004 	   {
1005 	     /* allow file to override command line */
1006 	     if (rept == ARG_USED_FILE)
1007 	       return _("illegal repeated keyword");
1008 	     if (rept == ARG_USED_CL || rept == ARG_ONE)
1009 	       usage[i].rept = ARG_USED_FILE;
1010 	   }
1011 
1012 	 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1013 	   {
1014 	     daemon->options |= rept;
1015 	     return NULL;
1016 	   }
1017 
1018 	 break;
1019       }
1020 
1021   switch (option)
1022     {
1023     case 'C': /* --conf-file */
1024       {
1025 	char *file = opt_string_alloc(arg);
1026 	if (file)
1027 	  {
1028 	    one_file(file, nest, 0);
1029 	    free(file);
1030 	  }
1031 	break;
1032       }
1033 
1034     case '7': /* --conf-dir */
1035       {
1036 	DIR *dir_stream;
1037 	struct dirent *ent;
1038 	char *directory, *path;
1039 	struct list {
1040 	  char *suffix;
1041 	  struct list *next;
1042 	} *ignore_suffix = NULL, *li;
1043 
1044 	comma = split(arg);
1045 	if (!(directory = opt_string_alloc(arg)))
1046 	  break;
1047 
1048 	for (arg = comma; arg; arg = comma)
1049 	  {
1050 	    comma = split(arg);
1051 	    li = opt_malloc(sizeof(struct list));
1052 	    li->next = ignore_suffix;
1053 	    ignore_suffix = li;
1054 	    /* Have to copy: buffer is overwritten */
1055 	    li->suffix = opt_string_alloc(arg);
1056 	  };
1057 
1058 	if (!(dir_stream = opendir(directory)))
1059 	  die(_("cannot access directory %s: %s"), directory, EC_FILE);
1060 
1061 	while ((ent = readdir(dir_stream)))
1062 	  {
1063 	    size_t len = strlen(ent->d_name);
1064 	    struct stat buf;
1065 
1066 	    /* ignore emacs backups and dotfiles */
1067 	    if (len == 0 ||
1068 		ent->d_name[len - 1] == '~' ||
1069 		(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1070 		ent->d_name[0] == '.')
1071 	      continue;
1072 
1073 	    for (li = ignore_suffix; li; li = li->next)
1074 	      {
1075 		/* check for proscribed suffices */
1076 		size_t ls = strlen(li->suffix);
1077 		if (len > ls &&
1078 		    strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1079 		  break;
1080 	      }
1081 	    if (li)
1082 	      continue;
1083 
1084 	    path = opt_malloc(strlen(directory) + len + 2);
1085 	    strcpy(path, directory);
1086 	    strcat(path, "/");
1087 	    strcat(path, ent->d_name);
1088 
1089 	    if (stat(path, &buf) == -1)
1090 	      die(_("cannot access %s: %s"), path, EC_FILE);
1091 	    /* only reg files allowed. */
1092 	    if (!S_ISREG(buf.st_mode))
1093 	      continue;
1094 
1095 	    /* dir is one level, so files must be readable */
1096 	    one_file(path, nest + 1, 0);
1097 	    free(path);
1098 	  }
1099 
1100 	closedir(dir_stream);
1101 	free(directory);
1102 	for(; ignore_suffix; ignore_suffix = li)
1103 	  {
1104 	    li = ignore_suffix->next;
1105 	    free(ignore_suffix->suffix);
1106 	    free(ignore_suffix);
1107 	  }
1108 
1109 	break;
1110       }
1111 
1112     case '8': /* --log-facility */
1113       /* may be a filename */
1114       if (strchr(arg, '/'))
1115 	daemon->log_file = opt_string_alloc(arg);
1116       else
1117 	{
1118 #ifdef __ANDROID__
1119 	    problem = "Android does not support log facilities";
1120 #else
1121 	  for (i = 0; facilitynames[i].c_name; i++)
1122 	    if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1123 	      break;
1124 
1125 	  if (facilitynames[i].c_name)
1126 	    daemon->log_fac = facilitynames[i].c_val;
1127 	  else
1128 	    problem = "bad log facility";
1129 #endif
1130 	}
1131       break;
1132 
1133     case 'x': /* --pid-file */
1134       daemon->runfile = opt_string_alloc(arg);
1135       break;
1136 
1137     case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1138       if (daemon->dhcp_hosts_file)
1139 	problem = _("only one dhcp-hostsfile allowed");
1140       else
1141 	daemon->dhcp_hosts_file = opt_string_alloc(arg);
1142       break;
1143 
1144     case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1145       if (daemon->dhcp_opts_file)
1146 	problem = _("only one dhcp-optsfile allowed");
1147       else
1148 	daemon->dhcp_opts_file = opt_string_alloc(arg);
1149       break;
1150 
1151     case 'r': /* --resolv-file */
1152       {
1153 	char *name = opt_string_alloc(arg);
1154 	struct resolvc *new, *list = daemon->resolv_files;
1155 
1156 	if (list && list->is_default)
1157 	  {
1158 	    /* replace default resolv file - possibly with nothing */
1159 	    if (name)
1160 	      {
1161 		list->is_default = 0;
1162 		list->name = name;
1163 	      }
1164 	    else
1165 	      list = NULL;
1166 	  }
1167 	else if (name)
1168 	  {
1169 	    new = opt_malloc(sizeof(struct resolvc));
1170 	    new->next = list;
1171 	    new->name = name;
1172 	    new->is_default = 0;
1173 	    new->mtime = 0;
1174 	    new->logged = 0;
1175 	    list = new;
1176 	  }
1177 	daemon->resolv_files = list;
1178 	break;
1179       }
1180 
1181     case 'm':  /* --mx-host */
1182       {
1183 	int pref = 1;
1184 	struct mx_srv_record *new;
1185 	char *name, *target = NULL;
1186 
1187 	if ((comma = split(arg)))
1188 	  {
1189 	    char *prefstr;
1190 	    if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1191 	      problem = _("bad MX preference");
1192 	  }
1193 
1194 	if (!(name = canonicalise_opt(arg)) ||
1195 	    (comma && !(target = canonicalise_opt(comma))))
1196 	  problem = _("bad MX name");
1197 
1198 	new = opt_malloc(sizeof(struct mx_srv_record));
1199 	new->next = daemon->mxnames;
1200 	daemon->mxnames = new;
1201 	new->issrv = 0;
1202 	new->name = name;
1203 	new->target = target; /* may be NULL */
1204 	new->weight = pref;
1205 	break;
1206       }
1207 
1208     case 't': /*  --mx-target */
1209       if (!(daemon->mxtarget = canonicalise_opt(arg)))
1210 	problem = _("bad MX target");
1211       break;
1212 
1213 #ifdef HAVE_DHCP
1214     case 'l':  /* --dhcp-leasefile */
1215       daemon->lease_file = opt_string_alloc(arg);
1216       break;
1217 
1218     case '6': /* --dhcp-script */
1219 #  if defined(NO_FORK)
1220       problem = _("cannot run scripts under uClinux");
1221 #  elif !defined(HAVE_SCRIPT)
1222       problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1223 #  else
1224       daemon->lease_change_command = opt_string_alloc(arg);
1225 #  endif
1226       break;
1227 #endif
1228 
1229     case 'H': /* --addn-hosts */
1230       {
1231 	struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1232 	static int hosts_index = 1;
1233 	new->fname = opt_string_alloc(arg);
1234 	new->index = hosts_index++;
1235 	new->flags = 0;
1236 	new->next = daemon->addn_hosts;
1237 	daemon->addn_hosts = new;
1238 	break;
1239       }
1240 
1241     case 's': /* --domain */
1242       if (strcmp (arg, "#") == 0)
1243 	daemon->options |= OPT_RESOLV_DOMAIN;
1244       else
1245 	{
1246 	  char *d;
1247 	  comma = split(arg);
1248 	  if (!(d = canonicalise_opt(arg)))
1249 	    option = '?';
1250 	  else
1251 	    {
1252 	      if (comma)
1253 		{
1254 		  struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
1255 		  unhide_metas(comma);
1256 		  if ((arg = split_chr(comma, '/')))
1257 		    {
1258 		      int mask;
1259 		      if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1260 			  !atoi_check(arg, &mask))
1261 			option = '?';
1262 		      else
1263 			{
1264 			  mask = (1 << (32 - mask)) - 1;
1265 			  new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1266 			  new->end.s_addr = new->start.s_addr | htonl(mask);
1267 			}
1268 		    }
1269 		  else if ((arg = split(comma)))
1270 		    {
1271 		      if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1272 			  (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
1273 			option = '?';
1274 		    }
1275 		  else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1276 		    option = '?';
1277 
1278 		  new->domain = d;
1279 		  new->next = daemon->cond_domain;
1280 		  daemon->cond_domain = new;
1281 		}
1282 	      else
1283 		daemon->domain_suffix = d;
1284 	    }
1285 	}
1286       break;
1287 
1288     case 'u':  /* --user */
1289       daemon->username = opt_string_alloc(arg);
1290       break;
1291 
1292     case 'g':  /* --group */
1293       daemon->groupname = opt_string_alloc(arg);
1294       daemon->group_set = 1;
1295       break;
1296 
1297 #ifdef HAVE_DHCP
1298     case LOPT_SCRIPTUSR: /* --scriptuser */
1299       daemon->scriptuser = opt_string_alloc(arg);
1300       break;
1301 #endif
1302 
1303     case 'i':  /* --interface */
1304       do {
1305 	struct iname *new = opt_malloc(sizeof(struct iname));
1306 	comma = split(arg);
1307 	new->next = daemon->if_names;
1308 	daemon->if_names = new;
1309 	/* new->name may be NULL if someone does
1310 	   "interface=" to disable all interfaces except loop. */
1311 	new->name = opt_string_alloc(arg);
1312 	new->isloop = new->used = 0;
1313 	arg = comma;
1314       } while (arg);
1315       break;
1316 
1317     case 'I':  /* --except-interface */
1318     case '2':  /* --no-dhcp-interface */
1319       do {
1320 	struct iname *new = opt_malloc(sizeof(struct iname));
1321 	comma = split(arg);
1322 	new->name = opt_string_alloc(arg);
1323 	if (option == 'I')
1324 	  {
1325 	    new->next = daemon->if_except;
1326 	    daemon->if_except = new;
1327 	  }
1328 	else
1329 	  {
1330 	    new->next = daemon->dhcp_except;
1331 	    daemon->dhcp_except = new;
1332 	  }
1333 	arg = comma;
1334       } while (arg);
1335       break;
1336 
1337     case 'B':  /* --bogus-nxdomain */
1338       {
1339 	struct in_addr addr;
1340 	unhide_metas(arg);
1341 	if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1342 	  {
1343 	    struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1344 	    baddr->next = daemon->bogus_addr;
1345 	    daemon->bogus_addr = baddr;
1346 	    baddr->addr = addr;
1347 	  }
1348 	else
1349 	  option = '?'; /* error */
1350 	break;
1351       }
1352 
1353     case 'a':  /* --listen-address */
1354       do {
1355 	struct iname *new = opt_malloc(sizeof(struct iname));
1356 	comma = split(arg);
1357 	unhide_metas(arg);
1358 	new->next = daemon->if_addrs;
1359 	if (arg &&
1360 	    parse_addr(AF_INET, arg, &new->addr) != 0 &&
1361 	    parse_addr(AF_INET6, arg, &new->addr) != 0)
1362 	  {
1363 	    option = '?'; /* error */
1364 	    break;
1365 	  }
1366 
1367 	daemon->if_addrs = new;
1368 	arg = comma;
1369       } while (arg);
1370       break;
1371 
1372     case 'S':        /*  --server */
1373     case LOPT_LOCAL: /*  --local */
1374     case 'A':        /*  --address */
1375       {
1376 	struct server *serv, *newlist = NULL;
1377 
1378 	unhide_metas(arg);
1379 
1380 	if (arg && *arg == '/')
1381 	  {
1382 	    char *end;
1383 	    arg++;
1384 	    while ((end = split_chr(arg, '/')))
1385 	      {
1386 		char *domain = NULL;
1387 		/* # matches everything and becomes a zero length domain string */
1388 		if (strcmp(arg, "#") == 0)
1389 		  domain = "";
1390 		else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1391 		  option = '?';
1392 		serv = opt_malloc(sizeof(struct server));
1393 		memset(serv, 0, sizeof(struct server));
1394 		serv->next = newlist;
1395 		newlist = serv;
1396 		serv->domain = domain;
1397 		serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1398 		arg = end;
1399 	      }
1400 	    if (!newlist)
1401 	      {
1402 		option = '?';
1403 		break;
1404 	      }
1405 
1406 	  }
1407 	else
1408 	  {
1409 	    newlist = opt_malloc(sizeof(struct server));
1410 	    memset(newlist, 0, sizeof(struct server));
1411 	  }
1412 
1413 	if (option == 'A')
1414 	  {
1415 	    newlist->flags |= SERV_LITERAL_ADDRESS;
1416 	    if (!(newlist->flags & SERV_TYPE))
1417 	      option = '?';
1418 	  }
1419 
1420 	if (!arg || !*arg)
1421 	  {
1422 	    newlist->flags |= SERV_NO_ADDR; /* no server */
1423 	    if (newlist->flags & SERV_LITERAL_ADDRESS)
1424 	      option = '?';
1425 	  }
1426 	else
1427 	  {
1428 	    int source_port = 0, serv_port = NAMESERVER_PORT;
1429 	    char *portno, *source;
1430 
1431 	    if ((source = split_chr(arg, '@')) && /* is there a source. */
1432 		(portno = split_chr(source, '#')) &&
1433 		!atoi_check16(portno, &source_port))
1434 	      problem = _("bad port");
1435 
1436 	    if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1437 		!atoi_check16(portno, &serv_port))
1438 	      problem = _("bad port");
1439 
1440 	    if (parse_addr(AF_INET, arg, &newlist->addr) == 0)
1441 	      {
1442 		newlist->addr.in.sin_port = htons(serv_port);
1443 #ifdef HAVE_SOCKADDR_SA_LEN
1444 		newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
1445 #endif
1446 		if (source)
1447 		  {
1448 		    newlist->flags |= SERV_HAS_SOURCE;
1449 		    if (parse_addr(AF_INET, source, &newlist->addr) != 0)
1450 		      {
1451 #if defined(SO_BINDTODEVICE)
1452 			newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1453 			strncpy(newlist->interface, source, IF_NAMESIZE);
1454 #else
1455 			problem = _("interface binding not supported");
1456 #endif
1457 		      }
1458 		  }
1459 		else
1460 		  newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1461 
1462 		newlist->source_addr.in.sin_port = htons(source_port);
1463 		newlist->source_addr.sa.sa_family = AF_INET;
1464 	      }
1465 #ifdef HAVE_IPV6
1466 	    else if (parse_addr(AF_INET6, arg, &newlist->addr) == 0)
1467 	      {
1468 		newlist->addr.in6.sin6_port = htons(serv_port);
1469 		if (source)
1470 		  {
1471 		     newlist->flags |= SERV_HAS_SOURCE;
1472 		     if (parse_addr(AF_INET6, source, &newlist->source_addr) != 0)
1473 		      {
1474 #if defined(SO_BINDTODEVICE)
1475 			newlist->source_addr.in6.sin6_addr = in6addr_any;
1476 			strncpy(newlist->interface, source, IF_NAMESIZE);
1477 #else
1478 			problem = _("interface binding not supported");
1479 #endif
1480 		      }
1481 		  }
1482 		else
1483 		  newlist->source_addr.in6.sin6_addr = in6addr_any;
1484 
1485 		newlist->source_addr.in6.sin6_port = htons(source_port);
1486 		newlist->source_addr.sa.sa_family = AF_INET6;
1487 	      }
1488 #endif
1489 	    else
1490 	      option = '?'; /* error */
1491 
1492 	  }
1493 
1494 	serv = newlist;
1495 	while (serv->next)
1496 	  {
1497 	    serv->next->flags = serv->flags;
1498 	    serv->next->addr = serv->addr;
1499 	    serv->next->source_addr = serv->source_addr;
1500 	    serv = serv->next;
1501 	  }
1502 	serv->next = daemon->servers;
1503 	daemon->servers = newlist;
1504 	break;
1505       }
1506 
1507     case 'c':  /* --cache-size */
1508       {
1509 	int size;
1510 
1511 	if (!atoi_check(arg, &size))
1512 	  option = '?';
1513 	else
1514 	  {
1515 	    /* zero is OK, and means no caching. */
1516 
1517 	    if (size < 0)
1518 	      size = 0;
1519 	    else if (size > 10000)
1520 	      size = 10000;
1521 
1522 	    daemon->cachesize = size;
1523 	  }
1524 	break;
1525       }
1526 
1527     case 'p':  /* --port */
1528       if (!atoi_check16(arg, &daemon->port))
1529 	option = '?';
1530       break;
1531 
1532     case LOPT_MINPORT:  /* --min-port */
1533       if (!atoi_check16(arg, &daemon->min_port))
1534 	option = '?';
1535       break;
1536 
1537     case '0':  /* --dns-forward-max */
1538       if (!atoi_check(arg, &daemon->ftabsize))
1539 	option = '?';
1540       break;
1541 
1542     case LOPT_MAX_LOGS:  /* --log-async */
1543       daemon->max_logs = LOG_MAX; /* default */
1544       if (arg && !atoi_check(arg, &daemon->max_logs))
1545 	option = '?';
1546       else if (daemon->max_logs > 100)
1547 	daemon->max_logs = 100;
1548       break;
1549 
1550     case 'P': /* --edns-packet-max */
1551       {
1552 	int i;
1553 	if (!atoi_check(arg, &i))
1554 	  option = '?';
1555 	daemon->edns_pktsz = (unsigned short)i;
1556 	break;
1557       }
1558 
1559     case 'Q':  /* --query-port */
1560       if (!atoi_check16(arg, &daemon->query_port))
1561 	option = '?';
1562       /* if explicitly set to zero, use single OS ephemeral port
1563 	 and disable random ports */
1564       if (daemon->query_port == 0)
1565 	daemon->osport = 1;
1566       break;
1567 
1568     case 'T':         /* --local-ttl */
1569     case LOPT_NEGTTL: /* --neg-ttl */
1570       {
1571 	int ttl;
1572 	if (!atoi_check(arg, &ttl))
1573 	  option = '?';
1574 	else if (option == LOPT_NEGTTL)
1575 	  daemon->neg_ttl = (unsigned long)ttl;
1576 	else
1577 	  daemon->local_ttl = (unsigned long)ttl;
1578 	break;
1579       }
1580 
1581 #ifdef HAVE_DHCP
1582     case 'X': /* --dhcp-lease-max */
1583       if (!atoi_check(arg, &daemon->dhcp_max))
1584 	option = '?';
1585       break;
1586 #endif
1587 
1588     case LOPT_BRIDGE:   /* --bridge-interface */
1589       {
1590 	struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
1591 	if (!(comma = split(arg)))
1592 	  {
1593 	    problem = _("bad bridge-interface");
1594 	    break;
1595 	  }
1596 
1597 	strncpy(new->iface, arg, IF_NAMESIZE);
1598 	new->alias = NULL;
1599 	new->next = daemon->bridges;
1600 	daemon->bridges = new;
1601 
1602 	do {
1603 	  arg = comma;
1604 	  comma = split(arg);
1605 	  if (strlen(arg) != 0)
1606 	    {
1607 	      struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
1608 	      b->next = new->alias;
1609 	      new->alias = b;
1610 	      strncpy(b->iface, arg, IF_NAMESIZE);
1611 	    }
1612 	} while (comma);
1613 
1614 	break;
1615       }
1616 
1617 #ifdef HAVE_DHCP
1618     case 'F':  /* --dhcp-range */
1619       {
1620 	int k, leasepos = 2;
1621 	char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
1622 	struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
1623 
1624 	new->next = daemon->dhcp;
1625 	new->lease_time = DEFLEASE;
1626 	new->addr_epoch = 0;
1627 	new->netmask.s_addr = 0;
1628 	new->broadcast.s_addr = 0;
1629 	new->router.s_addr = 0;
1630 	new->netid.net = NULL;
1631 	new->filter = NULL;
1632 	new->flags = 0;
1633 
1634 	gen_prob = _("bad dhcp-range");
1635 
1636 	if (!arg)
1637 	  {
1638 	    option = '?';
1639 	    break;
1640 	  }
1641 
1642 	while(1)
1643 	  {
1644 	    for (cp = arg; *cp; cp++)
1645 	      if (!(*cp == ' ' || *cp == '.' ||  (*cp >='0' && *cp <= '9')))
1646 		break;
1647 
1648 	    if (*cp != ',' && (comma = split(arg)))
1649 	      {
1650 		if (strstr(arg, "net:") == arg)
1651 		  {
1652 		    struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
1653 		    tt->net = opt_string_alloc(arg+4);
1654 		    tt->next = new->filter;
1655 		    new->filter = tt;
1656 		  }
1657 		else
1658 		  {
1659 		    if (new->netid.net)
1660 		      problem = _("only one netid tag allowed");
1661 		    else
1662 		      new->netid.net = opt_string_alloc(arg);
1663 		  }
1664 		arg = comma;
1665 	      }
1666 	    else
1667 	      {
1668 		a[0] = arg;
1669 		break;
1670 	      }
1671 	  }
1672 
1673 	for (k = 1; k < 5; k++)
1674 	  if (!(a[k] = split(a[k-1])))
1675 	    break;
1676 
1677 	if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
1678 	  option = '?';
1679 	else if (strcmp(a[1], "static") == 0)
1680 	  {
1681 	    new->end = new->start;
1682 	    new->flags |= CONTEXT_STATIC;
1683 	  }
1684 	else if (strcmp(a[1], "proxy") == 0)
1685 	  {
1686 	    new->end = new->start;
1687 	    new->flags |= CONTEXT_PROXY;
1688 	  }
1689 	else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
1690 	  option = '?';
1691 
1692 	if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
1693 	  {
1694 	    struct in_addr tmp = new->start;
1695 	    new->start = new->end;
1696 	    new->end = tmp;
1697 	  }
1698 
1699 	if (option != '?' && k >= 3 && strchr(a[2], '.') &&
1700 	    ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
1701 	  {
1702 	    new->flags |= CONTEXT_NETMASK;
1703 	    leasepos = 3;
1704 	    if (!is_same_net(new->start, new->end, new->netmask))
1705 	      problem = _("inconsistent DHCP range");
1706 	  }
1707 	daemon->dhcp = new;
1708 
1709 	if (k >= 4 && strchr(a[3], '.') &&
1710 	    ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
1711 	  {
1712 	    new->flags |= CONTEXT_BRDCAST;
1713 	    leasepos = 4;
1714 	  }
1715 
1716 	if (k >= leasepos+1)
1717 	  {
1718 	    if (strcmp(a[leasepos], "infinite") == 0)
1719 	      new->lease_time = 0xffffffff;
1720 	    else
1721 	      {
1722 		int fac = 1;
1723 		if (strlen(a[leasepos]) > 0)
1724 		  {
1725 		    switch (a[leasepos][strlen(a[leasepos]) - 1])
1726 		      {
1727 		      case 'd':
1728 		      case 'D':
1729 			fac *= 24;
1730 			/* fall though */
1731 		      case 'h':
1732 		      case 'H':
1733 			fac *= 60;
1734 			/* fall through */
1735 		      case 'm':
1736 		      case 'M':
1737 			fac *= 60;
1738 			/* fall through */
1739 		      case 's':
1740 		      case 'S':
1741 			a[leasepos][strlen(a[leasepos]) - 1] = 0;
1742 		      }
1743 
1744 		    new->lease_time = atoi(a[leasepos]) * fac;
1745 		    /* Leases of a minute or less confuse
1746 		       some clients, notably Apple's */
1747 		    if (new->lease_time < 120)
1748 		      new->lease_time = 120;
1749 		  }
1750 	      }
1751 	  }
1752 	break;
1753       }
1754 
1755     case LOPT_BANK:
1756     case 'G':  /* --dhcp-host */
1757       {
1758 	int j, k = 0;
1759 	char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
1760 	struct dhcp_config *new;
1761 	struct in_addr in;
1762 
1763 	new = opt_malloc(sizeof(struct dhcp_config));
1764 
1765 	new->next = daemon->dhcp_conf;
1766 	new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
1767 	new->hwaddr = NULL;
1768 
1769 	if ((a[0] = arg))
1770 	  for (k = 1; k < 6; k++)
1771 	    if (!(a[k] = split(a[k-1])))
1772 	      break;
1773 
1774 	for (j = 0; j < k; j++)
1775 	  if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
1776 	    {
1777 	      char *arg = a[j];
1778 
1779 	      if ((arg[0] == 'i' || arg[0] == 'I') &&
1780 		  (arg[1] == 'd' || arg[1] == 'D') &&
1781 		  arg[2] == ':')
1782 		{
1783 		  if (arg[3] == '*')
1784 		    new->flags |= CONFIG_NOCLID;
1785 		  else
1786 		    {
1787 		      int len;
1788 		      arg += 3; /* dump id: */
1789 		      if (strchr(arg, ':'))
1790 			len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
1791 		      else
1792 			{
1793 			  unhide_metas(arg);
1794 			  len = (int) strlen(arg);
1795 			}
1796 
1797 		      if ((new->clid = opt_malloc(len)))
1798 			{
1799 			  new->flags |= CONFIG_CLID;
1800 			  new->clid_len = len;
1801 			  memcpy(new->clid, arg, len);
1802 			}
1803 		    }
1804 		}
1805 	      else if (strstr(arg, "net:") == arg)
1806 		{
1807 		  int len = strlen(arg + 4) + 1;
1808 		  if ((new->netid.net = opt_malloc(len)))
1809 		    {
1810 		      new->flags |= CONFIG_NETID;
1811 		      strcpy(new->netid.net, arg+4);
1812 		      unhide_metas(new->netid.net);
1813 		    }
1814 		}
1815 	      else
1816 		{
1817 		  struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
1818 		  newhw->next = new->hwaddr;
1819 		  new->hwaddr = newhw;
1820 		  newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
1821 						&newhw->wildcard_mask, &newhw->hwaddr_type);
1822 		}
1823 	    }
1824 	  else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
1825 	    {
1826 	      new->addr = in;
1827 	      new->flags |= CONFIG_ADDR;
1828 	    }
1829 	  else
1830 	    {
1831 	      char *cp, *lastp = NULL, last = 0;
1832 	      int fac = 1;
1833 
1834 	      if (strlen(a[j]) > 1)
1835 		{
1836 		  lastp = a[j] + strlen(a[j]) - 1;
1837 		  last = *lastp;
1838 		  switch (last)
1839 		    {
1840 		    case 'd':
1841 		    case 'D':
1842 		      fac *= 24;
1843 		      /* fall through */
1844 		    case 'h':
1845 		    case 'H':
1846 		      fac *= 60;
1847 		      /* fall through */
1848 		    case 'm':
1849 		    case 'M':
1850 		      fac *= 60;
1851 		      /* fall through */
1852 		    case 's':
1853 		    case 'S':
1854 		      *lastp = 0;
1855 		    }
1856 		}
1857 
1858 	      for (cp = a[j]; *cp; cp++)
1859 		if (!isdigit((int)*cp) && *cp != ' ')
1860 		  break;
1861 
1862 	      if (*cp)
1863 		{
1864 		  if (lastp)
1865 		    *lastp = last;
1866 		  if (strcmp(a[j], "infinite") == 0)
1867 		    {
1868 		      new->lease_time = 0xffffffff;
1869 		      new->flags |= CONFIG_TIME;
1870 		    }
1871 		  else if (strcmp(a[j], "ignore") == 0)
1872 		    new->flags |= CONFIG_DISABLE;
1873 		  else
1874 		    {
1875 		      if (!(new->hostname = canonicalise_opt(a[j])) ||
1876 			  !legal_hostname(new->hostname))
1877 			problem = _("bad DHCP host name");
1878 		      else
1879 			new->flags |= CONFIG_NAME;
1880 		      new->domain = NULL;
1881 		    }
1882 		}
1883 	      else
1884 		{
1885 		  new->lease_time = atoi(a[j]) * fac;
1886 		  /* Leases of a minute or less confuse
1887 		     some clients, notably Apple's */
1888 		  if (new->lease_time < 120)
1889 		    new->lease_time = 120;
1890 		  new->flags |= CONFIG_TIME;
1891 		}
1892 	    }
1893 
1894 	daemon->dhcp_conf = new;
1895 	break;
1896       }
1897 
1898     case 'O':           /* --dhcp-option */
1899     case LOPT_FORCE:    /* --dhcp-option-force */
1900     case LOPT_OPTS:
1901     case LOPT_MATCH:    /* --dhcp-match */
1902       problem = parse_dhcp_opt(arg,
1903 			       option == LOPT_FORCE ? DHOPT_FORCE :
1904 			       (option == LOPT_MATCH ? DHOPT_MATCH :
1905 			       (option == LOPT_OPTS ? DHOPT_BANK : 0)));
1906       break;
1907 
1908     case 'M': /* --dhcp-boot */
1909       {
1910 	struct dhcp_netid *id = NULL;
1911 	while (arg && strstr(arg, "net:") == arg)
1912 	  {
1913 	    struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
1914 	    newid->next = id;
1915 	    id = newid;
1916 	    comma = split(arg);
1917 	    newid->net = opt_string_alloc(arg+4);
1918 	    arg = comma;
1919 	  };
1920 
1921 	if (!arg)
1922 	  option = '?';
1923 	else
1924 	  {
1925 	    char *dhcp_file, *dhcp_sname = NULL;
1926 	    struct in_addr dhcp_next_server;
1927 	    comma = split(arg);
1928 	    dhcp_file = opt_string_alloc(arg);
1929 	    dhcp_next_server.s_addr = 0;
1930 	    if (comma)
1931 	      {
1932 		arg = comma;
1933 		comma = split(arg);
1934 		dhcp_sname = opt_string_alloc(arg);
1935 		if (comma)
1936 		  {
1937 		    unhide_metas(comma);
1938 		    if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1939 		      option = '?';
1940 		  }
1941 	      }
1942 	    if (option != '?')
1943 	      {
1944 		struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
1945 		new->file = dhcp_file;
1946 		new->sname = dhcp_sname;
1947 		new->next_server = dhcp_next_server;
1948 		new->netid = id;
1949 		new->next = daemon->boot_config;
1950 		daemon->boot_config = new;
1951 	      }
1952 	  }
1953 
1954 	break;
1955       }
1956 
1957     case LOPT_PXE_PROMT:  /* --pxe-prompt */
1958        {
1959 	 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
1960 	 int timeout;
1961 
1962 	 new->netid = NULL;
1963 	 new->opt = 10; /* PXE_MENU_PROMPT */
1964 
1965 	 while (arg && strstr(arg, "net:") == arg)
1966 	   {
1967 	     struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
1968 	     comma = split(arg);
1969 	     nn->next = new->netid;
1970 	     new->netid = nn;
1971 	     nn->net = opt_string_alloc(arg+4);
1972 	     arg = comma;
1973 	   }
1974 
1975 	 if (!arg)
1976 	   option = '?';
1977 	 else
1978 	   {
1979 	     comma = split(arg);
1980 	     unhide_metas(arg);
1981 	     new->len = strlen(arg) + 1;
1982 	     new->val = opt_malloc(new->len);
1983 	     memcpy(new->val + 1, arg, new->len - 1);
1984 
1985 	     new->u.vendor_class = (unsigned char *)"PXEClient";
1986 	     new->flags = DHOPT_VENDOR;
1987 
1988 	     if (comma && atoi_check(comma, &timeout))
1989 	       *(new->val) = timeout;
1990 	     else
1991 	       *(new->val) = 255;
1992 
1993 	     new->next = daemon->dhcp_opts;
1994 	     daemon->dhcp_opts = new;
1995 	     daemon->enable_pxe = 1;
1996 	   }
1997 
1998 	 break;
1999        }
2000 
2001     case LOPT_PXE_SERV:  /* --pxe-service */
2002        {
2003 	 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2004 	 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2005 			 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2006 	 static int boottype = 32768;
2007 
2008 	 new->netid = NULL;
2009 	 new->server.s_addr = 0;
2010 
2011 	 while (arg && strstr(arg, "net:") == arg)
2012 	   {
2013 	     struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2014 	     comma = split(arg);
2015 	     nn->next = new->netid;
2016 	     new->netid = nn;
2017 	     nn->net = opt_string_alloc(arg+4);
2018 	     arg = comma;
2019 	   }
2020 
2021 	 if (arg && (comma = split(arg)))
2022 	   {
2023 	     for (i = 0; CSA[i]; i++)
2024 	       if (strcasecmp(CSA[i], arg) == 0)
2025 		 break;
2026 
2027 	     if (CSA[i] || atoi_check(arg, &i))
2028 	       {
2029 		 arg = comma;
2030 		 comma = split(arg);
2031 
2032 		 new->CSA = i;
2033 		 new->menu = opt_string_alloc(arg);
2034 
2035 		 if (comma)
2036 		   {
2037 		     arg = comma;
2038 		     comma = split(arg);
2039 		     if (atoi_check(arg, &i))
2040 		       {
2041 			 new->type = i;
2042 			 new->basename = NULL;
2043 		       }
2044 		     else
2045 		       {
2046 			 new->type = boottype++;
2047 			 new->basename = opt_string_alloc(arg);
2048 		       }
2049 
2050 		     if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
2051 		       option = '?';
2052 
2053 		     /* Order matters */
2054 		     new->next = NULL;
2055 		     if (!daemon->pxe_services)
2056 		       daemon->pxe_services = new;
2057 		     else
2058 		       {
2059 			 struct pxe_service *s;
2060 			 for (s = daemon->pxe_services; s->next; s = s->next);
2061 			 s->next = new;
2062 		       }
2063 
2064 		     daemon->enable_pxe = 1;
2065 		     break;
2066 		   }
2067 	       }
2068 	   }
2069 
2070 	 option = '?';
2071 	 break;
2072        }
2073 
2074     case '4':  /* --dhcp-mac */
2075       {
2076 	if (!(comma = split(arg)))
2077 	  option = '?';
2078 	else
2079 	  {
2080 	    struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2081 	    if (strstr(arg, "net:") == arg)
2082 	      new->netid.net = opt_string_alloc(arg+4);
2083 	    else
2084 	      new->netid.net = opt_string_alloc(arg);
2085 	    unhide_metas(comma);
2086 	    new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2087 	    new->next = daemon->dhcp_macs;
2088 	    daemon->dhcp_macs = new;
2089 	  }
2090       }
2091       break;
2092 
2093     case 'U':           /* --dhcp-vendorclass */
2094     case 'j':           /* --dhcp-userclass */
2095     case LOPT_CIRCUIT:  /* --dhcp-circuitid */
2096     case LOPT_REMOTE:   /* --dhcp-remoteid */
2097     case LOPT_SUBSCR:   /* --dhcp-subscrid */
2098       {
2099 	if (!(comma = split(arg)))
2100 	  option = '?';
2101 	else
2102 	  {
2103 	    char *p;
2104 	    int dig = 0;
2105 	    struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2106 	    if (strstr(arg, "net:") == arg)
2107 	      new->netid.net = opt_string_alloc(arg+4);
2108 	    else
2109 	      new->netid.net = opt_string_alloc(arg);
2110 	    /* check for hex string - must digits may include : must not have nothing else,
2111 	       only allowed for agent-options. */
2112 	    for (p = comma; *p; p++)
2113 	      if (isxdigit((int)*p))
2114 		dig = 1;
2115 	      else if (*p != ':')
2116 		break;
2117 	    unhide_metas(comma);
2118 	    if (option == 'U' || option == 'j' || *p || !dig)
2119 	      {
2120 		new->len = strlen(comma);
2121 		new->data = opt_malloc(new->len);
2122 		memcpy(new->data, comma, new->len);
2123 	      }
2124 	    else
2125 	      {
2126 		new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2127 		new->data = opt_malloc(new->len);
2128 		memcpy(new->data, comma, new->len);
2129 	      }
2130 
2131 	    switch (option)
2132 	      {
2133 	      case 'j':
2134 		new->match_type = MATCH_USER;
2135 		break;
2136 	      case 'U':
2137 		new->match_type = MATCH_VENDOR;
2138 		break;
2139 	      case LOPT_CIRCUIT:
2140 		new->match_type = MATCH_CIRCUIT;
2141 		break;
2142 	      case LOPT_REMOTE:
2143 		new->match_type = MATCH_REMOTE;
2144 		break;
2145 	      case LOPT_SUBSCR:
2146 		new->match_type = MATCH_SUBSCRIBER;
2147 		break;
2148 	      }
2149 	    new->next = daemon->dhcp_vendors;
2150 	    daemon->dhcp_vendors = new;
2151 	  }
2152 	break;
2153       }
2154 
2155     case LOPT_ALTPORT:   /* --dhcp-alternate-port */
2156       if (!arg)
2157 	{
2158 	  daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2159 	  daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2160 	}
2161       else
2162 	{
2163 	  comma = split(arg);
2164 	  if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2165 	      (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
2166 	    problem = _("invalid port number");
2167 	  if (!comma)
2168 	    daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2169 	}
2170       break;
2171 
2172     case 'J':            /* --dhcp-ignore */
2173     case LOPT_NO_NAMES:  /* --dhcp-ignore-names */
2174     case LOPT_BROADCAST: /* --dhcp-broadcast */
2175     case '3':            /* --bootp-dynamic */
2176       {
2177 	struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
2178 	struct dhcp_netid *list = NULL;
2179 	if (option == 'J')
2180 	  {
2181 	    new->next = daemon->dhcp_ignore;
2182 	    daemon->dhcp_ignore = new;
2183 	  }
2184 	else if (option == LOPT_BROADCAST)
2185 	  {
2186 	    new->next = daemon->force_broadcast;
2187 	    daemon->force_broadcast = new;
2188 	  }
2189 	else if (option == '3')
2190 	  {
2191 	    new->next = daemon->bootp_dynamic;
2192 	    daemon->bootp_dynamic = new;
2193 	  }
2194 	else
2195 	  {
2196 	    new->next = daemon->dhcp_ignore_names;
2197 	    daemon->dhcp_ignore_names = new;
2198 	  }
2199 
2200 	while (arg) {
2201 	  struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
2202 	  comma = split(arg);
2203 	  member->next = list;
2204 	  list = member;
2205 	  if (strstr(arg, "net:") == arg)
2206 	    member->net = opt_string_alloc(arg+4);
2207 	  else
2208 	    member->net = opt_string_alloc(arg);
2209 	  arg = comma;
2210 	}
2211 
2212 	new->list = list;
2213 	break;
2214       }
2215 #endif
2216 
2217     case 'V':  /* --alias */
2218       {
2219 	char *dash, *a[3] = { NULL, NULL, NULL };
2220 	int k = 0;
2221 	struct doctor *new = opt_malloc(sizeof(struct doctor));
2222 	new->next = daemon->doctors;
2223 	daemon->doctors = new;
2224 	new->mask.s_addr = 0xffffffff;
2225 	new->end.s_addr = 0;
2226 
2227 	if ((a[0] = arg))
2228 	  for (k = 1; k < 3; k++)
2229 	    {
2230 	      if (!(a[k] = split(a[k-1])))
2231 		break;
2232 	      unhide_metas(a[k]);
2233 	    }
2234 
2235 	dash = split_chr(a[0], '-');
2236 
2237 	if ((k < 2) ||
2238 	    ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
2239 	    ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
2240 	  option = '?';
2241 
2242 	if (k == 3)
2243 	  new->mask.s_addr = inet_addr(a[2]);
2244 
2245 	if (dash &&
2246 	    ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
2247 	     !is_same_net(new->in, new->end, new->mask) ||
2248 	     ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
2249 	  problem = _("invalid alias range");
2250 
2251 	break;
2252       }
2253 
2254     case LOPT_INTNAME:  /* --interface-name */
2255       {
2256 	struct interface_name *new, **up;
2257 	char *domain = NULL;
2258 
2259 	comma = split(arg);
2260 
2261 	if (!comma || !(domain = canonicalise_opt(arg)))
2262 	  problem = _("bad interface name");
2263 
2264 	new = opt_malloc(sizeof(struct interface_name));
2265 	new->next = NULL;
2266 	/* Add to the end of the list, so that first name
2267 	   of an interface is used for PTR lookups. */
2268 	for (up = &daemon->int_names; *up; up = &((*up)->next));
2269 	*up = new;
2270 	new->name = domain;
2271 	new->intr = opt_string_alloc(comma);
2272 	break;
2273       }
2274 
2275     case LOPT_CNAME: /* --cname */
2276       {
2277 	struct cname *new;
2278 
2279 	if (!(comma = split(arg)))
2280 	  option = '?';
2281 	else
2282 	  {
2283 	    char *alias = canonicalise_opt(arg);
2284 	    char *target = canonicalise_opt(comma);
2285 
2286 	    if (!alias || !target)
2287 	      problem = _("bad CNAME");
2288 	    else
2289 	      {
2290 		for (new = daemon->cnames; new; new = new->next)
2291 		  if (hostname_isequal(new->alias, arg))
2292 		    problem = _("duplicate CNAME");
2293 		new = opt_malloc(sizeof(struct cname));
2294 		new->next = daemon->cnames;
2295 		daemon->cnames = new;
2296 		new->alias = alias;
2297 		new->target = target;
2298 	      }
2299 	  }
2300 	break;
2301       }
2302 
2303     case LOPT_PTR:  /* --ptr-record */
2304       {
2305 	struct ptr_record *new;
2306 	char *dom, *target = NULL;
2307 
2308 	comma = split(arg);
2309 
2310 	if (!(dom = canonicalise_opt(arg)) ||
2311 	    (comma && !(target = canonicalise_opt(comma))))
2312 	  problem = _("bad PTR record");
2313 	else
2314 	  {
2315 	    new = opt_malloc(sizeof(struct ptr_record));
2316 	    new->next = daemon->ptr;
2317 	    daemon->ptr = new;
2318 	    new->name = dom;
2319 	    new->ptr = target;
2320 	  }
2321 	break;
2322       }
2323 
2324     case LOPT_NAPTR: /* --naptr-record */
2325       {
2326 	char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2327 	int k = 0;
2328 	struct naptr *new;
2329 	int order, pref;
2330 	char *name, *replace = NULL;
2331 
2332 	if ((a[0] = arg))
2333 	  for (k = 1; k < 7; k++)
2334 	    if (!(a[k] = split(a[k-1])))
2335 	      break;
2336 
2337 
2338 	if (k < 6 ||
2339 	    !(name = canonicalise_opt(a[0])) ||
2340 	    !atoi_check16(a[1], &order) ||
2341 	    !atoi_check16(a[2], &pref) ||
2342 	    (k == 7 && !(replace = canonicalise_opt(a[6]))))
2343 	  problem = _("bad NAPTR record");
2344 	else
2345 	  {
2346 	    new = opt_malloc(sizeof(struct naptr));
2347 	    new->next = daemon->naptr;
2348 	    daemon->naptr = new;
2349 	    new->name = name;
2350 	    new->flags = opt_string_alloc(a[3]);
2351 	    new->services = opt_string_alloc(a[4]);
2352 	    new->regexp = opt_string_alloc(a[5]);
2353 	    new->replace = replace;
2354 	    new->order = order;
2355 	    new->pref = pref;
2356 	  }
2357 	break;
2358       }
2359 
2360     case 'Y':  /* --txt-record */
2361       {
2362 	struct txt_record *new;
2363 	unsigned char *p, *q;
2364 
2365 	if ((comma = split(arg)))
2366 	  comma--;
2367 
2368 	gen_prob = _("TXT record string too long");
2369 
2370 	if ((q = (unsigned char *)comma))
2371 	  while (1)
2372 	    {
2373 	      size_t len;
2374 	      if ((p = (unsigned char *)strchr((char*)q+1, ',')))
2375 		{
2376 		  if ((len = p - q - 1) > 255)
2377 		    option = '?';
2378 		  *q = len;
2379 		  for (q = q+1; q < p; q++)
2380 		    *q = unhide_meta(*q);
2381 		}
2382 	      else
2383 		{
2384 		  if ((len = strlen((char *)q+1)) > 255)
2385 		    option = '?';
2386 		  *q = len;
2387 		  for (q = q+1; *q; q++)
2388 		    *q = unhide_meta(*q);
2389 		  break;
2390 		}
2391 	    }
2392 
2393 	new = opt_malloc(sizeof(struct txt_record));
2394 	new->next = daemon->txt;
2395 	daemon->txt = new;
2396 	new->class = C_IN;
2397 	if (comma)
2398 	  {
2399 	    new->len = q - ((unsigned char *)comma);
2400 	    new->txt = opt_malloc(new->len);
2401 	    memcpy(new->txt, comma, new->len);
2402 	  }
2403 	else
2404 	  {
2405 	    static char empty[] = "";
2406 	    new->len = 1;
2407 	    new->txt = empty;
2408 	  }
2409 
2410 	/* ensure arg is terminated */
2411 	if (comma)
2412 	  *comma = 0;
2413 
2414 	if (!(new->name = canonicalise_opt(arg)))
2415 	  {
2416 	    problem = _("bad TXT record");
2417 	    break;
2418 	  }
2419 
2420 	break;
2421       }
2422 
2423     case 'W':  /* --srv-host */
2424       {
2425 	int port = 1, priority = 0, weight = 0;
2426 	char *name, *target = NULL;
2427 	struct mx_srv_record *new;
2428 
2429 	comma = split(arg);
2430 
2431 	if (!(name = canonicalise_opt(arg)))
2432 	  problem = _("bad SRV record");
2433 
2434 	if (comma)
2435 	  {
2436 	    arg = comma;
2437 	    comma = split(arg);
2438 	    if (!(target = canonicalise_opt(arg))
2439 )	      problem = _("bad SRV target");
2440 
2441 	    if (comma)
2442 	      {
2443 		arg = comma;
2444 		comma = split(arg);
2445 		if (!atoi_check16(arg, &port))
2446 		  problem = _("invalid port number");
2447 
2448 		if (comma)
2449 		  {
2450 		    arg = comma;
2451 		    comma = split(arg);
2452 		    if (!atoi_check16(arg, &priority))
2453 		      problem = _("invalid priority");
2454 
2455 		    if (comma)
2456 		      {
2457 			arg = comma;
2458 			comma = split(arg);
2459 			if (!atoi_check16(arg, &weight))
2460 			  problem = _("invalid weight");
2461 		      }
2462 		  }
2463 	      }
2464 	  }
2465 
2466 	new = opt_malloc(sizeof(struct mx_srv_record));
2467 	new->next = daemon->mxnames;
2468 	daemon->mxnames = new;
2469 	new->issrv = 1;
2470 	new->name = name;
2471 	new->target = target;
2472 	new->srvport = port;
2473 	new->priority = priority;
2474 	new->weight = weight;
2475 	break;
2476       }
2477 
2478     case LOPT_LISTNMARK: /* --listen-mark */
2479       {
2480 	char *endptr;
2481 	uint32_t mark = strtoul(arg, &endptr, 0);
2482         // my_syslog(LOG_WARNING, "passed-in mark: %s", arg);
2483 	if (!*endptr)
2484 	  daemon->listen_mark = mark;
2485 	else
2486 	  problem = _("invalid mark");
2487         // my_syslog(LOG_WARNING, "daemon->listen_mark: 0x%x, *endptr=%d", daemon->listen_mark, *endptr);
2488 	break;
2489       }
2490 
2491     default:
2492       return _("unsupported option (check that dnsmasq was compiled with DHCP support)");
2493 
2494     }
2495 
2496   if (problem)
2497     return problem;
2498 
2499   if (option == '?')
2500     return gen_prob;
2501 
2502   return NULL;
2503 }
2504 
one_file(char * file,int nest,int hard_opt)2505 static void one_file(char *file, int nest, int hard_opt)
2506 {
2507   volatile int lineno = 0;
2508   int i, option;
2509   FILE *f;
2510   char *p, *arg, *start, *buff = daemon->namebuff;
2511   static struct fileread {
2512     dev_t dev;
2513     ino_t ino;
2514     struct fileread *next;
2515   } *filesread = NULL;
2516   struct stat statbuf;
2517 
2518   /* ignore repeated files. */
2519   if (hard_opt == 0 && stat(file, &statbuf) == 0)
2520     {
2521       struct fileread *r;
2522 
2523       for (r = filesread; r; r = r->next)
2524 	if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
2525 	  return;
2526 
2527       r = safe_malloc(sizeof(struct fileread));
2528       r->next = filesread;
2529       filesread = r;
2530       r->dev = statbuf.st_dev;
2531       r->ino = statbuf.st_ino;
2532     }
2533 
2534   if (nest > 20)
2535     die(_("files nested too deep in %s"), file, EC_BADCONF);
2536 
2537   if (!(f = fopen(file, "r")))
2538     {
2539       if (errno == ENOENT && nest == 0)
2540 	return; /* No conffile, all done. */
2541       else
2542 	{
2543 	  char *str = _("cannot read %s: %s");
2544 	  if (hard_opt != 0)
2545 	    {
2546 	      my_syslog(LOG_ERR, str, file, strerror(errno));
2547 	      return;
2548 	    }
2549 	  else
2550 	    die(str, file, EC_FILE);
2551 	}
2552     }
2553 
2554   while (fgets(buff, MAXDNAME, f))
2555     {
2556       int white;
2557       unsigned int lastquote;
2558       char *errmess;
2559 
2560       /* Memory allocation failure longjmps here if mem_recover == 1 */
2561       if (hard_opt)
2562 	{
2563 	  if (setjmp(mem_jmp))
2564 	    continue;
2565 	  mem_recover = 1;
2566 	}
2567 
2568       lineno++;
2569       errmess = NULL;
2570 
2571       /* Implement quotes, inside quotes we allow \\ \" \n and \t
2572 	 metacharacters get hidden also strip comments */
2573 
2574       for (white = 1, lastquote = 0, p = buff; *p; p++)
2575 	{
2576 	  if (*p == '"')
2577 	    {
2578 	      memmove(p, p+1, strlen(p+1)+1);
2579 	      for(; *p && *p != '"'; p++)
2580 		{
2581 		  if (*p == '\\' && strchr("\"tnebr\\", p[1]))
2582 		    {
2583 		      if (p[1] == 't')
2584 			p[1] = '\t';
2585 		      else if (p[1] == 'n')
2586 			p[1] = '\n';
2587 		      else if (p[1] == 'b')
2588 			p[1] = '\b';
2589 		      else if (p[1] == 'r')
2590 			p[1] = '\r';
2591 		      else if (p[1] == 'e') /* escape */
2592 			p[1] = '\033';
2593 		      memmove(p, p+1, strlen(p+1)+1);
2594 		    }
2595 		  *p = hide_meta(*p);
2596 		}
2597 	      if (*p == '"')
2598 		{
2599 		  memmove(p, p+1, strlen(p+1)+1);
2600 		  lastquote = p - buff;
2601 		}
2602 	      else
2603 		{
2604 		  errmess = _("missing \"");
2605 		  goto oops;
2606 		}
2607 	    }
2608 
2609 	  if (white && *p == '#')
2610 	    {
2611 	      *p = 0;
2612 	      break;
2613 	    }
2614 	  white = isspace((int)unhide_meta(*p));
2615 	}
2616 
2617       /* fgets gets end of line char too. */
2618       while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1])))
2619 	buff[strlen(buff)-1] = 0;
2620 
2621       if (*buff == 0)
2622 	continue;
2623 
2624       if (hard_opt != 0)
2625 	arg = buff;
2626       else if ((p=strchr(buff, '=')))
2627 	{
2628 	  /* allow spaces around "=" */
2629 	  arg = p+1;
2630 	  for (; p >= buff && (isspace((int)*p) || *p == '='); p--)
2631 	    *p = 0;
2632 	}
2633       else
2634 	arg = NULL;
2635 
2636       if (hard_opt != 0)
2637 	option = hard_opt;
2638       else
2639 	{
2640 	  /* skip leading space */
2641 	  for (start = buff; *start && isspace((int)*start); start++);
2642 
2643 	  for (option = 0, i = 0; opts[i].name; i++)
2644 	    if (strcmp(opts[i].name, start) == 0)
2645 	      {
2646 		option = opts[i].val;
2647 		break;
2648 	      }
2649 
2650 	  if (!option)
2651 	    errmess = _("bad option");
2652 	  else if (opts[i].has_arg == 0 && arg)
2653 	    errmess = _("extraneous parameter");
2654 	  else if (opts[i].has_arg == 1 && !arg)
2655 	    errmess = _("missing parameter");
2656 	}
2657 
2658       if (!errmess)
2659 	{
2660 	  if (arg)
2661 	    for (; isspace((int)*arg); arg++);
2662 
2663 	  errmess = one_opt(option, arg, _("error"), nest + 1);
2664 	}
2665 
2666       if (errmess)
2667 	{
2668 	oops:
2669 	  sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
2670 	  if (hard_opt != 0)
2671 	    my_syslog(LOG_ERR, buff, file);
2672 	  else
2673 	    die(buff, file, EC_BADCONF);
2674 	}
2675     }
2676 
2677   mem_recover = 1;
2678   fclose(f);
2679 }
2680 
2681 #ifdef HAVE_DHCP
reread_dhcp(void)2682 void reread_dhcp(void)
2683 {
2684   if (daemon->dhcp_hosts_file)
2685     {
2686       struct dhcp_config *configs, *cp, **up;
2687 
2688       /* remove existing... */
2689       for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
2690 	{
2691 	  cp = configs->next;
2692 
2693 	  if (configs->flags & CONFIG_BANK)
2694 	    {
2695 	      struct hwaddr_config *mac, *tmp;
2696 
2697 	      for (mac = configs->hwaddr; mac; mac = tmp)
2698 		{
2699 		  tmp = mac->next;
2700 		  free(mac);
2701 		}
2702 	      if (configs->flags & CONFIG_CLID)
2703 		free(configs->clid);
2704 	      if (configs->flags & CONFIG_NETID)
2705 		free(configs->netid.net);
2706 	      if (configs->flags & CONFIG_NAME)
2707 		free(configs->hostname);
2708 
2709 
2710 	      *up = configs->next;
2711 	      free(configs);
2712 	    }
2713 	  else
2714 	    up = &configs->next;
2715 	}
2716 
2717       one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
2718       my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
2719     }
2720 
2721   if (daemon->dhcp_opts_file)
2722     {
2723       struct dhcp_opt *opts, *cp, **up;
2724       struct dhcp_netid *id, *next;
2725 
2726       for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
2727 	{
2728 	  cp = opts->next;
2729 
2730 	  if (opts->flags & DHOPT_BANK)
2731 	    {
2732 	      if ((opts->flags & DHOPT_VENDOR))
2733 		free(opts->u.vendor_class);
2734 	      free(opts->val);
2735 	      for (id = opts->netid; id; id = next)
2736 		{
2737 		  next = id->next;
2738 		  free(id->net);
2739 		  free(id);
2740 		}
2741 	      *up = opts->next;
2742 	      free(opts);
2743 	    }
2744 	  else
2745 	    up = &opts->next;
2746 	}
2747 
2748       one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
2749       my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
2750     }
2751 }
2752 #endif
2753 
read_opts(int argc,char ** argv,char * compile_opts)2754 void read_opts(int argc, char **argv, char *compile_opts)
2755 {
2756   char *buff = opt_malloc(MAXDNAME);
2757   int option, nest = 0, testmode = 0;
2758   char *errmess, *arg, *conffile = CONFFILE;
2759 
2760   opterr = 0;
2761 
2762   daemon = opt_malloc(sizeof(struct daemon));
2763   memset(daemon, 0, sizeof(struct daemon));
2764   daemon->namebuff = buff;
2765 
2766   /* Set defaults - everything else is zero or NULL */
2767   daemon->cachesize = CACHESIZ;
2768   daemon->ftabsize = FTABSIZ;
2769   daemon->port = NAMESERVER_PORT;
2770   daemon->dhcp_client_port = DHCP_CLIENT_PORT;
2771   daemon->dhcp_server_port = DHCP_SERVER_PORT;
2772   daemon->default_resolv.is_default = 1;
2773   daemon->default_resolv.name = RESOLVFILE;
2774   daemon->resolv_files = &daemon->default_resolv;
2775   daemon->username = CHUSER;
2776   daemon->runfile =  RUNFILE;
2777   daemon->dhcp_max = MAXLEASES;
2778   daemon->edns_pktsz = EDNS_PKTSZ;
2779   daemon->log_fac = -1;
2780   add_txt("version.bind", "dnsmasq-" VERSION );
2781   add_txt("authors.bind", "Simon Kelley");
2782   add_txt("copyright.bind", COPYRIGHT);
2783 
2784   while (1)
2785     {
2786 #ifdef HAVE_GETOPT_LONG
2787       option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
2788 #else
2789       option = getopt(argc, argv, OPTSTRING);
2790 #endif
2791 
2792       if (option == -1)
2793 	break;
2794 
2795       /* Copy optarg so that argv doesn't get changed */
2796       if (optarg)
2797 	{
2798 	  strncpy(buff, optarg, MAXDNAME);
2799 	  buff[MAXDNAME-1] = 0;
2800 	  arg = buff;
2801 	}
2802       else
2803 	arg = NULL;
2804 
2805       /* command-line only stuff */
2806       if (option == LOPT_TEST)
2807 	testmode = 1;
2808       else if (option == 'w')
2809 	{
2810 	  if (argc != 3 ||  strcmp(argv[2], "dhcp") != 0)
2811 	    do_usage();
2812 #ifdef HAVE_DHCP
2813 	  else
2814 	    display_opts();
2815 #endif
2816 	  exit(0);
2817 	}
2818       else if (option == 'v')
2819 	{
2820 	  printf(_("Dnsmasq version %s  %s\n"), VERSION, COPYRIGHT);
2821 	  printf(_("Compile time options %s\n\n"), compile_opts);
2822 	  printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
2823 	  printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
2824 	  printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
2825           exit(0);
2826         }
2827       else if (option == 'C')
2828 	{
2829 	  conffile = opt_string_alloc(arg);
2830 	  nest++;
2831 	}
2832       else
2833 	{
2834 #ifdef HAVE_GETOPT_LONG
2835 	  errmess = one_opt(option, arg, _("try --help"), 0);
2836 #else
2837 	  errmess = one_opt(option, arg, _("try -w"), 0);
2838 #endif
2839 	  if (errmess)
2840 	    die(_("bad command line options: %s"), errmess, EC_BADCONF);
2841 	}
2842     }
2843 
2844   if (conffile)
2845     one_file(conffile, nest, 0);
2846 
2847   /* port might not be known when the address is parsed - fill in here */
2848   if (daemon->servers)
2849     {
2850       struct server *tmp;
2851       for (tmp = daemon->servers; tmp; tmp = tmp->next)
2852 	if (!(tmp->flags & SERV_HAS_SOURCE))
2853 	  {
2854 	    if (tmp->source_addr.sa.sa_family == AF_INET)
2855 	      tmp->source_addr.in.sin_port = htons(daemon->query_port);
2856 #ifdef HAVE_IPV6
2857 	    else if (tmp->source_addr.sa.sa_family == AF_INET6)
2858 	      tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
2859 #endif
2860 	  }
2861     }
2862 
2863   if (daemon->if_addrs)
2864     {
2865       struct iname *tmp;
2866       for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
2867 	if (tmp->addr.sa.sa_family == AF_INET)
2868 	  tmp->addr.in.sin_port = htons(daemon->port);
2869 #ifdef HAVE_IPV6
2870 	else if (tmp->addr.sa.sa_family == AF_INET6)
2871 	  tmp->addr.in6.sin6_port = htons(daemon->port);
2872 #endif /* IPv6 */
2873     }
2874 
2875   /* only one of these need be specified: the other defaults to the host-name */
2876   if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
2877     {
2878       struct mx_srv_record *mx;
2879 
2880       if (gethostname(buff, MAXDNAME) == -1)
2881 	die(_("cannot get host-name: %s"), NULL, EC_MISC);
2882 
2883       for (mx = daemon->mxnames; mx; mx = mx->next)
2884 	if (!mx->issrv && hostname_isequal(mx->name, buff))
2885 	  break;
2886 
2887       if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
2888 	{
2889 	  mx = opt_malloc(sizeof(struct mx_srv_record));
2890 	  mx->next = daemon->mxnames;
2891 	  mx->issrv = 0;
2892 	  mx->target = NULL;
2893 	  mx->name = opt_string_alloc(buff);
2894 	  daemon->mxnames = mx;
2895 	}
2896 
2897       if (!daemon->mxtarget)
2898 	daemon->mxtarget = opt_string_alloc(buff);
2899 
2900       for (mx = daemon->mxnames; mx; mx = mx->next)
2901 	if (!mx->issrv && !mx->target)
2902 	  mx->target = daemon->mxtarget;
2903     }
2904 
2905   if (!(daemon->options & OPT_NO_RESOLV) &&
2906       daemon->resolv_files &&
2907       daemon->resolv_files->next &&
2908       (daemon->options & OPT_NO_POLL))
2909     die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
2910 
2911   if (daemon->options & OPT_RESOLV_DOMAIN)
2912     {
2913       char *line;
2914       FILE *f;
2915 
2916       if ((daemon->options & OPT_NO_RESOLV) ||
2917 	  !daemon->resolv_files ||
2918 	  (daemon->resolv_files)->next)
2919 	die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
2920 
2921       if (!(f = fopen((daemon->resolv_files)->name, "r")))
2922 	die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
2923 
2924       while ((line = fgets(buff, MAXDNAME, f)))
2925 	{
2926 	  char *token = strtok(line, " \t\n\r");
2927 
2928 	  if (!token || strcmp(token, "search") != 0)
2929 	    continue;
2930 
2931 	  if ((token = strtok(NULL, " \t\n\r")) &&
2932 	      (daemon->domain_suffix = canonicalise_opt(token)))
2933 	    break;
2934 	}
2935 
2936       fclose(f);
2937 
2938       if (!daemon->domain_suffix)
2939 	die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
2940     }
2941 
2942   if (daemon->domain_suffix)
2943     {
2944        /* add domain for any srv record without one. */
2945       struct mx_srv_record *srv;
2946 
2947       for (srv = daemon->mxnames; srv; srv = srv->next)
2948 	if (srv->issrv &&
2949 	    strchr(srv->name, '.') &&
2950 	    strchr(srv->name, '.') == strrchr(srv->name, '.'))
2951 	  {
2952 	    strcpy(buff, srv->name);
2953 	    strcat(buff, ".");
2954 	    strcat(buff, daemon->domain_suffix);
2955 	    free(srv->name);
2956 	    srv->name = opt_string_alloc(buff);
2957 	  }
2958     }
2959   else if (daemon->options & OPT_DHCP_FQDN)
2960     die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
2961 
2962   if (testmode)
2963     {
2964       fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
2965       exit(0);
2966     }
2967 }
2968