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