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