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