]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/option.c
Tidy rebase
[people/ms/dnsmasq.git] / src / option.c
CommitLineData
61744359 1/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
9e4abcb5
SK
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
824af85b
SK
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
9e4abcb5
SK
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.
824af85b 12
73a08a24
SK
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/>.
9e4abcb5
SK
15*/
16
849a8357
SK
17/* define this to get facilitynames */
18#define SYSLOG_NAMES
9e4abcb5 19#include "dnsmasq.h"
824af85b
SK
20#include <setjmp.h>
21
7622fc06
SK
22static volatile int mem_recover = 0;
23static jmp_buf mem_jmp;
395eb719 24static int one_file(char *file, int hard_opt);
7622fc06 25
824af85b
SK
26/* Solaris headers don't have facility names. */
27#ifdef HAVE_SOLARIS_NETWORK
28static 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 },
824af85b 41 { "audit", LOG_AUDIT },
824af85b
SK
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
9e4abcb5 54
849a8357 55#ifndef HAVE_GETOPT_LONG
9e4abcb5
SK
56struct myoption {
57 const char *name;
58 int has_arg;
59 int *flag;
60 int val;
61};
849a8357 62#endif
9e4abcb5 63
9009d746 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:"
9e4abcb5 65
1697269c 66/* options which don't have a one-char version */
832af0ba
SK
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
6b01084f
SK
75#define LOPT_FORCE 264
76#define LOPT_NOBLOCK 265
f2621c7f
SK
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
5aabfc78
SK
83#define LOPT_BANK 272
84#define LOPT_DHCP_HOST 273
85#define LOPT_APREF 274
824af85b
SK
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
9e038946
SK
95#define LOPT_ALTPORT 284
96#define LOPT_SCRIPTUSR 285
1a6bca81
SK
97#define LOPT_LOCAL 286
98#define LOPT_NAPTR 287
99#define LOPT_MINPORT 288
9009d746
SK
100#define LOPT_DHCP_FQDN 289
101#define LOPT_CNAME 290
7622fc06
SK
102#define LOPT_PXE_PROMT 291
103#define LOPT_PXE_SERV 292
104#define LOPT_TEST 293
8ef5ada2
SK
105#define LOPT_TAG_IF 294
106#define LOPT_PROXY 295
107#define LOPT_GEN_NAMES 296
108#define LOPT_MAXTTL 297
109#define LOPT_NO_REBIND 298
110#define LOPT_LOC_REBND 299
28866e95 111#define LOPT_ADD_MAC 300
237724c0 112#define LOPT_SEC_PROXY 301
7de060b0
SK
113#define LOPT_INCR_ADDR 302
114#define LOPT_CONNTRACK 303
c72daea8
SK
115#define LOPT_FQDN 304
116#define LOPT_LUASCRIPT 305
c5ad4e79 117#define LOPT_RA 306
8b372704 118#define LOPT_DUID 307
e759d426 119#define LOPT_HOST_REC 308
61ce600b 120#define LOPT_TFTP_LC 309
9f7f3b12 121#define LOPT_RR 310
54dd393f 122#define LOPT_CLVERBIND 311
1d860415 123#define LOPT_MAXCTTL 312
4f7b304f
SK
124#define LOPT_AUTHZONE 313
125#define LOPT_AUTHSERV 314
e1ff419c 126#define LOPT_AUTHTTL 315
4f7b304f 127#define LOPT_AUTHSOA 316
e1ff419c 128#define LOPT_AUTHSFS 317
49678767 129#define LOPT_AUTHPEER 318
13d86c73 130#define LOPT_IPSET 319
2bb73af7 131#define LOPT_SYNTH 320
7dbe193b 132#define LOPT_SEC_VALID 321
c630924d 133#ifdef OPTION6_PREFIX_CLASS
7dbe193b 134#define LOPT_PREF_CLSS 322
c630924d 135#endif
8d030462 136#define LOPT_FAST_RA 322
1697269c 137
7dbe193b 138
849a8357
SK
139#ifdef HAVE_GETOPT_LONG
140static const struct option opts[] =
141#else
142static const struct myoption opts[] =
143#endif
144 {
7622fc06
SK
145 { "version", 0, 0, 'v' },
146 { "no-hosts", 0, 0, 'h' },
147 { "no-poll", 0, 0, 'n' },
148 { "help", 0, 0, 'w' },
149 { "no-daemon", 0, 0, 'd' },
150 { "log-queries", 0, 0, 'q' },
151 { "user", 2, 0, 'u' },
152 { "group", 2, 0, 'g' },
153 { "resolv-file", 2, 0, 'r' },
154 { "mx-host", 1, 0, 'm' },
155 { "mx-target", 1, 0, 't' },
156 { "cache-size", 2, 0, 'c' },
157 { "port", 1, 0, 'p' },
158 { "dhcp-leasefile", 2, 0, 'l' },
159 { "dhcp-lease", 1, 0, 'l' },
160 { "dhcp-host", 1, 0, 'G' },
161 { "dhcp-range", 1, 0, 'F' },
162 { "dhcp-option", 1, 0, 'O' },
163 { "dhcp-boot", 1, 0, 'M' },
164 { "domain", 1, 0, 's' },
165 { "domain-suffix", 1, 0, 's' },
166 { "interface", 1, 0, 'i' },
167 { "listen-address", 1, 0, 'a' },
168 { "bogus-priv", 0, 0, 'b' },
169 { "bogus-nxdomain", 1, 0, 'B' },
170 { "selfmx", 0, 0, 'e' },
171 { "filterwin2k", 0, 0, 'f' },
172 { "pid-file", 2, 0, 'x' },
173 { "strict-order", 0, 0, 'o' },
174 { "server", 1, 0, 'S' },
175 { "local", 1, 0, LOPT_LOCAL },
176 { "address", 1, 0, 'A' },
177 { "conf-file", 2, 0, 'C' },
178 { "no-resolv", 0, 0, 'R' },
179 { "expand-hosts", 0, 0, 'E' },
180 { "localmx", 0, 0, 'L' },
181 { "local-ttl", 1, 0, 'T' },
182 { "no-negcache", 0, 0, 'N' },
183 { "addn-hosts", 1, 0, 'H' },
184 { "query-port", 1, 0, 'Q' },
185 { "except-interface", 1, 0, 'I' },
186 { "no-dhcp-interface", 1, 0, '2' },
187 { "domain-needed", 0, 0, 'D' },
188 { "dhcp-lease-max", 1, 0, 'X' },
189 { "bind-interfaces", 0, 0, 'z' },
190 { "read-ethers", 0, 0, 'Z' },
191 { "alias", 1, 0, 'V' },
192 { "dhcp-vendorclass", 1, 0, 'U' },
193 { "dhcp-userclass", 1, 0, 'j' },
194 { "dhcp-ignore", 1, 0, 'J' },
195 { "edns-packet-max", 1, 0, 'P' },
196 { "keep-in-foreground", 0, 0, 'k' },
197 { "dhcp-authoritative", 0, 0, 'K' },
198 { "srv-host", 1, 0, 'W' },
199 { "localise-queries", 0, 0, 'y' },
200 { "txt-record", 1, 0, 'Y' },
9f7f3b12 201 { "dns-rr", 1, 0, LOPT_RR },
ad094275 202 { "enable-dbus", 2, 0, '1' },
7622fc06
SK
203 { "bootp-dynamic", 2, 0, '3' },
204 { "dhcp-mac", 1, 0, '4' },
205 { "no-ping", 0, 0, '5' },
206 { "dhcp-script", 1, 0, '6' },
207 { "conf-dir", 1, 0, '7' },
208 { "log-facility", 1, 0 ,'8' },
209 { "leasefile-ro", 0, 0, '9' },
210 { "dns-forward-max", 1, 0, '0' },
211 { "clear-on-reload", 0, 0, LOPT_RELOAD },
212 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
2937f8a0 213 { "enable-tftp", 2, 0, LOPT_TFTP },
7622fc06
SK
214 { "tftp-secure", 0, 0, LOPT_SECURE },
215 { "tftp-unique-root", 0, 0, LOPT_APREF },
216 { "tftp-root", 1, 0, LOPT_PREFIX },
217 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
61ce600b 218 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
7622fc06
SK
219 { "ptr-record", 1, 0, LOPT_PTR },
220 { "naptr-record", 1, 0, LOPT_NAPTR },
221 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
222 { "dhcp-option-force", 1, 0, LOPT_FORCE },
223 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
224 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
225 { "log-async", 2, 0, LOPT_MAX_LOGS },
226 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
227 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
228 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
229 { "interface-name", 1, 0, LOPT_INTNAME },
230 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
231 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
232 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
233 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
234 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
8ef5ada2 235 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
7622fc06
SK
236 { "all-servers", 0, 0, LOPT_NOLAST },
237 { "dhcp-match", 1, 0, LOPT_MATCH },
8ef5ada2 238 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
7622fc06 239 { "neg-ttl", 1, 0, LOPT_NEGTTL },
8ef5ada2 240 { "max-ttl", 1, 0, LOPT_MAXTTL },
1d860415 241 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
7622fc06
SK
242 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
243 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
244 { "min-port", 1, 0, LOPT_MINPORT },
245 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
246 { "cname", 1, 0, LOPT_CNAME },
247 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
248 { "pxe-service", 1, 0, LOPT_PXE_SERV },
249 { "test", 0, 0, LOPT_TEST },
8ef5ada2
SK
250 { "tag-if", 1, 0, LOPT_TAG_IF },
251 { "dhcp-proxy", 2, 0, LOPT_PROXY },
252 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
253 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
28866e95 254 { "add-mac", 0, 0, LOPT_ADD_MAC },
237724c0 255 { "proxy-dnssec", 0, 0, LOPT_SEC_PROXY },
7de060b0
SK
256 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
257 { "conntrack", 0, 0, LOPT_CONNTRACK },
c72daea8
SK
258 { "dhcp-client-update", 0, 0, LOPT_FQDN },
259 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
c5ad4e79 260 { "enable-ra", 0, 0, LOPT_RA },
8b372704 261 { "dhcp-duid", 1, 0, LOPT_DUID },
e759d426 262 { "host-record", 1, 0, LOPT_HOST_REC },
54dd393f 263 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
4f7b304f
SK
264 { "auth-zone", 1, 0, LOPT_AUTHZONE },
265 { "auth-server", 1, 0, LOPT_AUTHSERV },
266 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
267 { "auth-soa", 1, 0, LOPT_AUTHSOA },
e1ff419c 268 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
49678767 269 { "auth-peer", 1, 0, LOPT_AUTHPEER },
13d86c73 270 { "ipset", 1, 0, LOPT_IPSET },
2bb73af7 271 { "synth-domain", 1, 0, LOPT_SYNTH },
7dbe193b 272 { "dnssec", 0, 0, LOPT_SEC_VALID },
c630924d
SK
273#ifdef OPTION6_PREFIX_CLASS
274 { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
275#endif
8d030462 276 { "force-fast-ra", 0, 0, LOPT_FAST_RA },
849a8357
SK
277 { NULL, 0, 0, 0 }
278 };
9e4abcb5 279
28866e95
SK
280
281#define ARG_DUP OPT_LAST
282#define ARG_ONE OPT_LAST + 1
283#define ARG_USED_CL OPT_LAST + 2
284#define ARG_USED_FILE OPT_LAST + 3
9e4abcb5 285
1a6bca81
SK
286static struct {
287 int opt;
288 unsigned int rept;
289 char * const flagdesc;
b8187c80
SK
290 char * const desc;
291 char * const arg;
292} usage[] = {
8ecfaa4a
SK
293 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
294 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
1a6bca81 295 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
8ecfaa4a
SK
296 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
297 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
298 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
1a6bca81
SK
299 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
300 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
301 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
302 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
303 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
8ecfaa4a
SK
304 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
305 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
1a6bca81 306 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
8ecfaa4a
SK
307 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
308 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
8ef5ada2 309 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
1a6bca81 310 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
8ecfaa4a
SK
311 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
312 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
313 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
8ef5ada2
SK
314 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
315 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
316 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
317 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
318 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
319 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
1a6bca81
SK
320 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
321 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
8ecfaa4a 322 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
1a6bca81 323 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
8ecfaa4a 324 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
1a6bca81
SK
325 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
326 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
327 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
328 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
329 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
330 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
8ecfaa4a
SK
331 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
332 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
1a6bca81 333 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
8ecfaa4a 334 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
1a6bca81 335 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
8ecfaa4a
SK
336 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
337 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
338 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
9009d746 339 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
8ecfaa4a
SK
340 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
341 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
342 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
343 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
344 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
8ef5ada2 345 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
1a6bca81 346 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
8ecfaa4a
SK
347 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
348 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
1a6bca81 349 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
8ecfaa4a
SK
350 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
351 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
1a6bca81 352 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
8ecfaa4a
SK
353 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
354 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
355 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
1a6bca81
SK
356 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
357 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
ad094275 358 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
8ecfaa4a 359 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
8ef5ada2
SK
360 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
361 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
8ecfaa4a 362 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
1a6bca81 363 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
8ecfaa4a
SK
364 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
365 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
366 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
367 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
1a6bca81
SK
368 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
369 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
8ecfaa4a 370 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
1a6bca81 371 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
8ef5ada2 372 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
1a6bca81 373 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
2937f8a0 374 { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
8b3ae2fd 375 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
1a6bca81
SK
376 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
377 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
8ecfaa4a 378 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
1a6bca81 379 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
61ce600b 380 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
1a6bca81
SK
381 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
382 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
8ecfaa4a 383 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
1a6bca81 384 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
8ef5ada2 385 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
8ecfaa4a 386 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
1a6bca81 387 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
8ef5ada2 388 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
1a6bca81 389 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
1a6bca81
SK
390 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
391 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
9009d746 392 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
8ecfaa4a
SK
393 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
394 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
9009d746 395 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
7622fc06
SK
396 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
397 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
398 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
7de060b0 399 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
237724c0 400 { LOPT_SEC_PROXY, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
7de060b0
SK
401 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
402 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
c72daea8 403 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
c5ad4e79 404 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
8d030462 405 { LOPT_FAST_RA, OPT_FAST_RA, NULL, gettext_noop("Always send frequent router-advertisements"), NULL },
8b372704 406 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
e759d426 407 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
9f7f3b12 408 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
4f7b304f 409 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
86e3b9a0 410 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
333b2ceb 411 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
4f7b304f
SK
412 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
413 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
49678767
SK
414 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
415 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
13d86c73 416 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
48fd1c4d 417 { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
7dbe193b
GB
418#ifdef HAVE_DNSSEC
419 { LOPT_SEC_VALID, OPT_DNSSEC_VALIDATE, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
420#endif
c630924d
SK
421#ifdef OPTION6_PREFIX_CLASS
422 { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
423#endif
1a6bca81 424 { 0, 0, NULL, NULL, NULL }
b8187c80 425};
9e4abcb5 426
3d8df260 427/* We hide metacharaters in quoted strings by mapping them into the ASCII control
f2621c7f 428 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
3d8df260
SK
429 following sequence so that they map to themselves: it is therefore possible to call
430 unhide_metas repeatedly on string without breaking things.
824af85b 431 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
f2621c7f
SK
432 couple of other places.
433 Note that space is included here so that
434 --dhcp-option=3, string
435 has five characters, whilst
436 --dhcp-option=3," string"
437 has six.
438*/
3d8df260 439
f2621c7f 440static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
3d8df260
SK
441
442static char hide_meta(char c)
443{
444 unsigned int i;
445
446 for (i = 0; i < (sizeof(meta) - 1); i++)
447 if (c == meta[i])
448 return (char)i;
449
450 return c;
451}
452
453static char unhide_meta(char cr)
454{
455 unsigned int c = cr;
456
457 if (c < (sizeof(meta) - 1))
458 cr = meta[c];
459
460 return cr;
461}
462
463static void unhide_metas(char *cp)
464{
465 if (cp)
466 for(; *cp; cp++)
467 *cp = unhide_meta(*cp);
468}
469
824af85b
SK
470static void *opt_malloc(size_t size)
471{
472 void *ret;
473
474 if (mem_recover)
475 {
476 ret = whine_malloc(size);
477 if (!ret)
478 longjmp(mem_jmp, 1);
479 }
480 else
481 ret = safe_malloc(size);
482
483 return ret;
484}
485
486static char *opt_string_alloc(char *cp)
3d8df260
SK
487{
488 char *ret = NULL;
489
490 if (cp && strlen(cp) != 0)
491 {
824af85b 492 ret = opt_malloc(strlen(cp)+1);
3d8df260
SK
493 strcpy(ret, cp);
494
495 /* restore hidden metachars */
496 unhide_metas(ret);
497 }
498
499 return ret;
500}
501
f2621c7f
SK
502
503/* find next comma, split string with zero and eliminate spaces.
504 return start of string following comma */
73a08a24
SK
505
506static char *split_chr(char *s, char c)
3d8df260 507{
f2621c7f 508 char *comma, *p;
3d8df260 509
73a08a24 510 if (!s || !(comma = strchr(s, c)))
f2621c7f
SK
511 return NULL;
512
513 p = comma;
514 *comma = ' ';
515
8ef5ada2 516 for (; *comma == ' '; comma++);
f2621c7f 517
8ef5ada2 518 for (; (p >= s) && *p == ' '; p--)
f2621c7f
SK
519 *p = 0;
520
521 return comma;
3d8df260
SK
522}
523
73a08a24
SK
524static char *split(char *s)
525{
526 return split_chr(s, ',');
527}
528
1f15b81d 529static char *canonicalise_opt(char *s)
3d8df260 530{
1f15b81d
SK
531 char *ret;
532 int nomem;
533
3d8df260
SK
534 if (!s)
535 return 0;
536
537 unhide_metas(s);
1f15b81d
SK
538 if (!(ret = canonicalise(s, &nomem)) && nomem)
539 {
540 if (mem_recover)
541 longjmp(mem_jmp, 1);
542 else
543 die(_("could not get memory"), NULL, EC_NOMEM);
544 }
545
546 return ret;
3d8df260
SK
547}
548
549static int atoi_check(char *a, int *res)
550{
551 char *p;
552
553 if (!a)
554 return 0;
555
556 unhide_metas(a);
557
558 for (p = a; *p; p++)
559 if (*p < '0' || *p > '9')
560 return 0;
561
562 *res = atoi(a);
563 return 1;
564}
565
1ad24ae1
SK
566static int atoi_check16(char *a, int *res)
567{
568 if (!(atoi_check(a, res)) ||
569 *res < 0 ||
570 *res > 0xffff)
571 return 0;
572
573 return 1;
574}
575
5aabfc78 576static void add_txt(char *name, char *txt)
0a852541
SK
577{
578 size_t len = strlen(txt);
824af85b 579 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
0a852541 580
824af85b 581 r->name = opt_string_alloc(name);
0a852541
SK
582 r->next = daemon->txt;
583 daemon->txt = r;
584 r->class = C_CHAOS;
824af85b 585 r->txt = opt_malloc(len+1);
0a852541
SK
586 r->len = len+1;
587 *(r->txt) = len;
588 memcpy((r->txt)+1, txt, len);
589}
9e4abcb5 590
849a8357 591static void do_usage(void)
9e4abcb5 592{
849a8357 593 char buff[100];
832af0ba
SK
594 int i, j;
595
596 struct {
597 char handle;
598 int val;
599 } tab[] = {
600 { '$', CACHESIZ },
601 { '*', EDNS_PKTSZ },
602 { '&', MAXLEASES },
603 { '!', FTABSIZ },
604 { '#', TFTP_MAX_CONNECTIONS },
605 { '\0', 0 }
606 };
0a852541 607
849a8357
SK
608 printf(_("Usage: dnsmasq [options]\n\n"));
609#ifndef HAVE_GETOPT_LONG
610 printf(_("Use short options only on the command line.\n"));
611#endif
1a6bca81 612 printf(_("Valid options are:\n"));
3be34541 613
1a6bca81 614 for (i = 0; usage[i].opt != 0; i++)
9e4abcb5 615 {
1a6bca81
SK
616 char *desc = usage[i].flagdesc;
617 char *eq = "=";
618
619 if (!desc || *desc == '[')
620 eq = "";
621
622 if (!desc)
623 desc = "";
624
625 for ( j = 0; opts[j].name; j++)
626 if (opts[j].val == usage[i].opt)
627 break;
628 if (usage[i].opt < 256)
629 sprintf(buff, "-%c, ", usage[i].opt);
630 else
631 sprintf(buff, " ");
632
633 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
8ef5ada2 634 printf("%-40.40s", buff);
1a6bca81 635
849a8357 636 if (usage[i].arg)
0a852541 637 {
832af0ba
SK
638 strcpy(buff, usage[i].arg);
639 for (j = 0; tab[j].handle; j++)
640 if (tab[j].handle == *(usage[i].arg))
641 sprintf(buff, "%d", tab[j].val);
0a852541 642 }
849a8357
SK
643 printf(_(usage[i].desc), buff);
644 printf("\n");
645 }
646}
0a852541 647
c740e4f3
SK
648#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
649
faafb3f7
SK
650char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
651{
652 int source_port = 0, serv_port = NAMESERVER_PORT;
653 char *portno, *source;
654#ifdef HAVE_IPV6
655 int scope_index = 0;
656 char *scope_id;
657#endif
658
659 if ((source = split_chr(arg, '@')) && /* is there a source. */
660 (portno = split_chr(source, '#')) &&
661 !atoi_check16(portno, &source_port))
662 return _("bad port");
663
664 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
665 !atoi_check16(portno, &serv_port))
666 return _("bad port");
667
668#ifdef HAVE_IPV6
669 scope_id = split_chr(arg, '%');
670#endif
671
ddd9a6b4 672 if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
faafb3f7
SK
673 {
674 addr->in.sin_port = htons(serv_port);
675 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
676#ifdef HAVE_SOCKADDR_SA_LEN
677 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
678#endif
679 source_addr->in.sin_addr.s_addr = INADDR_ANY;
680 source_addr->in.sin_port = htons(daemon->query_port);
681
682 if (source)
683 {
684 if (flags)
685 *flags |= SERV_HAS_SOURCE;
686 source_addr->in.sin_port = htons(source_port);
ddd9a6b4 687 if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
faafb3f7
SK
688 {
689#if defined(SO_BINDTODEVICE)
690 source_addr->in.sin_addr.s_addr = INADDR_ANY;
691 strncpy(interface, source, IF_NAMESIZE - 1);
692#else
693 return _("interface binding not supported");
694#endif
695 }
696 }
697 }
698#ifdef HAVE_IPV6
699 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
700 {
701 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
702 return _("bad interface name");
703
704 addr->in6.sin6_port = htons(serv_port);
705 addr->in6.sin6_scope_id = scope_index;
706 source_addr->in6.sin6_addr = in6addr_any;
707 source_addr->in6.sin6_port = htons(daemon->query_port);
708 source_addr->in6.sin6_scope_id = 0;
709 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
710 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
711#ifdef HAVE_SOCKADDR_SA_LEN
712 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
713#endif
714 if (source)
715 {
716 if (flags)
717 *flags |= SERV_HAS_SOURCE;
718 source_addr->in6.sin6_port = htons(source_port);
719 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
720 {
721#if defined(SO_BINDTODEVICE)
722 source_addr->in6.sin6_addr = in6addr_any;
723 strncpy(interface, source, IF_NAMESIZE - 1);
724#else
725 return _("interface binding not supported");
726#endif
727 }
728 }
729 }
730#endif
731 else
732 return _("bad address");
733
734 return NULL;
735}
736
b5a8dd1d
SK
737#ifdef HAVE_DHCP
738
739static int is_tag_prefix(char *arg)
740{
741 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
742 return 1;
743
744 return 0;
745}
746
747static char *set_prefix(char *arg)
748{
749 if (strstr(arg, "set:") == arg)
750 return arg+4;
751
752 return arg;
753}
754
832af0ba 755/* This is too insanely large to keep in-line in the switch */
c4a7f90e 756static int parse_dhcp_opt(char *errstr, char *arg, int flags)
832af0ba 757{
824af85b 758 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
832af0ba 759 char lenchar = 0, *cp;
40ef23b5 760 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
c4a7f90e 761 char *comma = NULL;
f2621c7f 762 struct dhcp_netid *np = NULL;
4cb1b320
SK
763 u16 opt_len = 0;
764 int is6 = 0;
bd08ae67 765 int option_ok = 0;
832af0ba
SK
766
767 new->len = 0;
824af85b 768 new->flags = flags;
832af0ba
SK
769 new->netid = NULL;
770 new->val = NULL;
f2621c7f 771 new->opt = 0;
832af0ba 772
f2621c7f 773 while (arg)
832af0ba 774 {
f2621c7f
SK
775 comma = split(arg);
776
777 for (cp = arg; *cp; cp++)
778 if (*cp < '0' || *cp > '9')
779 break;
832af0ba 780
f2621c7f
SK
781 if (!*cp)
782 {
783 new->opt = atoi(arg);
784 opt_len = 0;
bd08ae67 785 option_ok = 1;
832af0ba 786 break;
f2621c7f
SK
787 }
788
789 if (strstr(arg, "option:") == arg)
790 {
bd08ae67
SK
791 if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
792 {
793 opt_len = lookup_dhcp_len(AF_INET, new->opt);
794 /* option:<optname> must follow tag and vendor string. */
795 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
796 option_ok = 1;
797 }
f2621c7f
SK
798 break;
799 }
4cb1b320
SK
800#ifdef HAVE_DHCP6
801 else if (strstr(arg, "option6:") == arg)
802 {
803 for (cp = arg+8; *cp; cp++)
804 if (*cp < '0' || *cp > '9')
805 break;
806
807 if (!*cp)
808 {
809 new->opt = atoi(arg+8);
810 opt_len = 0;
bd08ae67 811 option_ok = 1;
4cb1b320
SK
812 }
813 else
40ef23b5 814 {
bd08ae67
SK
815 if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
816 {
817 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
818 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
819 option_ok = 1;
820 }
40ef23b5 821 }
4cb1b320
SK
822 /* option6:<opt>|<optname> must follow tag and vendor string. */
823 is6 = 1;
824 break;
825 }
826#endif
f2621c7f
SK
827 else if (strstr(arg, "vendor:") == arg)
828 {
73a08a24
SK
829 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
830 new->flags |= DHOPT_VENDOR;
831 }
832 else if (strstr(arg, "encap:") == arg)
833 {
834 new->u.encap = atoi(arg+6);
f2621c7f
SK
835 new->flags |= DHOPT_ENCAPSULATE;
836 }
316e2730
SK
837 else if (strstr(arg, "vi-encap:") == arg)
838 {
839 new->u.encap = atoi(arg+9);
840 new->flags |= DHOPT_RFC3925;
841 if (flags == DHOPT_MATCH)
842 {
bd08ae67 843 option_ok = 1;
316e2730
SK
844 break;
845 }
846 }
f2621c7f
SK
847 else
848 {
824af85b 849 new->netid = opt_malloc(sizeof (struct dhcp_netid));
8ef5ada2
SK
850 /* allow optional "net:" or "tag:" for consistency */
851 if (is_tag_prefix(arg))
824af85b 852 new->netid->net = opt_string_alloc(arg+4);
f2621c7f 853 else
8ef5ada2 854 new->netid->net = opt_string_alloc(set_prefix(arg));
f2621c7f
SK
855 new->netid->next = np;
856 np = new->netid;
857 }
858
859 arg = comma;
832af0ba 860 }
4cb1b320
SK
861
862#ifdef HAVE_DHCP6
863 if (is6)
864 {
865 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
c4a7f90e 866 ret_err(_("unsupported encapsulation for IPv6 option"));
4cb1b320
SK
867
868 if (opt_len == 0 &&
869 !(new->flags & DHOPT_RFC3925))
bd08ae67 870 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
4cb1b320
SK
871 }
872 else
873#endif
874 if (opt_len == 0 &&
875 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
bd08ae67 876 opt_len = lookup_dhcp_len(AF_INET, new->opt);
40ef23b5 877
316e2730 878 /* option may be missing with rfc3925 match */
bd08ae67 879 if (!option_ok)
c4a7f90e
SK
880 ret_err(_("bad dhcp-option"));
881
882 if (comma)
832af0ba
SK
883 {
884 /* characterise the value */
f2621c7f 885 char c;
28866e95 886 int found_dig = 0;
4cb1b320 887 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
832af0ba 888 addrs = digs = 1;
f2621c7f
SK
889 dots = 0;
890 for (cp = comma; (c = *cp); cp++)
891 if (c == ',')
832af0ba
SK
892 {
893 addrs++;
894 is_dec = is_hex = 0;
895 }
f2621c7f 896 else if (c == ':')
832af0ba
SK
897 {
898 digs++;
899 is_dec = is_addr = 0;
900 }
f2621c7f 901 else if (c == '/')
832af0ba 902 {
4cb1b320 903 is_addr6 = is_dec = is_hex = 0;
832af0ba
SK
904 if (cp == comma) /* leading / means a pathname */
905 is_addr = 0;
906 }
f2621c7f
SK
907 else if (c == '.')
908 {
23245c0c 909 is_addr6 = is_dec = is_hex = 0;
f2621c7f
SK
910 dots++;
911 }
912 else if (c == '-')
4cb1b320 913 is_hex = is_addr = is_addr6 = 0;
f2621c7f 914 else if (c == ' ')
832af0ba 915 is_dec = is_hex = 0;
f2621c7f 916 else if (!(c >='0' && c <= '9'))
832af0ba
SK
917 {
918 is_addr = 0;
919 if (cp[1] == 0 && is_dec &&
f2621c7f 920 (c == 'b' || c == 's' || c == 'i'))
832af0ba 921 {
f2621c7f 922 lenchar = c;
832af0ba
SK
923 *cp = 0;
924 }
925 else
926 is_dec = 0;
f2621c7f 927 if (!((c >='A' && c <= 'F') ||
73a08a24
SK
928 (c >='a' && c <= 'f') ||
929 (c == '*' && (flags & DHOPT_MATCH))))
4cb1b320
SK
930 {
931 is_hex = 0;
932 if (c != '[' && c != ']')
933 is_addr6 = 0;
934 }
832af0ba 935 }
28866e95
SK
936 else
937 found_dig = 1;
f2621c7f 938
28866e95
SK
939 if (!found_dig)
940 is_dec = is_addr = 0;
4cb1b320 941
f2621c7f 942 /* We know that some options take addresses */
7622fc06 943 if (opt_len & OT_ADDR_LIST)
f2621c7f
SK
944 {
945 is_string = is_dec = is_hex = 0;
4cb1b320
SK
946
947 if (!is6 && (!is_addr || dots == 0))
c4a7f90e 948 ret_err(_("bad IP address"));
4cb1b320
SK
949
950 if (is6 && !is_addr6)
c4a7f90e 951 ret_err(_("bad IPv6 address"));
f2621c7f 952 }
28866e95 953 /* or names */
4cb1b320
SK
954 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
955 is_addr6 = is_addr = is_dec = is_hex = 0;
23245c0c
SK
956
957 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
958 {
959 int val, fac = 1;
960
961 switch (comma[strlen(comma) - 1])
962 {
42243214
SK
963 case 'w':
964 case 'W':
965 fac *= 7;
966 /* fall through */
23245c0c
SK
967 case 'd':
968 case 'D':
969 fac *= 24;
970 /* fall though */
971 case 'h':
972 case 'H':
973 fac *= 60;
974 /* fall through */
975 case 'm':
976 case 'M':
977 fac *= 60;
978 /* fall through */
979 case 's':
980 case 'S':
981 comma[strlen(comma) - 1] = 0;
982 }
983
984 new->len = 4;
985 new->val = opt_malloc(4);
986 val = atoi(comma);
987 *((int *)new->val) = htonl(val * fac);
988 }
989 else if (is_hex && digs > 1)
832af0ba
SK
990 {
991 new->len = digs;
824af85b 992 new->val = opt_malloc(new->len);
73a08a24
SK
993 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
994 new->flags |= DHOPT_HEX;
832af0ba
SK
995 }
996 else if (is_dec)
997 {
998 int i, val = atoi(comma);
999 /* assume numeric arg is 1 byte except for
1000 options where it is known otherwise.
1001 For vendor class option, we have to hack. */
f2621c7f
SK
1002 if (opt_len != 0)
1003 new->len = opt_len;
1004 else if (val & 0xffff0000)
1005 new->len = 4;
1006 else if (val & 0xff00)
1007 new->len = 2;
1008 else
1009 new->len = 1;
1010
832af0ba
SK
1011 if (lenchar == 'b')
1012 new->len = 1;
1013 else if (lenchar == 's')
1014 new->len = 2;
1015 else if (lenchar == 'i')
1016 new->len = 4;
f2621c7f 1017
824af85b 1018 new->val = opt_malloc(new->len);
832af0ba
SK
1019 for (i=0; i<new->len; i++)
1020 new->val[i] = val>>((new->len - i - 1)*8);
1021 }
4cb1b320 1022 else if (is_addr && !is6)
832af0ba
SK
1023 {
1024 struct in_addr in;
1025 unsigned char *op;
1026 char *slash;
1027 /* max length of address/subnet descriptor is five bytes,
1028 add one for the option 120 enc byte too */
824af85b 1029 new->val = op = opt_malloc((5 * addrs) + 1);
6b01084f
SK
1030 new->flags |= DHOPT_ADDR;
1031
572b41eb
SK
1032 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1033 new->opt == OPTION_SIP_SERVER)
832af0ba 1034 {
6b01084f
SK
1035 *(op++) = 1; /* RFC 3361 "enc byte" */
1036 new->flags &= ~DHOPT_ADDR;
832af0ba
SK
1037 }
1038 while (addrs--)
1039 {
1040 cp = comma;
f2621c7f 1041 comma = split(cp);
73a08a24 1042 slash = split_chr(cp, '/');
ddd9a6b4 1043 inet_pton(AF_INET, cp, &in);
832af0ba
SK
1044 if (!slash)
1045 {
1046 memcpy(op, &in, INADDRSZ);
1047 op += INADDRSZ;
1048 }
1049 else
1050 {
1051 unsigned char *p = (unsigned char *)&in;
1052 int netsize = atoi(slash);
1053 *op++ = netsize;
1054 if (netsize > 0)
1055 *op++ = *p++;
1056 if (netsize > 8)
1057 *op++ = *p++;
1058 if (netsize > 16)
1059 *op++ = *p++;
1060 if (netsize > 24)
1061 *op++ = *p++;
1062 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1063 }
1064 }
1065 new->len = op - new->val;
1066 }
4cb1b320
SK
1067 else if (is_addr6 && is6)
1068 {
1069 unsigned char *op;
1070 new->val = op = opt_malloc(16 * addrs);
1071 new->flags |= DHOPT_ADDR6;
1072 while (addrs--)
1073 {
1074 cp = comma;
1075 comma = split(cp);
1076
1077 /* check for [1234::7] */
1078 if (*cp == '[')
1079 cp++;
1080 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1081 cp[strlen(cp)-1] = 0;
1082
1083 if (inet_pton(AF_INET6, cp, op))
1084 {
1085 op += IN6ADDRSZ;
1086 continue;
1087 }
1088
c4a7f90e 1089 ret_err(_("bad IPv6 address"));
4cb1b320
SK
1090 }
1091 new->len = op - new->val;
1092 }
f2621c7f 1093 else if (is_string)
832af0ba 1094 {
4cb1b320 1095 /* text arg */
572b41eb 1096 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
4cb1b320 1097 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
832af0ba
SK
1098 {
1099 /* dns search, RFC 3397, or SIP, RFC 3361 */
1100 unsigned char *q, *r, *tail;
824af85b 1101 unsigned char *p, *m = NULL, *newp;
832af0ba 1102 size_t newlen, len = 0;
572b41eb 1103 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
832af0ba
SK
1104
1105 arg = comma;
f2621c7f 1106 comma = split(arg);
832af0ba
SK
1107
1108 while (arg && *arg)
1109 {
c52e1897
SK
1110 char *in, *dom = NULL;
1111 size_t domlen = 1;
1112 /* Allow "." as an empty domain */
1113 if (strcmp (arg, ".") != 0)
832af0ba 1114 {
c52e1897 1115 if (!(dom = canonicalise_opt(arg)))
c4a7f90e
SK
1116 ret_err(_("bad domain in dhcp-option"));
1117
c52e1897 1118 domlen = strlen(dom) + 2;
832af0ba 1119 }
c52e1897
SK
1120
1121 newp = opt_malloc(len + domlen + header_size);
824af85b 1122 if (m)
c52e1897
SK
1123 {
1124 memcpy(newp, m, header_size + len);
1125 free(m);
1126 }
824af85b 1127 m = newp;
832af0ba
SK
1128 p = m + header_size;
1129 q = p + len;
1130
1131 /* add string on the end in RFC1035 format */
c52e1897 1132 for (in = dom; in && *in;)
832af0ba
SK
1133 {
1134 unsigned char *cp = q++;
1135 int j;
c52e1897
SK
1136 for (j = 0; *in && (*in != '.'); in++, j++)
1137 *q++ = *in;
832af0ba 1138 *cp = j;
c52e1897
SK
1139 if (*in)
1140 in++;
832af0ba
SK
1141 }
1142 *q++ = 0;
1f15b81d 1143 free(dom);
c52e1897 1144
832af0ba
SK
1145 /* Now tail-compress using earlier names. */
1146 newlen = q - p;
1147 for (tail = p + len; *tail; tail += (*tail) + 1)
1148 for (r = p; r - p < (int)len; r += (*r) + 1)
1149 if (strcmp((char *)r, (char *)tail) == 0)
1150 {
1151 PUTSHORT((r - p) | 0xc000, tail);
1152 newlen = tail - p;
1153 goto end;
1154 }
1155 end:
1156 len = newlen;
1157
1158 arg = comma;
f2621c7f 1159 comma = split(arg);
832af0ba
SK
1160 }
1161
1162 /* RFC 3361, enc byte is zero for names */
572b41eb 1163 if (new->opt == OPTION_SIP_SERVER)
832af0ba
SK
1164 m[0] = 0;
1165 new->len = (int) len + header_size;
1166 new->val = m;
1167 }
4cb1b320
SK
1168#ifdef HAVE_DHCP6
1169 else if (comma && (opt_len & OT_CSTRING))
1170 {
1171 /* length fields are two bytes so need 16 bits for each string */
40ef23b5 1172 int i, commas = 1;
4cb1b320
SK
1173 unsigned char *p, *newp;
1174
40ef23b5 1175 for (i = 0; comma[i]; i++)
4cb1b320
SK
1176 if (comma[i] == ',')
1177 commas++;
1178
1179 newp = opt_malloc(strlen(comma)+(2*commas));
1180 p = newp;
1181 arg = comma;
1182 comma = split(arg);
1183
1184 while (arg && *arg)
1185 {
1186 u16 len = strlen(arg);
18f0fb05 1187 unhide_metas(arg);
4cb1b320
SK
1188 PUTSHORT(len, p);
1189 memcpy(p, arg, len);
1190 p += len;
1191
1192 arg = comma;
1193 comma = split(arg);
1194 }
1195
1196 new->val = newp;
1197 new->len = p - newp;
1198 }
1199 else if (comma && (opt_len & OT_RFC1035_NAME))
1200 {
18f0fb05
SK
1201 unsigned char *p = NULL, *newp, *end;
1202 int len = 0;
4cb1b320
SK
1203 arg = comma;
1204 comma = split(arg);
1205
1206 while (arg && *arg)
1207 {
18f0fb05
SK
1208 char *dom = canonicalise_opt(arg);
1209 if (!dom)
c4a7f90e
SK
1210 ret_err(_("bad domain in dhcp-option"));
1211
18f0fb05
SK
1212 newp = opt_malloc(len + strlen(dom) + 2);
1213
1214 if (p)
1215 {
1216 memcpy(newp, p, len);
1217 free(p);
1218 }
4cb1b320 1219
18f0fb05
SK
1220 p = newp;
1221 end = do_rfc1035_name(p + len, dom);
1222 *end++ = 0;
1223 len = end - p;
1224 free(dom);
1225
4cb1b320
SK
1226 arg = comma;
1227 comma = split(arg);
1228 }
1229
18f0fb05
SK
1230 new->val = p;
1231 new->len = len;
4cb1b320
SK
1232 }
1233#endif
832af0ba
SK
1234 else
1235 {
1236 new->len = strlen(comma);
1237 /* keep terminating zero on string */
824af85b 1238 new->val = (unsigned char *)opt_string_alloc(comma);
832af0ba
SK
1239 new->flags |= DHOPT_STRING;
1240 }
1241 }
1242 }
1243
4cb1b320
SK
1244 if (!is6 &&
1245 ((new->len > 255) ||
316e2730 1246 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
4cb1b320 1247 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
c4a7f90e 1248 ret_err(_("dhcp-option too long"));
832af0ba 1249
c4a7f90e 1250 if (flags == DHOPT_MATCH)
824af85b 1251 {
c4a7f90e
SK
1252 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1253 !new->netid ||
1254 new->netid->next)
1255 ret_err(_("illegal dhcp-match"));
1256
1257 if (is6)
4cb1b320 1258 {
c4a7f90e
SK
1259 new->next = daemon->dhcp_match6;
1260 daemon->dhcp_match6 = new;
4cb1b320
SK
1261 }
1262 else
73a08a24 1263 {
c4a7f90e
SK
1264 new->next = daemon->dhcp_match;
1265 daemon->dhcp_match = new;
73a08a24 1266 }
824af85b 1267 }
c4a7f90e
SK
1268 else if (is6)
1269 {
1270 new->next = daemon->dhcp_opts6;
1271 daemon->dhcp_opts6 = new;
1272 }
1273 else
1274 {
1275 new->next = daemon->dhcp_opts;
1276 daemon->dhcp_opts = new;
1277 }
1278
1279 return 1;
832af0ba
SK
1280}
1281
7622fc06 1282#endif
832af0ba 1283
28866e95
SK
1284void set_option_bool(unsigned int opt)
1285{
1286 if (opt < 32)
1287 daemon->options |= 1u << opt;
1288 else
1289 daemon->options2 |= 1u << (opt - 32);
1290}
1291
2b5bae9a
SK
1292void reset_option_bool(unsigned int opt)
1293{
1294 if (opt < 32)
1295 daemon->options &= ~(1u << opt);
1296 else
1297 daemon->options2 &= ~(1u << (opt - 32));
1298}
1299
c4a7f90e 1300static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
849a8357
SK
1301{
1302 int i;
c4a7f90e 1303 char *comma;
b8187c80 1304
832af0ba 1305 if (option == '?')
c4a7f90e 1306 ret_err(gen_err);
832af0ba 1307
1a6bca81
SK
1308 for (i=0; usage[i].opt != 0; i++)
1309 if (usage[i].opt == option)
849a8357 1310 {
1a6bca81
SK
1311 int rept = usage[i].rept;
1312
28866e95 1313 if (command_line)
1a6bca81
SK
1314 {
1315 /* command line */
1316 if (rept == ARG_USED_CL)
c4a7f90e 1317 ret_err(_("illegal repeated flag"));
1a6bca81
SK
1318 if (rept == ARG_ONE)
1319 usage[i].rept = ARG_USED_CL;
1320 }
1321 else
1322 {
1323 /* allow file to override command line */
1324 if (rept == ARG_USED_FILE)
c4a7f90e 1325 ret_err(_("illegal repeated keyword"));
1a6bca81
SK
1326 if (rept == ARG_USED_CL || rept == ARG_ONE)
1327 usage[i].rept = ARG_USED_FILE;
1328 }
1329
1330 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1331 {
28866e95 1332 set_option_bool(rept);
c4a7f90e 1333 return 1;
1a6bca81
SK
1334 }
1335
1336 break;
849a8357 1337 }
1a6bca81 1338
849a8357
SK
1339 switch (option)
1340 {
f2621c7f 1341 case 'C': /* --conf-file */
849a8357 1342 {
824af85b 1343 char *file = opt_string_alloc(arg);
849a8357 1344 if (file)
9009d746 1345 {
28866e95 1346 one_file(file, 0);
9009d746
SK
1347 free(file);
1348 }
849a8357
SK
1349 break;
1350 }
1351
f2621c7f 1352 case '7': /* --conf-dir */
849a8357
SK
1353 {
1354 DIR *dir_stream;
1355 struct dirent *ent;
1356 char *directory, *path;
1f15b81d
SK
1357 struct list {
1358 char *suffix;
1359 struct list *next;
1360 } *ignore_suffix = NULL, *li;
849a8357 1361
1f15b81d 1362 comma = split(arg);
824af85b 1363 if (!(directory = opt_string_alloc(arg)))
849a8357
SK
1364 break;
1365
1f15b81d
SK
1366 for (arg = comma; arg; arg = comma)
1367 {
1368 comma = split(arg);
1369 li = opt_malloc(sizeof(struct list));
1370 li->next = ignore_suffix;
1371 ignore_suffix = li;
1372 /* Have to copy: buffer is overwritten */
1373 li->suffix = opt_string_alloc(arg);
1374 };
1375
849a8357 1376 if (!(dir_stream = opendir(directory)))
5aabfc78 1377 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1f15b81d 1378
849a8357 1379 while ((ent = readdir(dir_stream)))
9e4abcb5 1380 {
7622fc06 1381 size_t len = strlen(ent->d_name);
849a8357 1382 struct stat buf;
1f15b81d
SK
1383
1384 /* ignore emacs backups and dotfiles */
7622fc06
SK
1385 if (len == 0 ||
1386 ent->d_name[len - 1] == '~' ||
849a8357
SK
1387 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1388 ent->d_name[0] == '.')
1389 continue;
7622fc06 1390
1f15b81d
SK
1391 for (li = ignore_suffix; li; li = li->next)
1392 {
1393 /* check for proscribed suffices */
1394 size_t ls = strlen(li->suffix);
1395 if (len > ls &&
1396 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1397 break;
1398 }
1399 if (li)
1400 continue;
1401
824af85b 1402 path = opt_malloc(strlen(directory) + len + 2);
849a8357
SK
1403 strcpy(path, directory);
1404 strcat(path, "/");
1405 strcat(path, ent->d_name);
7622fc06 1406
39595cfe 1407 /* files must be readable */
849a8357 1408 if (stat(path, &buf) == -1)
5aabfc78 1409 die(_("cannot access %s: %s"), path, EC_FILE);
39595cfe 1410
849a8357 1411 /* only reg files allowed. */
39595cfe
SK
1412 if (S_ISREG(buf.st_mode))
1413 one_file(path, 0);
849a8357 1414
849a8357 1415 free(path);
9e4abcb5 1416 }
849a8357
SK
1417
1418 closedir(dir_stream);
9009d746 1419 free(directory);
1f15b81d
SK
1420 for(; ignore_suffix; ignore_suffix = li)
1421 {
1422 li = ignore_suffix->next;
1423 free(ignore_suffix->suffix);
1424 free(ignore_suffix);
1425 }
1426
849a8357
SK
1427 break;
1428 }
1429
ad094275
SK
1430 case '1': /* --enable-dbus */
1431 set_option_bool(OPT_DBUS);
1432 if (arg)
1433 daemon->dbus_name = opt_string_alloc(arg);
1434 else
1435 daemon->dbus_name = DNSMASQ_SERVICE;
1436 break;
1437
f2621c7f
SK
1438 case '8': /* --log-facility */
1439 /* may be a filename */
8ef5ada2 1440 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
824af85b 1441 daemon->log_file = opt_string_alloc(arg);
849a8357 1442 else
f2621c7f 1443 {
572b41eb 1444#ifdef __ANDROID__
c4a7f90e 1445 ret_err(_("setting log facility is not possible under Android"));
572b41eb 1446#else
f2621c7f
SK
1447 for (i = 0; facilitynames[i].c_name; i++)
1448 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1449 break;
1450
1451 if (facilitynames[i].c_name)
1452 daemon->log_fac = facilitynames[i].c_val;
1453 else
c4a7f90e 1454 ret_err(_("bad log facility"));
572b41eb 1455#endif
849a8357
SK
1456 }
1457 break;
1458
f2621c7f 1459 case 'x': /* --pid-file */
824af85b 1460 daemon->runfile = opt_string_alloc(arg);
849a8357 1461 break;
5aabfc78 1462
f2621c7f 1463 case 'r': /* --resolv-file */
849a8357 1464 {
824af85b 1465 char *name = opt_string_alloc(arg);
849a8357
SK
1466 struct resolvc *new, *list = daemon->resolv_files;
1467
1468 if (list && list->is_default)
1469 {
1470 /* replace default resolv file - possibly with nothing */
1471 if (name)
9e4abcb5 1472 {
849a8357
SK
1473 list->is_default = 0;
1474 list->name = name;
9e4abcb5 1475 }
849a8357
SK
1476 else
1477 list = NULL;
1478 }
1479 else if (name)
1480 {
824af85b 1481 new = opt_malloc(sizeof(struct resolvc));
849a8357
SK
1482 new->next = list;
1483 new->name = name;
1484 new->is_default = 0;
1485 new->mtime = 0;
1486 new->logged = 0;
1487 list = new;
1488 }
1489 daemon->resolv_files = list;
1490 break;
1491 }
1492
f2621c7f 1493 case 'm': /* --mx-host */
849a8357
SK
1494 {
1495 int pref = 1;
1496 struct mx_srv_record *new;
1f15b81d
SK
1497 char *name, *target = NULL;
1498
f2621c7f 1499 if ((comma = split(arg)))
849a8357
SK
1500 {
1501 char *prefstr;
1f15b81d 1502 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
c4a7f90e 1503 ret_err(_("bad MX preference"));
849a8357
SK
1504 }
1505
1f15b81d
SK
1506 if (!(name = canonicalise_opt(arg)) ||
1507 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 1508 ret_err(_("bad MX name"));
1f15b81d 1509
824af85b 1510 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
1511 new->next = daemon->mxnames;
1512 daemon->mxnames = new;
1513 new->issrv = 0;
1f15b81d
SK
1514 new->name = name;
1515 new->target = target; /* may be NULL */
849a8357
SK
1516 new->weight = pref;
1517 break;
1518 }
1519
f2621c7f 1520 case 't': /* --mx-target */
1f15b81d 1521 if (!(daemon->mxtarget = canonicalise_opt(arg)))
c4a7f90e 1522 ret_err(_("bad MX target"));
849a8357 1523 break;
7622fc06
SK
1524
1525#ifdef HAVE_DHCP
f2621c7f 1526 case 'l': /* --dhcp-leasefile */
824af85b 1527 daemon->lease_file = opt_string_alloc(arg);
849a8357
SK
1528 break;
1529
c72daea8
SK
1530 /* Sorry about the gross pre-processor abuse */
1531 case '6': /* --dhcp-script */
1532 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1f15b81d 1533# if defined(NO_FORK)
c4a7f90e 1534 ret_err(_("cannot run scripts under uClinux"));
1f15b81d 1535# elif !defined(HAVE_SCRIPT)
c4a7f90e 1536 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
7622fc06 1537# else
c72daea8
SK
1538 if (option == LOPT_LUASCRIPT)
1539# if !defined(HAVE_LUASCRIPT)
c4a7f90e 1540 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
c72daea8
SK
1541# else
1542 daemon->luascript = opt_string_alloc(arg);
1543# endif
1544 else
1545 daemon->lease_change_command = opt_string_alloc(arg);
7622fc06 1546# endif
849a8357 1547 break;
c72daea8 1548#endif /* HAVE_DHCP */
7622fc06 1549
28866e95
SK
1550 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1551 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
f2621c7f 1552 case 'H': /* --addn-hosts */
849a8357 1553 {
824af85b 1554 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
849a8357 1555 static int hosts_index = 1;
824af85b 1556 new->fname = opt_string_alloc(arg);
849a8357 1557 new->index = hosts_index++;
7622fc06 1558 new->flags = 0;
28866e95
SK
1559 if (option == 'H')
1560 {
1561 new->next = daemon->addn_hosts;
1562 daemon->addn_hosts = new;
1563 }
1564 else if (option == LOPT_DHCP_HOST)
1565 {
1566 new->next = daemon->dhcp_hosts_file;
1567 daemon->dhcp_hosts_file = new;
1568 }
e1ff419c 1569 else if (option == LOPT_DHCP_OPTS)
28866e95
SK
1570 {
1571 new->next = daemon->dhcp_opts_file;
1572 daemon->dhcp_opts_file = new;
1573 }
849a8357
SK
1574 break;
1575 }
1576
4f7b304f 1577 case LOPT_AUTHSERV: /* --auth-server */
86e3b9a0 1578 if (!(comma = split(arg)))
4f7b304f
SK
1579 ret_err(gen_err);
1580
4f7b304f 1581 daemon->authserver = opt_string_alloc(arg);
429798fd
SK
1582 arg = comma;
1583 do {
1584 struct iname *new = opt_malloc(sizeof(struct iname));
1585 comma = split(arg);
1586 new->name = NULL;
1587 unhide_metas(arg);
ddd9a6b4 1588 if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
429798fd
SK
1589 new->addr.sa.sa_family = AF_INET;
1590#ifdef HAVE_IPV6
1591 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1592 new->addr.sa.sa_family = AF_INET6;
1593#endif
1594 else
1595 new->name = opt_string_alloc(arg);
1596
1597 new->next = daemon->authinterface;
1598 daemon->authinterface = new;
1599
1600 arg = comma;
1601 } while (arg);
1602
4f7b304f 1603 break;
e1ff419c
SK
1604
1605 case LOPT_AUTHSFS: /* --auth-sec-servers */
1606 {
1607 struct name_list *new;
1608
1609 do {
1610 comma = split(arg);
429798fd 1611 new = opt_malloc(sizeof(struct name_list));
e1ff419c
SK
1612 new->name = opt_string_alloc(arg);
1613 new->next = daemon->secondary_forward_server;
1614 daemon->secondary_forward_server = new;
1615 arg = comma;
1616 } while (arg);
1617 break;
1618 }
1619
4f7b304f
SK
1620 case LOPT_AUTHZONE: /* --auth-zone */
1621 {
1622 struct auth_zone *new;
1623
1624 comma = split(arg);
1e14cc0f 1625
429798fd 1626 new = opt_malloc(sizeof(struct auth_zone));
4f7b304f
SK
1627 new->domain = opt_string_alloc(arg);
1628 new->subnet = NULL;
1629 new->next = daemon->auth_zones;
1630 daemon->auth_zones = new;
1631
1632 while ((arg = comma))
1633 {
1634 int prefixlen = 0;
1635 char *prefix;
429798fd 1636 struct subnet *subnet = opt_malloc(sizeof(struct subnet));
4f7b304f
SK
1637
1638 subnet->next = new->subnet;
1639 new->subnet = subnet;
1640
1641 comma = split(arg);
1642 prefix = split_chr(arg, '/');
1643
1644 if (prefix && !atoi_check(prefix, &prefixlen))
1645 ret_err(gen_err);
1646
1647 if (inet_pton(AF_INET, arg, &subnet->addr4))
1648 {
1649 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
1650 subnet->is6 = 0;
1651 }
1652#ifdef HAVE_IPV6
1653 else if (inet_pton(AF_INET6, arg, &subnet->addr6))
1654 {
1655 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
1656 subnet->is6 = 1;
1657 }
1658#endif
1659 else
1660 ret_err(gen_err);
1661 }
1662 break;
1663 }
1664
1665 case LOPT_AUTHSOA: /* --auth-soa */
1666 comma = split(arg);
5c72bb9e 1667 daemon->soa_sn = (u32)atoi(arg);
4f7b304f
SK
1668 if (comma)
1669 {
86e3b9a0 1670 char *cp;
4f7b304f
SK
1671 arg = comma;
1672 comma = split(arg);
1673 daemon->hostmaster = opt_string_alloc(arg);
86e3b9a0
SK
1674 for (cp = daemon->hostmaster; *cp; cp++)
1675 if (*cp == '@')
1676 *cp = '.';
1677
4f7b304f
SK
1678 if (comma)
1679 {
1680 arg = comma;
1681 comma = split(arg);
5c72bb9e 1682 daemon->soa_refresh = (u32)atoi(arg);
4f7b304f
SK
1683 if (comma)
1684 {
1685 arg = comma;
1686 comma = split(arg);
5c72bb9e 1687 daemon->soa_retry = (u32)atoi(arg);
4f7b304f
SK
1688 if (comma)
1689 {
1690 arg = comma;
1691 comma = split(arg);
5c72bb9e 1692 daemon->soa_expiry = (u32)atoi(arg);
4f7b304f
SK
1693 }
1694 }
1695 }
1696 }
1697
1698 break;
1699
2bb73af7
SK
1700 case 's': /* --domain */
1701 case LOPT_SYNTH: /* --synth-domain */
849a8357 1702 if (strcmp (arg, "#") == 0)
28866e95 1703 set_option_bool(OPT_RESOLV_DOMAIN);
849a8357 1704 else
9009d746 1705 {
1f15b81d 1706 char *d;
9009d746 1707 comma = split(arg);
1f15b81d 1708 if (!(d = canonicalise_opt(arg)))
c4a7f90e 1709 ret_err(gen_err);
9009d746
SK
1710 else
1711 {
9009d746
SK
1712 if (comma)
1713 {
429798fd 1714 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
28866e95 1715 char *netpart;
2bb73af7 1716
48fd1c4d
SK
1717 new->prefix = NULL;
1718
9009d746 1719 unhide_metas(comma);
28866e95 1720 if ((netpart = split_chr(comma, '/')))
9009d746 1721 {
d74942a0
SK
1722 int msize;
1723
28866e95 1724 arg = split(netpart);
d74942a0 1725 if (!atoi_check(netpart, &msize))
c4a7f90e 1726 ret_err(gen_err);
d74942a0 1727 else if (inet_pton(AF_INET, comma, &new->start))
9009d746 1728 {
d74942a0
SK
1729 int mask = (1 << (32 - msize)) - 1;
1730 new->is6 = 0;
9009d746
SK
1731 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1732 new->end.s_addr = new->start.s_addr | htonl(mask);
28866e95
SK
1733 if (arg)
1734 {
48fd1c4d 1735 if (option != 's')
b5a7ff42
SK
1736 {
1737 if (!(new->prefix = canonicalise_opt(arg)) ||
1738 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1739 ret_err(_("bad prefix"));
1740 }
48fd1c4d
SK
1741 else if (strcmp(arg, "local") != 0 ||
1742 (msize != 8 && msize != 16 && msize != 24))
c4a7f90e 1743 ret_err(gen_err);
28866e95
SK
1744 else
1745 {
48fd1c4d
SK
1746 /* generate the equivalent of
1747 local=/<domain>/
1748 local=/xxx.yyy.zzz.in-addr.arpa/ */
28866e95
SK
1749 struct server *serv = opt_malloc(sizeof(struct server));
1750 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1751 char *p;
48fd1c4d 1752
28866e95
SK
1753 memset(serv, 0, sizeof(struct server));
1754 serv->domain = d;
1755 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1756 serv->next = daemon->servers;
1757 daemon->servers = serv;
48fd1c4d 1758
28866e95
SK
1759 serv = opt_malloc(sizeof(struct server));
1760 memset(serv, 0, sizeof(struct server));
1761 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1762
1763 if (msize == 24)
1764 p += sprintf(p, "%d.", a & 0xff);
1765 a = a >> 8;
1766 if (msize != 8)
1767 p += sprintf(p, "%d.", a & 0xff);
1768 a = a >> 8;
1769 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
48fd1c4d 1770
28866e95
SK
1771 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1772 serv->next = daemon->servers;
1773 daemon->servers = serv;
1774 }
1775 }
9009d746 1776 }
d74942a0
SK
1777#ifdef HAVE_IPV6
1778 else if (inet_pton(AF_INET6, comma, &new->start6))
1779 {
1780 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1781 u64 addrpart = addr6part(&new->start6);
1782 new->is6 = 1;
48fd1c4d 1783
d74942a0
SK
1784 /* prefix==64 overflows the mask calculation above */
1785 if (msize == 64)
1786 mask = (u64)-1LL;
48fd1c4d 1787
d74942a0
SK
1788 new->end6 = new->start6;
1789 setaddr6part(&new->start6, addrpart & ~mask);
1790 setaddr6part(&new->end6, addrpart | mask);
1791
1792 if (msize < 64)
c4a7f90e 1793 ret_err(gen_err);
d74942a0
SK
1794 else if (arg)
1795 {
48fd1c4d 1796 if (option != 's')
b5a7ff42
SK
1797 {
1798 if (!(new->prefix = canonicalise_opt(arg)) ||
1799 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
1800 ret_err(_("bad prefix"));
1801 }
48fd1c4d 1802 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
c4a7f90e 1803 ret_err(gen_err);
d74942a0
SK
1804 else
1805 {
48fd1c4d
SK
1806 /* generate the equivalent of
1807 local=/<domain>/
1808 local=/xxx.yyy.zzz.ip6.arpa/ */
d74942a0 1809 struct server *serv = opt_malloc(sizeof(struct server));
d74942a0 1810 char *p;
ceae00dd 1811
d74942a0
SK
1812 memset(serv, 0, sizeof(struct server));
1813 serv->domain = d;
1814 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1815 serv->next = daemon->servers;
1816 daemon->servers = serv;
1817
1818 serv = opt_malloc(sizeof(struct server));
1819 memset(serv, 0, sizeof(struct server));
1820 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1821
1822 for (i = msize-1; i >= 0; i -= 4)
1823 {
1824 int dig = ((unsigned char *)&new->start6)[i>>3];
1825 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1826 }
1827 p += sprintf(p, "ip6.arpa");
1828
1829 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1830 serv->next = daemon->servers;
1831 daemon->servers = serv;
1832 }
1833 }
1834 }
1835#endif
1836 else
c4a7f90e 1837 ret_err(gen_err);
9009d746 1838 }
2bb73af7 1839 else
9009d746 1840 {
d74942a0
SK
1841 arg = split(comma);
1842 if (inet_pton(AF_INET, comma, &new->start))
1843 {
1844 new->is6 = 0;
1845 if (!arg)
1846 new->end.s_addr = new->start.s_addr;
1847 else if (!inet_pton(AF_INET, arg, &new->end))
c4a7f90e 1848 ret_err(gen_err);
d74942a0
SK
1849 }
1850#ifdef HAVE_IPV6
1851 else if (inet_pton(AF_INET6, comma, &new->start6))
1852 {
1853 new->is6 = 1;
1854 if (!arg)
1855 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1856 else if (!inet_pton(AF_INET6, arg, &new->end6))
c4a7f90e 1857 ret_err(gen_err);
d74942a0
SK
1858 }
1859#endif
1860 else
c4a7f90e 1861 ret_err(gen_err);
d74942a0 1862 }
2307eac6
SK
1863
1864 new->domain = d;
2bb73af7
SK
1865 if (option == 's')
1866 {
1867 new->next = daemon->cond_domain;
1868 daemon->cond_domain = new;
1869 }
1870 else
1871 {
1872 new->next = daemon->synth_domains;
1873 daemon->synth_domains = new;
1874 }
9009d746 1875 }
2bb73af7 1876 else if (option == 's')
9009d746 1877 daemon->domain_suffix = d;
2bb73af7
SK
1878 else
1879 ret_err(gen_err);
9009d746
SK
1880 }
1881 }
849a8357
SK
1882 break;
1883
f2621c7f 1884 case 'u': /* --user */
824af85b 1885 daemon->username = opt_string_alloc(arg);
849a8357
SK
1886 break;
1887
f2621c7f 1888 case 'g': /* --group */
824af85b 1889 daemon->groupname = opt_string_alloc(arg);
1a6bca81 1890 daemon->group_set = 1;
849a8357 1891 break;
9e038946 1892
7622fc06 1893#ifdef HAVE_DHCP
9e038946
SK
1894 case LOPT_SCRIPTUSR: /* --scriptuser */
1895 daemon->scriptuser = opt_string_alloc(arg);
1896 break;
7622fc06 1897#endif
849a8357 1898
f2621c7f 1899 case 'i': /* --interface */
849a8357 1900 do {
824af85b 1901 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1902 comma = split(arg);
849a8357
SK
1903 new->next = daemon->if_names;
1904 daemon->if_names = new;
1905 /* new->name may be NULL if someone does
1906 "interface=" to disable all interfaces except loop. */
824af85b 1907 new->name = opt_string_alloc(arg);
4ce4f377 1908 new->used = 0;
849a8357
SK
1909 arg = comma;
1910 } while (arg);
1911 break;
1912
2937f8a0
SK
1913 case LOPT_TFTP: /* --enable-tftp */
1914 set_option_bool(OPT_TFTP);
1915 if (!arg)
1916 break;
1917 /* fall through */
1918
f2621c7f
SK
1919 case 'I': /* --except-interface */
1920 case '2': /* --no-dhcp-interface */
849a8357 1921 do {
824af85b 1922 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1923 comma = split(arg);
824af85b 1924 new->name = opt_string_alloc(arg);
849a8357
SK
1925 if (option == 'I')
1926 {
1927 new->next = daemon->if_except;
1928 daemon->if_except = new;
1929 }
2937f8a0
SK
1930 else if (option == LOPT_TFTP)
1931 {
1932 new->next = daemon->tftp_interfaces;
1933 daemon->tftp_interfaces = new;
1934 }
849a8357
SK
1935 else
1936 {
1937 new->next = daemon->dhcp_except;
1938 daemon->dhcp_except = new;
1939 }
1940 arg = comma;
1941 } while (arg);
1942 break;
1943
f2621c7f 1944 case 'B': /* --bogus-nxdomain */
849a8357
SK
1945 {
1946 struct in_addr addr;
1947 unhide_metas(arg);
ddd9a6b4 1948 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
849a8357 1949 {
824af85b 1950 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
849a8357
SK
1951 baddr->next = daemon->bogus_addr;
1952 daemon->bogus_addr = baddr;
1953 baddr->addr = addr;
1954 }
1955 else
c4a7f90e 1956 ret_err(gen_err); /* error */
849a8357
SK
1957 break;
1958 }
1959
f2621c7f 1960 case 'a': /* --listen-address */
49678767 1961 case LOPT_AUTHPEER: /* --auth-peer */
849a8357 1962 do {
824af85b 1963 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1964 comma = split(arg);
849a8357 1965 unhide_metas(arg);
ddd9a6b4 1966 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
849a8357
SK
1967 {
1968 new->addr.sa.sa_family = AF_INET;
49678767 1969 new->addr.in.sin_port = 0;
849a8357
SK
1970#ifdef HAVE_SOCKADDR_SA_LEN
1971 new->addr.in.sin_len = sizeof(new->addr.in);
1972#endif
1973 }
1974#ifdef HAVE_IPV6
1975 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1976 {
1977 new->addr.sa.sa_family = AF_INET6;
1978 new->addr.in6.sin6_flowinfo = 0;
1979 new->addr.in6.sin6_scope_id = 0;
49678767 1980 new->addr.in6.sin6_port = 0;
849a8357
SK
1981#ifdef HAVE_SOCKADDR_SA_LEN
1982 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1983#endif
1984 }
1985#endif
1986 else
c4a7f90e 1987 ret_err(gen_err);
4ce4f377
SK
1988
1989 new->used = 0;
49678767
SK
1990 if (option == 'a')
1991 {
1992 new->next = daemon->if_addrs;
1993 daemon->if_addrs = new;
1994 }
1995 else
1996 {
1997 new->next = daemon->auth_peers;
1998 daemon->auth_peers = new;
1999 }
849a8357
SK
2000 arg = comma;
2001 } while (arg);
2002 break;
2003
8ef5ada2
SK
2004 case 'S': /* --server */
2005 case LOPT_LOCAL: /* --local */
2006 case 'A': /* --address */
2007 case LOPT_NO_REBIND: /* --rebind-domain-ok */
849a8357
SK
2008 {
2009 struct server *serv, *newlist = NULL;
2010
2011 unhide_metas(arg);
2012
8ef5ada2 2013 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
849a8357 2014 {
8ef5ada2
SK
2015 int rebind = !(*arg == '/');
2016 char *end = NULL;
2017 if (!rebind)
2018 arg++;
2019 while (rebind || (end = split_chr(arg, '/')))
fd9fa481 2020 {
849a8357 2021 char *domain = NULL;
8ef5ada2
SK
2022 /* elide leading dots - they are implied in the search algorithm */
2023 while (*arg == '.') arg++;
849a8357
SK
2024 /* # matches everything and becomes a zero length domain string */
2025 if (strcmp(arg, "#") == 0)
2026 domain = "";
1f15b81d 2027 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
849a8357 2028 option = '?';
824af85b
SK
2029 serv = opt_malloc(sizeof(struct server));
2030 memset(serv, 0, sizeof(struct server));
849a8357
SK
2031 serv->next = newlist;
2032 newlist = serv;
849a8357
SK
2033 serv->domain = domain;
2034 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
73a08a24 2035 arg = end;
8ef5ada2
SK
2036 if (rebind)
2037 break;
fd9fa481 2038 }
849a8357 2039 if (!newlist)
c4a7f90e 2040 ret_err(gen_err);
849a8357
SK
2041 }
2042 else
2043 {
824af85b
SK
2044 newlist = opt_malloc(sizeof(struct server));
2045 memset(newlist, 0, sizeof(struct server));
849a8357
SK
2046 }
2047
2048 if (option == 'A')
2049 {
2050 newlist->flags |= SERV_LITERAL_ADDRESS;
2051 if (!(newlist->flags & SERV_TYPE))
c4a7f90e 2052 ret_err(gen_err);
849a8357 2053 }
8ef5ada2
SK
2054 else if (option == LOPT_NO_REBIND)
2055 newlist->flags |= SERV_NO_REBIND;
849a8357
SK
2056
2057 if (!arg || !*arg)
2058 {
8ef5ada2
SK
2059 if (!(newlist->flags & SERV_NO_REBIND))
2060 newlist->flags |= SERV_NO_ADDR; /* no server */
2061 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 2062 ret_err(gen_err);
8ef5ada2
SK
2063 }
2064
2065 else if (strcmp(arg, "#") == 0)
2066 {
2067 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
849a8357 2068 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 2069 ret_err(gen_err);
849a8357
SK
2070 }
2071 else
2072 {
faafb3f7
SK
2073 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2074 if (err)
2075 ret_err(err);
849a8357
SK
2076 }
2077
f2621c7f
SK
2078 serv = newlist;
2079 while (serv->next)
849a8357 2080 {
f2621c7f
SK
2081 serv->next->flags = serv->flags;
2082 serv->next->addr = serv->addr;
2083 serv->next->source_addr = serv->source_addr;
faafb3f7 2084 strcpy(serv->next->interface, serv->interface);
f2621c7f 2085 serv = serv->next;
849a8357 2086 }
f2621c7f
SK
2087 serv->next = daemon->servers;
2088 daemon->servers = newlist;
849a8357
SK
2089 break;
2090 }
13d86c73
JD
2091
2092 case LOPT_IPSET: /* --ipset */
2093#ifndef HAVE_IPSET
2094 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2095 break;
2096#else
2097 {
2098 struct ipsets ipsets_head;
2099 struct ipsets *ipsets = &ipsets_head;
2100 int size;
2101 char *end;
2102 char **sets, **sets_pos;
2103 memset(ipsets, 0, sizeof(struct ipsets));
2104 unhide_metas(arg);
2105 if (arg && *arg == '/')
2106 {
2107 arg++;
2108 while ((end = split_chr(arg, '/')))
2109 {
2110 char *domain = NULL;
2111 /* elide leading dots - they are implied in the search algorithm */
2112 while (*arg == '.')
2113 arg++;
2114 /* # matches everything and becomes a zero length domain string */
2115 if (strcmp(arg, "#") == 0 || !*arg)
2116 domain = "";
2117 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2118 option = '?';
2119 ipsets->next = opt_malloc(sizeof(struct ipsets));
2120 ipsets = ipsets->next;
2121 memset(ipsets, 0, sizeof(struct ipsets));
2122 ipsets->domain = domain;
2123 arg = end;
2124 }
2125 }
2126 else
2127 {
2128 ipsets->next = opt_malloc(sizeof(struct ipsets));
2129 ipsets = ipsets->next;
2130 memset(ipsets, 0, sizeof(struct ipsets));
2131 ipsets->domain = "";
2132 }
2133 if (!arg || !*arg)
2134 {
2135 option = '?';
2136 break;
2137 }
2138 size = 2;
2139 for (end = arg; *end; ++end)
2140 if (*end == ',')
2141 ++size;
2142
2143 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2144
2145 do {
2146 end = split(arg);
2147 *sets_pos++ = opt_string_alloc(arg);
2148 arg = end;
2149 } while (end);
2150 *sets_pos = 0;
2151 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2152 ipsets->next->sets = sets;
2153 ipsets->next = daemon->ipsets;
2154 daemon->ipsets = ipsets_head.next;
2155
2156 break;
2157 }
2158#endif
849a8357 2159
f2621c7f 2160 case 'c': /* --cache-size */
849a8357
SK
2161 {
2162 int size;
2163
2164 if (!atoi_check(arg, &size))
c4a7f90e 2165 ret_err(gen_err);
849a8357
SK
2166 else
2167 {
2168 /* zero is OK, and means no caching. */
2169
2170 if (size < 0)
2171 size = 0;
2172 else if (size > 10000)
2173 size = 10000;
2174
2175 daemon->cachesize = size;
2176 }
2177 break;
2178 }
2179
f2621c7f 2180 case 'p': /* --port */
1ad24ae1 2181 if (!atoi_check16(arg, &daemon->port))
c4a7f90e 2182 ret_err(gen_err);
849a8357 2183 break;
208b65c5 2184
1a6bca81 2185 case LOPT_MINPORT: /* --min-port */
1ad24ae1 2186 if (!atoi_check16(arg, &daemon->min_port))
c4a7f90e 2187 ret_err(gen_err);
1a6bca81
SK
2188 break;
2189
f2621c7f 2190 case '0': /* --dns-forward-max */
208b65c5 2191 if (!atoi_check(arg, &daemon->ftabsize))
c4a7f90e 2192 ret_err(gen_err);
208b65c5
SK
2193 break;
2194
f2621c7f
SK
2195 case LOPT_MAX_LOGS: /* --log-async */
2196 daemon->max_logs = LOG_MAX; /* default */
2197 if (arg && !atoi_check(arg, &daemon->max_logs))
c4a7f90e 2198 ret_err(gen_err);
f2621c7f
SK
2199 else if (daemon->max_logs > 100)
2200 daemon->max_logs = 100;
2201 break;
2202
2203 case 'P': /* --edns-packet-max */
849a8357
SK
2204 {
2205 int i;
2206 if (!atoi_check(arg, &i))
c4a7f90e 2207 ret_err(gen_err);
849a8357
SK
2208 daemon->edns_pktsz = (unsigned short)i;
2209 break;
2210 }
2211
f2621c7f 2212 case 'Q': /* --query-port */
1ad24ae1 2213 if (!atoi_check16(arg, &daemon->query_port))
c4a7f90e 2214 ret_err(gen_err);
1a6bca81
SK
2215 /* if explicitly set to zero, use single OS ephemeral port
2216 and disable random ports */
2217 if (daemon->query_port == 0)
2218 daemon->osport = 1;
849a8357
SK
2219 break;
2220
824af85b
SK
2221 case 'T': /* --local-ttl */
2222 case LOPT_NEGTTL: /* --neg-ttl */
8ef5ada2 2223 case LOPT_MAXTTL: /* --max-ttl */
1d860415 2224 case LOPT_MAXCTTL: /* --max-cache-ttl */
4f7b304f 2225 case LOPT_AUTHTTL: /* --auth-ttl */
849a8357
SK
2226 {
2227 int ttl;
2228 if (!atoi_check(arg, &ttl))
c4a7f90e 2229 ret_err(gen_err);
824af85b
SK
2230 else if (option == LOPT_NEGTTL)
2231 daemon->neg_ttl = (unsigned long)ttl;
8ef5ada2
SK
2232 else if (option == LOPT_MAXTTL)
2233 daemon->max_ttl = (unsigned long)ttl;
1d860415
SK
2234 else if (option == LOPT_MAXCTTL)
2235 daemon->max_cache_ttl = (unsigned long)ttl;
4f7b304f
SK
2236 else if (option == LOPT_AUTHTTL)
2237 daemon->auth_ttl = (unsigned long)ttl;
849a8357
SK
2238 else
2239 daemon->local_ttl = (unsigned long)ttl;
2240 break;
2241 }
2242
7622fc06 2243#ifdef HAVE_DHCP
f2621c7f 2244 case 'X': /* --dhcp-lease-max */
849a8357 2245 if (!atoi_check(arg, &daemon->dhcp_max))
c4a7f90e 2246 ret_err(gen_err);
849a8357 2247 break;
7622fc06 2248#endif
849a8357 2249
7622fc06 2250#ifdef HAVE_TFTP
f2621c7f 2251 case LOPT_TFTP_MAX: /* --tftp-max */
832af0ba 2252 if (!atoi_check(arg, &daemon->tftp_max))
c4a7f90e 2253 ret_err(gen_err);
832af0ba
SK
2254 break;
2255
824af85b 2256 case LOPT_PREFIX: /* --tftp-prefix */
8ef5ada2
SK
2257 comma = split(arg);
2258 if (comma)
2259 {
2260 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2261 new->interface = opt_string_alloc(comma);
2262 new->prefix = opt_string_alloc(arg);
2263 new->next = daemon->if_prefix;
2264 daemon->if_prefix = new;
2265 }
2266 else
2267 daemon->tftp_prefix = opt_string_alloc(arg);
832af0ba
SK
2268 break;
2269
824af85b
SK
2270 case LOPT_TFTPPORTS: /* --tftp-port-range */
2271 if (!(comma = split(arg)) ||
1ad24ae1
SK
2272 !atoi_check16(arg, &daemon->start_tftp_port) ||
2273 !atoi_check16(comma, &daemon->end_tftp_port))
c4a7f90e 2274 ret_err(_("bad port range"));
824af85b
SK
2275
2276 if (daemon->start_tftp_port > daemon->end_tftp_port)
2277 {
2278 int tmp = daemon->start_tftp_port;
2279 daemon->start_tftp_port = daemon->end_tftp_port;
2280 daemon->end_tftp_port = tmp;
2281 }
2282
2283 break;
7622fc06 2284#endif
824af85b 2285
f2621c7f 2286 case LOPT_BRIDGE: /* --bridge-interface */
832af0ba 2287 {
824af85b 2288 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
316e2730 2289 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
c4a7f90e 2290 ret_err(_("bad bridge-interface"));
832af0ba 2291
316e2730 2292 strcpy(new->iface, arg);
832af0ba
SK
2293 new->alias = NULL;
2294 new->next = daemon->bridges;
2295 daemon->bridges = new;
2296
2297 do {
f2621c7f
SK
2298 arg = comma;
2299 comma = split(arg);
316e2730 2300 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
832af0ba 2301 {
824af85b 2302 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
832af0ba
SK
2303 b->next = new->alias;
2304 new->alias = b;
316e2730 2305 strcpy(b->iface, arg);
832af0ba
SK
2306 }
2307 } while (comma);
2308
2309 break;
2310 }
832af0ba 2311
7622fc06 2312#ifdef HAVE_DHCP
f2621c7f 2313 case 'F': /* --dhcp-range */
849a8357
SK
2314 {
2315 int k, leasepos = 2;
8445f5d2 2316 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
824af85b 2317 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
849a8357 2318
52b92f4d 2319 memset (new, 0, sizeof(*new));
849a8357 2320 new->lease_time = DEFLEASE;
52b92f4d 2321
849a8357
SK
2322 if (!arg)
2323 {
2324 option = '?';
2325 break;
2326 }
2327
2328 while(1)
2329 {
2330 for (cp = arg; *cp; cp++)
52b92f4d
SK
2331 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2332 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2333 (*cp >='0' && *cp <= '9')))
849a8357
SK
2334 break;
2335
f2621c7f 2336 if (*cp != ',' && (comma = split(arg)))
849a8357 2337 {
8bc4cece 2338 if (is_tag_prefix(arg))
9e4abcb5 2339 {
824af85b
SK
2340 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2341 tt->net = opt_string_alloc(arg+4);
849a8357
SK
2342 tt->next = new->filter;
2343 new->filter = tt;
9e4abcb5
SK
2344 }
2345 else
2346 {
849a8357 2347 if (new->netid.net)
c4a7f90e 2348 ret_err(_("only one tag allowed"));
8ef5ada2
SK
2349 else if (strstr(arg, "set:") == arg)
2350 new->netid.net = opt_string_alloc(arg+4);
9e4abcb5 2351 else
824af85b 2352 new->netid.net = opt_string_alloc(arg);
9e4abcb5 2353 }
f2621c7f 2354 arg = comma;
9e4abcb5 2355 }
849a8357 2356 else
9e4abcb5 2357 {
849a8357 2358 a[0] = arg;
9e4abcb5
SK
2359 break;
2360 }
849a8357
SK
2361 }
2362
1f776932 2363 for (k = 1; k < 8; k++)
f2621c7f
SK
2364 if (!(a[k] = split(a[k-1])))
2365 break;
849a8357 2366
52b92f4d 2367 if (k < 2)
c4a7f90e
SK
2368 ret_err(_("bad dhcp-range"));
2369
2370 if (inet_pton(AF_INET, a[0], &new->start))
849a8357 2371 {
52b92f4d
SK
2372 new->next = daemon->dhcp;
2373 daemon->dhcp = new;
30cd9666 2374 new->end = new->start;
52b92f4d 2375 if (strcmp(a[1], "static") == 0)
30cd9666 2376 new->flags |= CONTEXT_STATIC;
52b92f4d 2377 else if (strcmp(a[1], "proxy") == 0)
30cd9666
SK
2378 new->flags |= CONTEXT_PROXY;
2379 else if (!inet_pton(AF_INET, a[1], &new->end))
c4a7f90e 2380 ret_err(_("bad dhcp-range"));
52b92f4d
SK
2381
2382 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2383 {
2384 struct in_addr tmp = new->start;
2385 new->start = new->end;
2386 new->end = tmp;
2387 }
2388
c4a7f90e 2389 if (k >= 3 && strchr(a[2], '.') &&
ddd9a6b4 2390 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
52b92f4d
SK
2391 {
2392 new->flags |= CONTEXT_NETMASK;
2393 leasepos = 3;
2394 if (!is_same_net(new->start, new->end, new->netmask))
c4a7f90e 2395 ret_err(_("inconsistent DHCP range"));
52b92f4d
SK
2396 }
2397
2398 if (k >= 4 && strchr(a[3], '.') &&
ddd9a6b4 2399 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
52b92f4d
SK
2400 {
2401 new->flags |= CONTEXT_BRDCAST;
2402 leasepos = 4;
2403 }
849a8357 2404 }
52b92f4d
SK
2405#ifdef HAVE_DHCP6
2406 else if (inet_pton(AF_INET6, a[0], &new->start6))
849a8357 2407 {
52b92f4d 2408 new->prefix = 64; /* default */
30cd9666 2409 new->end6 = new->start6;
6692a1a5
SK
2410 new->next = daemon->dhcp6;
2411 daemon->dhcp6 = new;
2412
30cd9666 2413 for (leasepos = 1; leasepos < k; leasepos++)
801ca9a7 2414 {
30cd9666
SK
2415 if (strcmp(a[leasepos], "static") == 0)
2416 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2417 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
1f776932 2418 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
30cd9666 2419 else if (strcmp(a[leasepos], "ra-names") == 0)
1f776932 2420 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
30cd9666 2421 else if (strcmp(a[leasepos], "ra-stateless") == 0)
1f776932 2422 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
30cd9666
SK
2423 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2424 new->flags |= CONTEXT_DHCP;
1f776932
SK
2425 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2426 {
2427 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2428 new->flags |= CONTEXT_TEMPLATE;
2429 }
921360ce
SK
2430 else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
2431 {
2432 new->template_interface = opt_string_alloc(a[leasepos] + 19);
2433 new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
2434 }
30cd9666
SK
2435 else
2436 break;
801ca9a7 2437 }
6692a1a5 2438
52b92f4d 2439 /* bare integer < 128 is prefix value */
c4a7f90e 2440 if (leasepos < k)
52b92f4d
SK
2441 {
2442 int pref;
30cd9666 2443 for (cp = a[leasepos]; *cp; cp++)
52b92f4d
SK
2444 if (!(*cp >= '0' && *cp <= '9'))
2445 break;
30cd9666 2446 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
52b92f4d
SK
2447 {
2448 new->prefix = pref;
30cd9666 2449 leasepos++;
52b92f4d
SK
2450 }
2451 }
30cd9666 2452
6692a1a5
SK
2453 if (new->prefix != 64)
2454 {
2455 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2456 ret_err(_("prefix length must be exactly 64 for RA subnets"));
2457 else if (new->flags & CONTEXT_TEMPLATE)
2458 ret_err(_("prefix length must be exactly 64 for subnet constructors"));
2459 }
2460
2461 if (new->prefix < 64)
2462 ret_err(_("prefix length must be at least 64"));
2463
c4a7f90e
SK
2464 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2465 ret_err(_("inconsistent DHCPv6 range"));
6692a1a5
SK
2466
2467 /* dhcp-range=:: enables DHCP stateless on any interface */
2468 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
2469 new->prefix = 0;
66409193
SK
2470
2471 if (new->flags & CONTEXT_TEMPLATE)
2472 {
2473 struct in6_addr zero;
2474 memset(&zero, 0, sizeof(zero));
2475 if (!is_same_net6(&zero, &new->start6, new->prefix))
2476 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2477 }
2478
c4a7f90e 2479 if (addr6part(&new->start6) > addr6part(&new->end6))
52b92f4d
SK
2480 {
2481 struct in6_addr tmp = new->start6;
2482 new->start6 = new->end6;
2483 new->end6 = tmp;
2484 }
849a8357 2485 }
52b92f4d 2486#endif
d9ee9c08
SK
2487 else
2488 ret_err(_("bad dhcp-range"));
849a8357 2489
30cd9666 2490 if (leasepos < k)
849a8357
SK
2491 {
2492 if (strcmp(a[leasepos], "infinite") == 0)
2493 new->lease_time = 0xffffffff;
c8257540
SK
2494 else if (strcmp(a[leasepos], "deprecated") == 0)
2495 new->flags |= CONTEXT_DEPRECATE;
849a8357 2496 else
9e4abcb5 2497 {
849a8357
SK
2498 int fac = 1;
2499 if (strlen(a[leasepos]) > 0)
36717eee 2500 {
849a8357 2501 switch (a[leasepos][strlen(a[leasepos]) - 1])
36717eee 2502 {
42243214
SK
2503 case 'w':
2504 case 'W':
2505 fac *= 7;
2506 /* fall through */
849a8357
SK
2507 case 'd':
2508 case 'D':
2509 fac *= 24;
2510 /* fall though */
2511 case 'h':
2512 case 'H':
2513 fac *= 60;
2514 /* fall through */
2515 case 'm':
2516 case 'M':
2517 fac *= 60;
2518 /* fall through */
2519 case 's':
2520 case 'S':
f2621c7f 2521 a[leasepos][strlen(a[leasepos]) - 1] = 0;
9e4abcb5 2522 }
849a8357 2523
be37986a
SK
2524 for (cp = a[leasepos]; *cp; cp++)
2525 if (!(*cp >= '0' && *cp <= '9'))
2526 break;
2527
54dae552 2528 if (*cp || (leasepos+1 < k))
be37986a
SK
2529 ret_err(_("bad dhcp-range"));
2530
849a8357
SK
2531 new->lease_time = atoi(a[leasepos]) * fac;
2532 /* Leases of a minute or less confuse
2533 some clients, notably Apple's */
2534 if (new->lease_time < 120)
2535 new->lease_time = 120;
9e4abcb5 2536 }
9e4abcb5 2537 }
849a8357
SK
2538 }
2539 break;
2540 }
5aabfc78 2541
5aabfc78 2542 case LOPT_BANK:
f2621c7f 2543 case 'G': /* --dhcp-host */
849a8357 2544 {
f2621c7f 2545 int j, k = 0;
3e8ed78b 2546 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
5aabfc78 2547 struct dhcp_config *new;
849a8357
SK
2548 struct in_addr in;
2549
824af85b
SK
2550 new = opt_malloc(sizeof(struct dhcp_config));
2551
849a8357 2552 new->next = daemon->dhcp_conf;
9009d746
SK
2553 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2554 new->hwaddr = NULL;
8ef5ada2
SK
2555 new->netid = NULL;
2556
849a8357 2557 if ((a[0] = arg))
3e8ed78b 2558 for (k = 1; k < 7; k++)
f2621c7f
SK
2559 if (!(a[k] = split(a[k-1])))
2560 break;
849a8357
SK
2561
2562 for (j = 0; j < k; j++)
2563 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2564 {
2565 char *arg = a[j];
2566
2567 if ((arg[0] == 'i' || arg[0] == 'I') &&
2568 (arg[1] == 'd' || arg[1] == 'D') &&
2569 arg[2] == ':')
2570 {
2571 if (arg[3] == '*')
2572 new->flags |= CONFIG_NOCLID;
2573 else
3d8df260 2574 {
849a8357
SK
2575 int len;
2576 arg += 3; /* dump id: */
2577 if (strchr(arg, ':'))
2578 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2579 else
5aabfc78
SK
2580 {
2581 unhide_metas(arg);
2582 len = (int) strlen(arg);
2583 }
2584
28866e95 2585 if (len == -1)
9f7f3b12 2586
c4a7f90e 2587 ret_err(_("bad hex constant"));
28866e95 2588 else if ((new->clid = opt_malloc(len)))
5aabfc78
SK
2589 {
2590 new->flags |= CONFIG_CLID;
2591 new->clid_len = len;
2592 memcpy(new->clid, arg, len);
2593 }
3d8df260 2594 }
849a8357 2595 }
8ef5ada2
SK
2596 /* dhcp-host has strange backwards-compat needs. */
2597 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
849a8357 2598 {
8ef5ada2
SK
2599 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2600 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2601 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2602 newlist->next = new->netid;
2603 new->netid = newlist;
2604 newlist->list = newtag;
2605 strcpy(newtag->net, arg+4);
2606 unhide_metas(newtag->net);
849a8357 2607 }
7de060b0 2608 else if (strstr(arg, "tag:") == arg)
c4a7f90e 2609 ret_err(_("cannot match tags in --dhcp-host"));
4cb1b320
SK
2610#ifdef HAVE_DHCP6
2611 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2612 {
2613 arg[strlen(arg)-1] = 0;
2614 arg++;
2615
2616 if (!inet_pton(AF_INET6, arg, &new->addr6))
c4a7f90e 2617 ret_err(_("bad IPv6 address"));
30393100
SK
2618
2619 for (i= 0; i < 8; i++)
2620 if (new->addr6.s6_addr[i] != 0)
2621 break;
2622
2623 /* set WILDCARD if network part all zeros */
2624 if (i == 8)
2625 new->flags |= CONFIG_WILDCARD;
4cb1b320
SK
2626
2627 new->flags |= CONFIG_ADDR6;
2628 }
2629#endif
7de060b0 2630 else
849a8357 2631 {
9009d746 2632 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
28866e95
SK
2633 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2634 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
c4a7f90e 2635 ret_err(_("bad hex constant"));
28866e95
SK
2636 else
2637 {
2638
2639 newhw->next = new->hwaddr;
2640 new->hwaddr = newhw;
2641 }
849a8357
SK
2642 }
2643 }
ddd9a6b4 2644 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
849a8357 2645 {
c4a7f90e
SK
2646 struct dhcp_config *configs;
2647
849a8357
SK
2648 new->addr = in;
2649 new->flags |= CONFIG_ADDR;
c4a7f90e
SK
2650
2651 /* If the same IP appears in more than one host config, then DISCOVER
2652 for one of the hosts will get the address, but REQUEST will be NAKed,
2653 since the address is reserved by the other one -> protocol loop. */
2654 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2655 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2656 {
2657 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2658 return 0;
2659 }
849a8357
SK
2660 }
2661 else
2662 {
2663 char *cp, *lastp = NULL, last = 0;
2664 int fac = 1;
2665
2666 if (strlen(a[j]) > 1)
2667 {
2668 lastp = a[j] + strlen(a[j]) - 1;
2669 last = *lastp;
2670 switch (last)
9e4abcb5 2671 {
42243214
SK
2672 case 'w':
2673 case 'W':
2674 fac *= 7;
2675 /* fall through */
849a8357
SK
2676 case 'd':
2677 case 'D':
2678 fac *= 24;
2679 /* fall through */
2680 case 'h':
2681 case 'H':
2682 fac *= 60;
2683 /* fall through */
2684 case 'm':
2685 case 'M':
2686 fac *= 60;
2687 /* fall through */
2688 case 's':
2689 case 'S':
2690 *lastp = 0;
9e4abcb5 2691 }
849a8357
SK
2692 }
2693
2694 for (cp = a[j]; *cp; cp++)
572b41eb 2695 if (!isdigit((unsigned char)*cp) && *cp != ' ')
849a8357
SK
2696 break;
2697
2698 if (*cp)
2699 {
2700 if (lastp)
2701 *lastp = last;
2702 if (strcmp(a[j], "infinite") == 0)
33820b7e 2703 {
849a8357
SK
2704 new->lease_time = 0xffffffff;
2705 new->flags |= CONFIG_TIME;
33820b7e 2706 }
849a8357
SK
2707 else if (strcmp(a[j], "ignore") == 0)
2708 new->flags |= CONFIG_DISABLE;
9e4abcb5
SK
2709 else
2710 {
1f15b81d
SK
2711 if (!(new->hostname = canonicalise_opt(a[j])) ||
2712 !legal_hostname(new->hostname))
c4a7f90e
SK
2713 ret_err(_("bad DHCP host name"));
2714
2715 new->flags |= CONFIG_NAME;
2716 new->domain = strip_hostname(new->hostname);
9e4abcb5 2717 }
849a8357
SK
2718 }
2719 else
2720 {
2721 new->lease_time = atoi(a[j]) * fac;
2722 /* Leases of a minute or less confuse
2723 some clients, notably Apple's */
2724 if (new->lease_time < 120)
2725 new->lease_time = 120;
2726 new->flags |= CONFIG_TIME;
2727 }
2728 }
2729
5aabfc78 2730 daemon->dhcp_conf = new;
849a8357
SK
2731 break;
2732 }
8ef5ada2
SK
2733
2734 case LOPT_TAG_IF: /* --tag-if */
2735 {
2736 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2737
2738 new->tag = NULL;
2739 new->set = NULL;
2740 new->next = NULL;
2741
2742 /* preserve order */
2743 if (!daemon->tag_if)
2744 daemon->tag_if = new;
2745 else
2746 {
2747 struct tag_if *tmp;
2748 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2749 tmp->next = new;
2750 }
2751
2752 while (arg)
2753 {
2754 size_t len;
2755
2756 comma = split(arg);
2757 len = strlen(arg);
2758
2759 if (len < 5)
2760 {
2761 new->set = NULL;
2762 break;
2763 }
2764 else
2765 {
2766 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2767 newtag->net = opt_malloc(len - 3);
2768 strcpy(newtag->net, arg+4);
2769 unhide_metas(newtag->net);
2770
2771 if (strstr(arg, "set:") == arg)
2772 {
2773 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2774 newlist->next = new->set;
2775 new->set = newlist;
2776 newlist->list = newtag;
2777 }
2778 else if (strstr(arg, "tag:") == arg)
2779 {
2780 newtag->next = new->tag;
2781 new->tag = newtag;
2782 }
2783 else
2784 {
2785 new->set = NULL;
4dc9c657 2786 free(newtag);
8ef5ada2
SK
2787 break;
2788 }
2789 }
2790
2791 arg = comma;
2792 }
2793
2794 if (!new->set)
c4a7f90e 2795 ret_err(_("bad tag-if"));
8ef5ada2
SK
2796
2797 break;
2798 }
2799
849a8357 2800
73a08a24
SK
2801 case 'O': /* --dhcp-option */
2802 case LOPT_FORCE: /* --dhcp-option-force */
824af85b 2803 case LOPT_OPTS:
73a08a24 2804 case LOPT_MATCH: /* --dhcp-match */
c4a7f90e
SK
2805 return parse_dhcp_opt(errstr, arg,
2806 option == LOPT_FORCE ? DHOPT_FORCE :
2807 (option == LOPT_MATCH ? DHOPT_MATCH :
2808 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2809
f2621c7f 2810 case 'M': /* --dhcp-boot */
849a8357
SK
2811 {
2812 struct dhcp_netid *id = NULL;
8ef5ada2 2813 while (is_tag_prefix(arg))
849a8357 2814 {
824af85b 2815 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
849a8357
SK
2816 newid->next = id;
2817 id = newid;
f2621c7f 2818 comma = split(arg);
824af85b 2819 newid->net = opt_string_alloc(arg+4);
849a8357
SK
2820 arg = comma;
2821 };
2822
2823 if (!arg)
c4a7f90e 2824 ret_err(gen_err);
849a8357
SK
2825 else
2826 {
7de060b0 2827 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
849a8357 2828 struct in_addr dhcp_next_server;
c4a7f90e 2829 struct dhcp_boot *new;
f2621c7f 2830 comma = split(arg);
824af85b 2831 dhcp_file = opt_string_alloc(arg);
849a8357
SK
2832 dhcp_next_server.s_addr = 0;
2833 if (comma)
a84fa1d0 2834 {
849a8357 2835 arg = comma;
f2621c7f 2836 comma = split(arg);
824af85b 2837 dhcp_sname = opt_string_alloc(arg);
849a8357 2838 if (comma)
a84fa1d0 2839 {
849a8357 2840 unhide_metas(comma);
ddd9a6b4
SK
2841 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2842 {
2843 /*
2844 * The user may have specified the tftp hostname here.
2845 * save it so that it can be resolved/looked up during
2846 * actual dhcp_reply().
2847 */
2848
2849 tftp_sname = opt_string_alloc(comma);
2850 dhcp_next_server.s_addr = 0;
2851 }
a84fa1d0 2852 }
a84fa1d0 2853 }
c4a7f90e
SK
2854
2855 new = opt_malloc(sizeof(struct dhcp_boot));
2856 new->file = dhcp_file;
2857 new->sname = dhcp_sname;
2858 new->tftp_sname = tftp_sname;
2859 new->next_server = dhcp_next_server;
2860 new->netid = id;
2861 new->next = daemon->boot_config;
2862 daemon->boot_config = new;
849a8357 2863 }
ddd9a6b4 2864
849a8357
SK
2865 break;
2866 }
7622fc06
SK
2867
2868 case LOPT_PXE_PROMT: /* --pxe-prompt */
2869 {
2870 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2871 int timeout;
2872
2873 new->netid = NULL;
2874 new->opt = 10; /* PXE_MENU_PROMPT */
2875
8ef5ada2
SK
2876 while (is_tag_prefix(arg))
2877 {
7622fc06
SK
2878 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2879 comma = split(arg);
2880 nn->next = new->netid;
2881 new->netid = nn;
2882 nn->net = opt_string_alloc(arg+4);
2883 arg = comma;
2884 }
2885
2886 if (!arg)
c4a7f90e 2887 ret_err(gen_err);
7622fc06
SK
2888 else
2889 {
2890 comma = split(arg);
2891 unhide_metas(arg);
2892 new->len = strlen(arg) + 1;
2893 new->val = opt_malloc(new->len);
2894 memcpy(new->val + 1, arg, new->len - 1);
2895
2896 new->u.vendor_class = (unsigned char *)"PXEClient";
2897 new->flags = DHOPT_VENDOR;
2898
2899 if (comma && atoi_check(comma, &timeout))
2900 *(new->val) = timeout;
2901 else
2902 *(new->val) = 255;
2903
2904 new->next = daemon->dhcp_opts;
2905 daemon->dhcp_opts = new;
1f15b81d 2906 daemon->enable_pxe = 1;
7622fc06
SK
2907 }
2908
2909 break;
2910 }
2911
2912 case LOPT_PXE_SERV: /* --pxe-service */
2913 {
2914 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2915 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2916 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2917 static int boottype = 32768;
2918
2919 new->netid = NULL;
751d6f4a 2920 new->sname = NULL;
7622fc06
SK
2921 new->server.s_addr = 0;
2922
8ef5ada2 2923 while (is_tag_prefix(arg))
7622fc06
SK
2924 {
2925 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2926 comma = split(arg);
2927 nn->next = new->netid;
2928 new->netid = nn;
2929 nn->net = opt_string_alloc(arg+4);
2930 arg = comma;
2931 }
2932
2933 if (arg && (comma = split(arg)))
2934 {
2935 for (i = 0; CSA[i]; i++)
2936 if (strcasecmp(CSA[i], arg) == 0)
2937 break;
2938
2939 if (CSA[i] || atoi_check(arg, &i))
2940 {
2941 arg = comma;
2942 comma = split(arg);
2943
2944 new->CSA = i;
2945 new->menu = opt_string_alloc(arg);
2946
316e2730
SK
2947 if (!comma)
2948 {
2949 new->type = 0; /* local boot */
2950 new->basename = NULL;
2951 }
2952 else
7622fc06
SK
2953 {
2954 arg = comma;
2955 comma = split(arg);
2956 if (atoi_check(arg, &i))
2957 {
2958 new->type = i;
2959 new->basename = NULL;
2960 }
2961 else
2962 {
2963 new->type = boottype++;
2964 new->basename = opt_string_alloc(arg);
2965 }
2966
751d6f4a
SK
2967 if (comma)
2968 {
2969 if (!inet_pton(AF_INET, comma, &new->server))
2970 {
2971 new->server.s_addr = 0;
2972 new->sname = opt_string_alloc(comma);
2973 }
2974
2975 }
7622fc06 2976 }
751d6f4a 2977
316e2730
SK
2978 /* Order matters */
2979 new->next = NULL;
2980 if (!daemon->pxe_services)
2981 daemon->pxe_services = new;
2982 else
2983 {
2984 struct pxe_service *s;
2985 for (s = daemon->pxe_services; s->next; s = s->next);
2986 s->next = new;
2987 }
2988
2989 daemon->enable_pxe = 1;
2990 break;
2991
7622fc06
SK
2992 }
2993 }
2994
c4a7f90e 2995 ret_err(gen_err);
7622fc06
SK
2996 }
2997
f2621c7f 2998 case '4': /* --dhcp-mac */
849a8357 2999 {
f2621c7f 3000 if (!(comma = split(arg)))
c4a7f90e 3001 ret_err(gen_err);
849a8357
SK
3002 else
3003 {
824af85b 3004 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
8ef5ada2 3005 new->netid.net = opt_string_alloc(set_prefix(arg));
f2621c7f
SK
3006 unhide_metas(comma);
3007 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
28866e95 3008 if (new->hwaddr_len == -1)
c4a7f90e 3009 ret_err(gen_err);
28866e95
SK
3010 else
3011 {
3012 new->next = daemon->dhcp_macs;
3013 daemon->dhcp_macs = new;
3014 }
849a8357
SK
3015 }
3016 }
3017 break;
c630924d
SK
3018
3019#ifdef OPTION6_PREFIX_CLASS
3020 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3021 {
3022 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3023
3024 if (!(comma = split(arg)) ||
3025 !atoi_check16(comma, &new->class))
3026 ret_err(gen_err);
3027
3028 new->tag.net = opt_string_alloc(set_prefix(arg));
3029 new->next = daemon->prefix_classes;
3030 daemon->prefix_classes = new;
3031
3032 break;
3033 }
3034#endif
3035
3036
f2621c7f
SK
3037 case 'U': /* --dhcp-vendorclass */
3038 case 'j': /* --dhcp-userclass */
3039 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3040 case LOPT_REMOTE: /* --dhcp-remoteid */
3041 case LOPT_SUBSCR: /* --dhcp-subscrid */
849a8357 3042 {
c4a7f90e
SK
3043 unsigned char *p;
3044 int dig = 0;
3045 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3046
3047 if (!(comma = split(arg)))
3048 ret_err(gen_err);
3049
3050 new->netid.net = opt_string_alloc(set_prefix(arg));
3051 /* check for hex string - must digits may include : must not have nothing else,
3052 only allowed for agent-options. */
3053
3054 arg = comma;
3055 if ((comma = split(arg)))
3056 {
3057 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3058 ret_err(gen_err);
3059 else
3060 new->enterprise = atoi(arg+11);
3061 }
3062 else
3063 comma = arg;
3064
3065 for (p = (unsigned char *)comma; *p; p++)
3066 if (isxdigit(*p))
3067 dig = 1;
3068 else if (*p != ':')
3069 break;
3070 unhide_metas(comma);
3071 if (option == 'U' || option == 'j' || *p || !dig)
3072 {
3073 new->len = strlen(comma);
3074 new->data = opt_malloc(new->len);
3075 memcpy(new->data, comma, new->len);
3076 }
3077 else
3078 {
3079 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3080 new->data = opt_malloc(new->len);
3081 memcpy(new->data, comma, new->len);
3082 }
3083
3084 switch (option)
3085 {
3086 case 'j':
3087 new->match_type = MATCH_USER;
3088 break;
3089 case 'U':
3090 new->match_type = MATCH_VENDOR;
3091 break;
3092 case LOPT_CIRCUIT:
3093 new->match_type = MATCH_CIRCUIT;
3094 break;
3095 case LOPT_REMOTE:
3096 new->match_type = MATCH_REMOTE;
3097 break;
3098 case LOPT_SUBSCR:
3099 new->match_type = MATCH_SUBSCRIBER;
3100 break;
3101 }
3102 new->next = daemon->dhcp_vendors;
3103 daemon->dhcp_vendors = new;
824af85b 3104
c4a7f90e 3105 break;
849a8357
SK
3106 }
3107
9e038946
SK
3108 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3109 if (!arg)
3110 {
3111 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3112 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3113 }
3114 else
3115 {
3116 comma = split(arg);
1ad24ae1
SK
3117 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3118 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
c4a7f90e 3119 ret_err(_("invalid port number"));
9e038946
SK
3120 if (!comma)
3121 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3122 }
3123 break;
3124
824af85b
SK
3125 case 'J': /* --dhcp-ignore */
3126 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3127 case LOPT_BROADCAST: /* --dhcp-broadcast */
8ef5ada2
SK
3128 case '3': /* --bootp-dynamic */
3129 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
849a8357 3130 {
824af85b 3131 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
849a8357 3132 struct dhcp_netid *list = NULL;
832af0ba
SK
3133 if (option == 'J')
3134 {
3135 new->next = daemon->dhcp_ignore;
3136 daemon->dhcp_ignore = new;
3137 }
824af85b
SK
3138 else if (option == LOPT_BROADCAST)
3139 {
3140 new->next = daemon->force_broadcast;
3141 daemon->force_broadcast = new;
3142 }
9009d746
SK
3143 else if (option == '3')
3144 {
3145 new->next = daemon->bootp_dynamic;
3146 daemon->bootp_dynamic = new;
3147 }
8ef5ada2
SK
3148 else if (option == LOPT_GEN_NAMES)
3149 {
3150 new->next = daemon->dhcp_gen_names;
3151 daemon->dhcp_gen_names = new;
3152 }
832af0ba
SK
3153 else
3154 {
3155 new->next = daemon->dhcp_ignore_names;
3156 daemon->dhcp_ignore_names = new;
3157 }
3158
3159 while (arg) {
824af85b 3160 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
f2621c7f 3161 comma = split(arg);
849a8357
SK
3162 member->next = list;
3163 list = member;
8ef5ada2 3164 if (is_tag_prefix(arg))
9009d746
SK
3165 member->net = opt_string_alloc(arg+4);
3166 else
3167 member->net = opt_string_alloc(arg);
849a8357 3168 arg = comma;
832af0ba 3169 }
849a8357
SK
3170
3171 new->list = list;
3172 break;
3173 }
8ef5ada2
SK
3174
3175 case LOPT_PROXY: /* --dhcp-proxy */
3176 daemon->override = 1;
3177 while (arg) {
3178 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3179 comma = split(arg);
ddd9a6b4 3180 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
c4a7f90e 3181 ret_err(_("bad dhcp-proxy address"));
8ef5ada2
SK
3182 new->next = daemon->override_relays;
3183 daemon->override_relays = new;
3184 arg = comma;
3185 }
3186 break;
7622fc06 3187#endif
849a8357 3188
8b372704
SK
3189#ifdef HAVE_DHCP6
3190 case LOPT_DUID: /* --dhcp-duid */
3191 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
c4a7f90e 3192 ret_err(_("bad DUID"));
8b372704
SK
3193 else
3194 {
3195 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3196 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3197 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3198 }
3199 break;
3200#endif
3201
f2621c7f 3202 case 'V': /* --alias */
849a8357 3203 {
73a08a24 3204 char *dash, *a[3] = { NULL, NULL, NULL };
f2621c7f 3205 int k = 0;
73a08a24
SK
3206 struct doctor *new = opt_malloc(sizeof(struct doctor));
3207 new->next = daemon->doctors;
3208 daemon->doctors = new;
3209 new->mask.s_addr = 0xffffffff;
3210 new->end.s_addr = 0;
3211
849a8357
SK
3212 if ((a[0] = arg))
3213 for (k = 1; k < 3; k++)
3214 {
f2621c7f 3215 if (!(a[k] = split(a[k-1])))
849a8357 3216 break;
849a8357
SK
3217 unhide_metas(a[k]);
3218 }
849a8357 3219
73a08a24
SK
3220 dash = split_chr(a[0], '-');
3221
849a8357 3222 if ((k < 2) ||
ddd9a6b4
SK
3223 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3224 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
73a08a24 3225 option = '?';
849a8357
SK
3226
3227 if (k == 3)
ddd9a6b4 3228 inet_pton(AF_INET, a[2], &new->mask);
849a8357 3229
73a08a24 3230 if (dash &&
ddd9a6b4 3231 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
73a08a24
SK
3232 !is_same_net(new->in, new->end, new->mask) ||
3233 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
c4a7f90e 3234 ret_err(_("invalid alias range"));
849a8357
SK
3235
3236 break;
3237 }
3238
f2621c7f 3239 case LOPT_INTNAME: /* --interface-name */
832af0ba 3240 {
f2621c7f 3241 struct interface_name *new, **up;
1f15b81d
SK
3242 char *domain = NULL;
3243
f2621c7f
SK
3244 comma = split(arg);
3245
1f15b81d 3246 if (!comma || !(domain = canonicalise_opt(arg)))
c4a7f90e 3247 ret_err(_("bad interface name"));
1f15b81d 3248
824af85b 3249 new = opt_malloc(sizeof(struct interface_name));
f2621c7f 3250 new->next = NULL;
115ac3e4
SK
3251 new->addr4 = NULL;
3252#ifdef HAVE_IPV6
3253 new->addr6 = NULL;
3254#endif
f2621c7f
SK
3255 /* Add to the end of the list, so that first name
3256 of an interface is used for PTR lookups. */
824af85b 3257 for (up = &daemon->int_names; *up; up = &((*up)->next));
f2621c7f 3258 *up = new;
1f15b81d 3259 new->name = domain;
824af85b 3260 new->intr = opt_string_alloc(comma);
f2621c7f
SK
3261 break;
3262 }
9009d746
SK
3263
3264 case LOPT_CNAME: /* --cname */
3265 {
3266 struct cname *new;
c4a7f90e
SK
3267 char *alias;
3268 char *target;
3269
9009d746 3270 if (!(comma = split(arg)))
c4a7f90e
SK
3271 ret_err(gen_err);
3272
3273 alias = canonicalise_opt(arg);
3274 target = canonicalise_opt(comma);
3275
3276 if (!alias || !target)
3277 ret_err(_("bad CNAME"));
9009d746
SK
3278 else
3279 {
c4a7f90e
SK
3280 for (new = daemon->cnames; new; new = new->next)
3281 if (hostname_isequal(new->alias, arg))
3282 ret_err(_("duplicate CNAME"));
3283 new = opt_malloc(sizeof(struct cname));
3284 new->next = daemon->cnames;
3285 daemon->cnames = new;
3286 new->alias = alias;
3287 new->target = target;
9009d746 3288 }
c4a7f90e 3289
9009d746
SK
3290 break;
3291 }
f2621c7f
SK
3292
3293 case LOPT_PTR: /* --ptr-record */
3294 {
3295 struct ptr_record *new;
1f15b81d
SK
3296 char *dom, *target = NULL;
3297
f2621c7f
SK
3298 comma = split(arg);
3299
1f15b81d
SK
3300 if (!(dom = canonicalise_opt(arg)) ||
3301 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 3302 ret_err(_("bad PTR record"));
1f15b81d
SK
3303 else
3304 {
3305 new = opt_malloc(sizeof(struct ptr_record));
3306 new->next = daemon->ptr;
3307 daemon->ptr = new;
3308 new->name = dom;
3309 new->ptr = target;
3310 }
832af0ba
SK
3311 break;
3312 }
3313
1a6bca81
SK
3314 case LOPT_NAPTR: /* --naptr-record */
3315 {
3316 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3317 int k = 0;
3318 struct naptr *new;
3319 int order, pref;
1f15b81d 3320 char *name, *replace = NULL;
1a6bca81
SK
3321
3322 if ((a[0] = arg))
3323 for (k = 1; k < 7; k++)
3324 if (!(a[k] = split(a[k-1])))
3325 break;
3326
3327
3328 if (k < 6 ||
1f15b81d 3329 !(name = canonicalise_opt(a[0])) ||
1ad24ae1
SK
3330 !atoi_check16(a[1], &order) ||
3331 !atoi_check16(a[2], &pref) ||
1f15b81d 3332 (k == 7 && !(replace = canonicalise_opt(a[6]))))
c4a7f90e 3333 ret_err(_("bad NAPTR record"));
1a6bca81
SK
3334 else
3335 {
3336 new = opt_malloc(sizeof(struct naptr));
3337 new->next = daemon->naptr;
3338 daemon->naptr = new;
1f15b81d 3339 new->name = name;
1a6bca81
SK
3340 new->flags = opt_string_alloc(a[3]);
3341 new->services = opt_string_alloc(a[4]);
3342 new->regexp = opt_string_alloc(a[5]);
1f15b81d 3343 new->replace = replace;
1a6bca81
SK
3344 new->order = order;
3345 new->pref = pref;
3346 }
3347 break;
3348 }
9f7f3b12
SK
3349
3350 case LOPT_RR: /* dns-rr */
3351 {
3352 struct txt_record *new;
3353 size_t len;
3354 char *data;
3355 int val;
3356
3357 comma = split(arg);
3358 data = split(comma);
3359
3360 new = opt_malloc(sizeof(struct txt_record));
3361 new->next = daemon->rr;
3362 daemon->rr = new;
3363
3364 if (!atoi_check(comma, &val) ||
3365 !(new->name = canonicalise_opt(arg)) ||
51931b88 3366 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
c4a7f90e
SK
3367 ret_err(_("bad RR record"));
3368
9f7f3b12
SK
3369 new->class = val;
3370 new->len = 0;
3371
3372 if (data)
3373 {
3374 new->txt=opt_malloc(len);
3375 new->len = len;
3376 memcpy(new->txt, data, len);
3377 }
3378
3379 break;
3380 }
3381
f2621c7f 3382 case 'Y': /* --txt-record */
849a8357
SK
3383 {
3384 struct txt_record *new;
28866e95
SK
3385 unsigned char *p, *cnt;
3386 size_t len;
3387
3388 comma = split(arg);
3389
824af85b 3390 new = opt_malloc(sizeof(struct txt_record));
849a8357
SK
3391 new->next = daemon->txt;
3392 daemon->txt = new;
3393 new->class = C_IN;
849a8357 3394
1f15b81d 3395 if (!(new->name = canonicalise_opt(arg)))
c4a7f90e
SK
3396 ret_err(_("bad TXT record"));
3397
28866e95
SK
3398 len = comma ? strlen(comma) : 0;
3399 len += (len/255) + 1; /* room for extra counts */
3400 new->txt = p = opt_malloc(len);
3401
3402 cnt = p++;
3403 *cnt = 0;
3404
3405 while (comma && *comma)
3406 {
3407 unsigned char c = (unsigned char)*comma++;
3408
3409 if (c == ',' || *cnt == 255)
3410 {
3411 if (c != ',')
3412 comma--;
3413 cnt = p++;
3414 *cnt = 0;
3415 }
3416 else
3417 {
3418 *p++ = unhide_meta(c);
3419 (*cnt)++;
3420 }
3421 }
3422
3423 new->len = p - new->txt;
3424
849a8357
SK
3425 break;
3426 }
3427
f2621c7f 3428 case 'W': /* --srv-host */
849a8357
SK
3429 {
3430 int port = 1, priority = 0, weight = 0;
3431 char *name, *target = NULL;
3432 struct mx_srv_record *new;
3433
f2621c7f 3434 comma = split(arg);
849a8357 3435
1f15b81d 3436 if (!(name = canonicalise_opt(arg)))
c4a7f90e
SK
3437 ret_err(_("bad SRV record"));
3438
849a8357
SK
3439 if (comma)
3440 {
3441 arg = comma;
f2621c7f 3442 comma = split(arg);
c4a7f90e
SK
3443 if (!(target = canonicalise_opt(arg)))
3444 ret_err(_("bad SRV target"));
824af85b 3445
849a8357 3446 if (comma)
f6b7dc47 3447 {
849a8357 3448 arg = comma;
f2621c7f 3449 comma = split(arg);
1ad24ae1 3450 if (!atoi_check16(arg, &port))
c4a7f90e 3451 ret_err(_("invalid port number"));
824af85b 3452
f6b7dc47
SK
3453 if (comma)
3454 {
91dccd09 3455 arg = comma;
f2621c7f 3456 comma = split(arg);
1ad24ae1 3457 if (!atoi_check16(arg, &priority))
c4a7f90e 3458 ret_err(_("invalid priority"));
824af85b 3459
f6b7dc47
SK
3460 if (comma)
3461 {
91dccd09 3462 arg = comma;
f2621c7f 3463 comma = split(arg);
1ad24ae1 3464 if (!atoi_check16(arg, &weight))
c4a7f90e 3465 ret_err(_("invalid weight"));
f6b7dc47
SK
3466 }
3467 }
f6b7dc47 3468 }
849a8357
SK
3469 }
3470
824af85b 3471 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
3472 new->next = daemon->mxnames;
3473 daemon->mxnames = new;
3474 new->issrv = 1;
3475 new->name = name;
3476 new->target = target;
3477 new->srvport = port;
3478 new->priority = priority;
3479 new->weight = weight;
3480 break;
3481 }
7622fc06 3482
e759d426
SK
3483 case LOPT_HOST_REC: /* --host-record */
3484 {
3485 struct host_record *new = opt_malloc(sizeof(struct host_record));
3486 memset(new, 0, sizeof(struct host_record));
3487
3488 if (!arg || !(comma = split(arg)))
c4a7f90e
SK
3489 ret_err(_("Bad host-record"));
3490
3491 while (arg)
3492 {
3493 struct all_addr addr;
3494 if (inet_pton(AF_INET, arg, &addr))
3495 new->addr = addr.addr.addr4;
e759d426 3496#ifdef HAVE_IPV6
c4a7f90e
SK
3497 else if (inet_pton(AF_INET6, arg, &addr))
3498 new->addr6 = addr.addr.addr6;
e759d426 3499#endif
c4a7f90e
SK
3500 else
3501 {
3502 int nomem;
3503 char *canon = canonicalise(arg, &nomem);
3504 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3505 if (!canon)
3506 ret_err(_("Bad name in host-record"));
3507
3508 nl->name = canon;
3509 /* keep order, so that PTR record goes to first name */
3510 nl->next = NULL;
3511 if (!new->names)
3512 new->names = nl;
3513 else
3514 {
3515 struct name_list *tmp;
3516 for (tmp = new->names; tmp->next; tmp = tmp->next);
3517 tmp->next = nl;
3518 }
c4a7f90e 3519 }
e4807d8b
SK
3520
3521 arg = comma;
3522 comma = split(arg);
c4a7f90e 3523 }
e759d426
SK
3524
3525 /* Keep list order */
3526 if (!daemon->host_records_tail)
3527 daemon->host_records = new;
3528 else
3529 daemon->host_records_tail->next = new;
3530 new->next = NULL;
3531 daemon->host_records_tail = new;
3532 break;
3533 }
c4a7f90e 3534
7622fc06 3535 default:
c4a7f90e
SK
3536 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3537
849a8357 3538 }
824af85b 3539
c4a7f90e 3540 return 1;
849a8357
SK
3541}
3542
28866e95 3543static void read_file(char *file, FILE *f, int hard_opt)
849a8357 3544{
824af85b 3545 volatile int lineno = 0;
8ef5ada2 3546 char *buff = daemon->namebuff;
849a8357
SK
3547
3548 while (fgets(buff, MAXDNAME, f))
3549 {
611ebc5f
SK
3550 int white, i, option = hard_opt;
3551 char *errmess, *p, *arg = NULL, *start;
8ef5ada2 3552 size_t len;
832af0ba 3553
824af85b 3554 /* Memory allocation failure longjmps here if mem_recover == 1 */
611ebc5f 3555 if (option != 0)
824af85b
SK
3556 {
3557 if (setjmp(mem_jmp))
3558 continue;
3559 mem_recover = 1;
3560 }
3561
849a8357 3562 lineno++;
824af85b
SK
3563 errmess = NULL;
3564
849a8357
SK
3565 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3566 metacharacters get hidden also strip comments */
8ef5ada2 3567 for (white = 1, p = buff; *p; p++)
849a8357
SK
3568 {
3569 if (*p == '"')
3570 {
3571 memmove(p, p+1, strlen(p+1)+1);
8ef5ada2 3572
849a8357
SK
3573 for(; *p && *p != '"'; p++)
3574 {
5aabfc78 3575 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
849a8357
SK
3576 {
3577 if (p[1] == 't')
3578 p[1] = '\t';
3579 else if (p[1] == 'n')
3580 p[1] = '\n';
849a8357
SK
3581 else if (p[1] == 'b')
3582 p[1] = '\b';
3583 else if (p[1] == 'r')
3584 p[1] = '\r';
6b01084f
SK
3585 else if (p[1] == 'e') /* escape */
3586 p[1] = '\033';
849a8357
SK
3587 memmove(p, p+1, strlen(p+1)+1);
3588 }
3589 *p = hide_meta(*p);
3590 }
8ef5ada2
SK
3591
3592 if (*p == 0)
f2621c7f
SK
3593 {
3594 errmess = _("missing \"");
3595 goto oops;
3596 }
8ef5ada2
SK
3597
3598 memmove(p, p+1, strlen(p+1)+1);
849a8357 3599 }
f2621c7f 3600
8ef5ada2
SK
3601 if (isspace(*p))
3602 {
3603 *p = ' ';
3604 white = 1;
9e4abcb5 3605 }
8ef5ada2
SK
3606 else
3607 {
3608 if (white && *p == '#')
3609 {
3610 *p = 0;
3611 break;
3612 }
3613 white = 0;
3614 }
849a8357
SK
3615 }
3616
8ef5ada2
SK
3617
3618 /* strip leading spaces */
3619 for (start = buff; *start && *start == ' '; start++);
3620
3621 /* strip trailing spaces */
3622 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3623
3624 if (len == 0)
849a8357 3625 continue;
8ef5ada2
SK
3626 else
3627 start[len] = 0;
3628
611ebc5f 3629 if (option != 0)
8ef5ada2
SK
3630 arg = start;
3631 else if ((p=strchr(start, '=')))
849a8357
SK
3632 {
3633 /* allow spaces around "=" */
8ef5ada2
SK
3634 for (arg = p+1; *arg == ' '; arg++);
3635 for (; p >= start && (*p == ' ' || *p == '='); p--)
849a8357 3636 *p = 0;
9e4abcb5 3637 }
849a8357
SK
3638 else
3639 arg = NULL;
832af0ba 3640
611ebc5f 3641 if (option == 0)
5aabfc78 3642 {
5aabfc78
SK
3643 for (option = 0, i = 0; opts[i].name; i++)
3644 if (strcmp(opts[i].name, start) == 0)
3645 {
3646 option = opts[i].val;
3647 break;
3648 }
3649
3650 if (!option)
3651 errmess = _("bad option");
3652 else if (opts[i].has_arg == 0 && arg)
3653 errmess = _("extraneous parameter");
3654 else if (opts[i].has_arg == 1 && !arg)
3655 errmess = _("missing parameter");
3656 }
c4a7f90e
SK
3657
3658 oops:
832af0ba 3659 if (errmess)
c4a7f90e
SK
3660 strcpy(daemon->namebuff, errmess);
3661
3662 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
f2621c7f 3663 {
c4a7f90e 3664 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
824af85b 3665 if (hard_opt != 0)
c4a7f90e 3666 my_syslog(LOG_ERR, "%s", daemon->namebuff);
5aabfc78 3667 else
c4a7f90e 3668 die("%s", daemon->namebuff, EC_BADCONF);
f2621c7f 3669 }
849a8357
SK
3670 }
3671
8ef5ada2 3672 mem_recover = 0;
849a8357
SK
3673 fclose(f);
3674}
3675
395eb719 3676static int one_file(char *file, int hard_opt)
28866e95
SK
3677{
3678 FILE *f;
3679 int nofile_ok = 0;
3680 static int read_stdin = 0;
3681 static struct fileread {
3682 dev_t dev;
3683 ino_t ino;
3684 struct fileread *next;
3685 } *filesread = NULL;
3686
3687 if (hard_opt == '7')
3688 {
3689 /* default conf-file reading */
3690 hard_opt = 0;
3691 nofile_ok = 1;
3692 }
3693
3694 if (hard_opt == 0 && strcmp(file, "-") == 0)
3695 {
3696 if (read_stdin == 1)
395eb719 3697 return 1;
28866e95
SK
3698 read_stdin = 1;
3699 file = "stdin";
3700 f = stdin;
3701 }
3702 else
3703 {
3704 /* ignore repeated files. */
3705 struct stat statbuf;
3706
3707 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3708 {
3709 struct fileread *r;
3710
3711 for (r = filesread; r; r = r->next)
3712 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
395eb719 3713 return 1;
28866e95
SK
3714
3715 r = safe_malloc(sizeof(struct fileread));
3716 r->next = filesread;
3717 filesread = r;
3718 r->dev = statbuf.st_dev;
3719 r->ino = statbuf.st_ino;
3720 }
3721
3722 if (!(f = fopen(file, "r")))
3723 {
3724 if (errno == ENOENT && nofile_ok)
395eb719 3725 return 1; /* No conffile, all done. */
28866e95
SK
3726 else
3727 {
3728 char *str = _("cannot read %s: %s");
3729 if (hard_opt != 0)
3730 {
3731 my_syslog(LOG_ERR, str, file, strerror(errno));
395eb719 3732 return 0;
28866e95
SK
3733 }
3734 else
3735 die(str, file, EC_FILE);
3736 }
3737 }
3738 }
3739
3740 read_file(file, f, hard_opt);
395eb719 3741 return 1;
28866e95
SK
3742}
3743
3744/* expand any name which is a directory */
3745struct hostsfile *expand_filelist(struct hostsfile *list)
3746{
3747 int i;
3748 struct hostsfile *ah;
3749
3750 for (i = 0, ah = list; ah; ah = ah->next)
3751 {
3752 if (i <= ah->index)
3753 i = ah->index + 1;
3754
3755 if (ah->flags & AH_DIR)
3756 ah->flags |= AH_INACTIVE;
3757 else
3758 ah->flags &= ~AH_INACTIVE;
3759 }
3760
3761 for (ah = list; ah; ah = ah->next)
3762 if (!(ah->flags & AH_INACTIVE))
3763 {
3764 struct stat buf;
3765 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3766 {
3767 DIR *dir_stream;
3768 struct dirent *ent;
3769
3770 /* don't read this as a file */
3771 ah->flags |= AH_INACTIVE;
3772
3773 if (!(dir_stream = opendir(ah->fname)))
3774 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3775 ah->fname, strerror(errno));
3776 else
3777 {
3778 while ((ent = readdir(dir_stream)))
3779 {
3780 size_t lendir = strlen(ah->fname);
3781 size_t lenfile = strlen(ent->d_name);
3782 struct hostsfile *ah1;
3783 char *path;
3784
3785 /* ignore emacs backups and dotfiles */
3786 if (lenfile == 0 ||
3787 ent->d_name[lenfile - 1] == '~' ||
3788 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3789 ent->d_name[0] == '.')
3790 continue;
3791
3792 /* see if we have an existing record.
3793 dir is ah->fname
3794 file is ent->d_name
3795 path to match is ah1->fname */
3796
3797 for (ah1 = list; ah1; ah1 = ah1->next)
3798 {
3799 if (lendir < strlen(ah1->fname) &&
3800 strstr(ah1->fname, ah->fname) == ah1->fname &&
3801 ah1->fname[lendir] == '/' &&
3802 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3803 {
3804 ah1->flags &= ~AH_INACTIVE;
3805 break;
3806 }
3807 }
3808
3809 /* make new record */
3810 if (!ah1)
3811 {
3812 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3813 continue;
3814
3815 if (!(path = whine_malloc(lendir + lenfile + 2)))
3816 {
3817 free(ah1);
3818 continue;
3819 }
3820
3821 strcpy(path, ah->fname);
3822 strcat(path, "/");
3823 strcat(path, ent->d_name);
3824 ah1->fname = path;
3825 ah1->index = i++;
3826 ah1->flags = AH_DIR;
3827 ah1->next = list;
3828 list = ah1;
3829 }
3830
3831 /* inactivate record if not regular file */
3832 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3833 ah1->flags |= AH_INACTIVE;
3834
3835 }
3836 closedir(dir_stream);
3837 }
3838 }
3839 }
3840
3841 return list;
3842}
3843
3844
7622fc06 3845#ifdef HAVE_DHCP
824af85b
SK
3846void reread_dhcp(void)
3847{
28866e95
SK
3848 struct hostsfile *hf;
3849
824af85b
SK
3850 if (daemon->dhcp_hosts_file)
3851 {
3852 struct dhcp_config *configs, *cp, **up;
28866e95 3853
824af85b
SK
3854 /* remove existing... */
3855 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3856 {
3857 cp = configs->next;
3858
3859 if (configs->flags & CONFIG_BANK)
3860 {
9009d746 3861 struct hwaddr_config *mac, *tmp;
8ef5ada2 3862 struct dhcp_netid_list *list, *tmplist;
9009d746
SK
3863
3864 for (mac = configs->hwaddr; mac; mac = tmp)
3865 {
3866 tmp = mac->next;
3867 free(mac);
3868 }
8ef5ada2 3869
824af85b
SK
3870 if (configs->flags & CONFIG_CLID)
3871 free(configs->clid);
8ef5ada2
SK
3872
3873 for (list = configs->netid; list; list = tmplist)
3874 {
3875 free(list->list);
3876 tmplist = list->next;
3877 free(list);
3878 }
3879
824af85b
SK
3880 if (configs->flags & CONFIG_NAME)
3881 free(configs->hostname);
3882
3883 *up = configs->next;
3884 free(configs);
3885 }
3886 else
3887 up = &configs->next;
3888 }
3889
28866e95
SK
3890 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3891 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3892 if (!(hf->flags & AH_INACTIVE))
3893 {
395eb719
SK
3894 if (one_file(hf->fname, LOPT_BANK))
3895 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 3896 }
824af85b
SK
3897 }
3898
3899 if (daemon->dhcp_opts_file)
3900 {
3901 struct dhcp_opt *opts, *cp, **up;
3902 struct dhcp_netid *id, *next;
3903
3904 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3905 {
3906 cp = opts->next;
3907
3908 if (opts->flags & DHOPT_BANK)
3909 {
73a08a24
SK
3910 if ((opts->flags & DHOPT_VENDOR))
3911 free(opts->u.vendor_class);
824af85b
SK
3912 free(opts->val);
3913 for (id = opts->netid; id; id = next)
3914 {
3915 next = id->next;
3916 free(id->net);
3917 free(id);
3918 }
3919 *up = opts->next;
3920 free(opts);
3921 }
3922 else
3923 up = &opts->next;
3924 }
3925
28866e95
SK
3926 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3927 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3928 if (!(hf->flags & AH_INACTIVE))
3929 {
395eb719
SK
3930 if (one_file(hf->fname, LOPT_OPTS))
3931 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 3932 }
824af85b
SK
3933 }
3934}
7622fc06 3935#endif
824af85b 3936
5aabfc78 3937void read_opts(int argc, char **argv, char *compile_opts)
849a8357 3938{
824af85b 3939 char *buff = opt_malloc(MAXDNAME);
28866e95 3940 int option, conffile_opt = '7', testmode = 0;
c4a7f90e 3941 char *arg, *conffile = CONFFILE;
849a8357
SK
3942
3943 opterr = 0;
5aabfc78 3944
824af85b 3945 daemon = opt_malloc(sizeof(struct daemon));
849a8357
SK
3946 memset(daemon, 0, sizeof(struct daemon));
3947 daemon->namebuff = buff;
3948
3949 /* Set defaults - everything else is zero or NULL */
3950 daemon->cachesize = CACHESIZ;
208b65c5 3951 daemon->ftabsize = FTABSIZ;
849a8357 3952 daemon->port = NAMESERVER_PORT;
9e038946
SK
3953 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3954 daemon->dhcp_server_port = DHCP_SERVER_PORT;
849a8357
SK
3955 daemon->default_resolv.is_default = 1;
3956 daemon->default_resolv.name = RESOLVFILE;
3957 daemon->resolv_files = &daemon->default_resolv;
3958 daemon->username = CHUSER;
849a8357
SK
3959 daemon->runfile = RUNFILE;
3960 daemon->dhcp_max = MAXLEASES;
832af0ba 3961 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
849a8357
SK
3962 daemon->edns_pktsz = EDNS_PKTSZ;
3963 daemon->log_fac = -1;
4f7b304f
SK
3964 daemon->auth_ttl = AUTH_TTL;
3965 daemon->soa_refresh = SOA_REFRESH;
3966 daemon->soa_retry = SOA_RETRY;
3967 daemon->soa_expiry = SOA_EXPIRY;
5aabfc78
SK
3968 add_txt("version.bind", "dnsmasq-" VERSION );
3969 add_txt("authors.bind", "Simon Kelley");
3970 add_txt("copyright.bind", COPYRIGHT);
849a8357
SK
3971
3972 while (1)
3973 {
26128d27 3974#ifdef HAVE_GETOPT_LONG
849a8357 3975 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
26128d27 3976#else
849a8357 3977 option = getopt(argc, argv, OPTSTRING);
26128d27 3978#endif
849a8357
SK
3979
3980 if (option == -1)
28866e95 3981 {
572b41eb
SK
3982 for (; optind < argc; optind++)
3983 {
3984 unsigned char *c = (unsigned char *)argv[optind];
3985 for (; *c != 0; c++)
3986 if (!isspace(*c))
3987 die(_("junk found in command line"), NULL, EC_BADCONF);
3988 }
28866e95
SK
3989 break;
3990 }
3991
849a8357
SK
3992 /* Copy optarg so that argv doesn't get changed */
3993 if (optarg)
3994 {
3995 strncpy(buff, optarg, MAXDNAME);
3996 buff[MAXDNAME-1] = 0;
3997 arg = buff;
9e4abcb5 3998 }
849a8357
SK
3999 else
4000 arg = NULL;
9e4abcb5 4001
849a8357 4002 /* command-line only stuff */
7622fc06
SK
4003 if (option == LOPT_TEST)
4004 testmode = 1;
4005 else if (option == 'w')
849a8357 4006 {
7622fc06 4007#ifdef HAVE_DHCP
4cb1b320 4008 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
7622fc06 4009 display_opts();
4cb1b320
SK
4010#ifdef HAVE_DHCP6
4011 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4012 display_opts6();
7622fc06 4013#endif
4cb1b320 4014 else
7622fc06 4015#endif
4cb1b320
SK
4016 do_usage();
4017
849a8357
SK
4018 exit(0);
4019 }
4020 else if (option == 'v')
4021 {
4022 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
c72daea8 4023 printf(_("Compile time options: %s\n\n"), compile_opts);
849a8357
SK
4024 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4025 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
824af85b 4026 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
849a8357
SK
4027 exit(0);
4028 }
4029 else if (option == 'C')
4030 {
28866e95 4031 conffile_opt = 0; /* file must exist */
824af85b 4032 conffile = opt_string_alloc(arg);
849a8357
SK
4033 }
4034 else
4035 {
4036#ifdef HAVE_GETOPT_LONG
c4a7f90e 4037 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
849a8357 4038#else
c4a7f90e 4039 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
849a8357 4040#endif
c4a7f90e 4041 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
849a8357
SK
4042 }
4043 }
4044
4045 if (conffile)
28866e95 4046 one_file(conffile, conffile_opt);
849a8357 4047
1a6bca81 4048 /* port might not be known when the address is parsed - fill in here */
3be34541 4049 if (daemon->servers)
9e4abcb5
SK
4050 {
4051 struct server *tmp;
3be34541 4052 for (tmp = daemon->servers; tmp; tmp = tmp->next)
9e4abcb5
SK
4053 if (!(tmp->flags & SERV_HAS_SOURCE))
4054 {
4055 if (tmp->source_addr.sa.sa_family == AF_INET)
3be34541 4056 tmp->source_addr.in.sin_port = htons(daemon->query_port);
9e4abcb5
SK
4057#ifdef HAVE_IPV6
4058 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3be34541 4059 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
5aabfc78
SK
4060#endif
4061 }
9e4abcb5
SK
4062 }
4063
3be34541 4064 if (daemon->if_addrs)
9e4abcb5
SK
4065 {
4066 struct iname *tmp;
3be34541 4067 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
9e4abcb5 4068 if (tmp->addr.sa.sa_family == AF_INET)
3be34541 4069 tmp->addr.in.sin_port = htons(daemon->port);
9e4abcb5
SK
4070#ifdef HAVE_IPV6
4071 else if (tmp->addr.sa.sa_family == AF_INET6)
3be34541 4072 tmp->addr.in6.sin6_port = htons(daemon->port);
9e4abcb5
SK
4073#endif /* IPv6 */
4074 }
4f7b304f
SK
4075
4076 /* create default, if not specified */
4077 if (daemon->authserver && !daemon->hostmaster)
4078 {
4079 strcpy(buff, "hostmaster.");
4080 strcat(buff, daemon->authserver);
4081 daemon->hostmaster = opt_string_alloc(buff);
4082 }
4083
f6b7dc47 4084 /* only one of these need be specified: the other defaults to the host-name */
28866e95 4085 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
9e4abcb5 4086 {
0a852541
SK
4087 struct mx_srv_record *mx;
4088
9e4abcb5 4089 if (gethostname(buff, MAXDNAME) == -1)
5aabfc78 4090 die(_("cannot get host-name: %s"), NULL, EC_MISC);
f6b7dc47 4091
0a852541
SK
4092 for (mx = daemon->mxnames; mx; mx = mx->next)
4093 if (!mx->issrv && hostname_isequal(mx->name, buff))
4094 break;
4095
28866e95 4096 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
de37951c 4097 {
824af85b 4098 mx = opt_malloc(sizeof(struct mx_srv_record));
91dccd09
SK
4099 mx->next = daemon->mxnames;
4100 mx->issrv = 0;
4101 mx->target = NULL;
824af85b 4102 mx->name = opt_string_alloc(buff);
91dccd09 4103 daemon->mxnames = mx;
f6b7dc47 4104 }
9e4abcb5 4105
3be34541 4106 if (!daemon->mxtarget)
824af85b 4107 daemon->mxtarget = opt_string_alloc(buff);
0a852541
SK
4108
4109 for (mx = daemon->mxnames; mx; mx = mx->next)
4110 if (!mx->issrv && !mx->target)
4111 mx->target = daemon->mxtarget;
9e4abcb5 4112 }
f6b7dc47 4113
28866e95 4114 if (!option_bool(OPT_NO_RESOLV) &&
208b65c5
SK
4115 daemon->resolv_files &&
4116 daemon->resolv_files->next &&
28866e95 4117 option_bool(OPT_NO_POLL))
5aabfc78 4118 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
de37951c 4119
28866e95 4120 if (option_bool(OPT_RESOLV_DOMAIN))
de37951c
SK
4121 {
4122 char *line;
849a8357
SK
4123 FILE *f;
4124
28866e95 4125 if (option_bool(OPT_NO_RESOLV) ||
208b65c5
SK
4126 !daemon->resolv_files ||
4127 (daemon->resolv_files)->next)
5aabfc78 4128 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
de37951c 4129
3be34541 4130 if (!(f = fopen((daemon->resolv_files)->name, "r")))
5aabfc78 4131 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
de37951c
SK
4132
4133 while ((line = fgets(buff, MAXDNAME, f)))
4134 {
4135 char *token = strtok(line, " \t\n\r");
4136
4137 if (!token || strcmp(token, "search") != 0)
4138 continue;
4139
4140 if ((token = strtok(NULL, " \t\n\r")) &&
1f15b81d 4141 (daemon->domain_suffix = canonicalise_opt(token)))
de37951c
SK
4142 break;
4143 }
3be34541 4144
de37951c 4145 fclose(f);
8a911ccc 4146
3be34541 4147 if (!daemon->domain_suffix)
5aabfc78 4148 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
de37951c 4149 }
3d8df260
SK
4150
4151 if (daemon->domain_suffix)
4152 {
4153 /* add domain for any srv record without one. */
4154 struct mx_srv_record *srv;
de37951c 4155
3d8df260
SK
4156 for (srv = daemon->mxnames; srv; srv = srv->next)
4157 if (srv->issrv &&
4158 strchr(srv->name, '.') &&
4159 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4160 {
4161 strcpy(buff, srv->name);
4162 strcat(buff, ".");
4163 strcat(buff, daemon->domain_suffix);
4164 free(srv->name);
824af85b 4165 srv->name = opt_string_alloc(buff);
3d8df260
SK
4166 }
4167 }
28866e95 4168 else if (option_bool(OPT_DHCP_FQDN))
9009d746 4169 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
7622fc06
SK
4170
4171 if (testmode)
4172 {
4173 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4174 exit(0);
4175 }
849a8357 4176}