]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/option.c
Add code to get IPv6 address lifetimes and flags for *BSD.
[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 },
2937f8a0 211 { "enable-tftp", 2, 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 },
2937f8a0 371 { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", 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
2937f8a0
SK
1907 case LOPT_TFTP: /* --enable-tftp */
1908 set_option_bool(OPT_TFTP);
1909 if (!arg)
1910 break;
1911 /* fall through */
1912
f2621c7f
SK
1913 case 'I': /* --except-interface */
1914 case '2': /* --no-dhcp-interface */
849a8357 1915 do {
824af85b 1916 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1917 comma = split(arg);
824af85b 1918 new->name = opt_string_alloc(arg);
849a8357
SK
1919 if (option == 'I')
1920 {
1921 new->next = daemon->if_except;
1922 daemon->if_except = new;
1923 }
2937f8a0
SK
1924 else if (option == LOPT_TFTP)
1925 {
1926 new->next = daemon->tftp_interfaces;
1927 daemon->tftp_interfaces = new;
1928 }
849a8357
SK
1929 else
1930 {
1931 new->next = daemon->dhcp_except;
1932 daemon->dhcp_except = new;
1933 }
1934 arg = comma;
1935 } while (arg);
1936 break;
1937
f2621c7f 1938 case 'B': /* --bogus-nxdomain */
849a8357
SK
1939 {
1940 struct in_addr addr;
1941 unhide_metas(arg);
ddd9a6b4 1942 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
849a8357 1943 {
824af85b 1944 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
849a8357
SK
1945 baddr->next = daemon->bogus_addr;
1946 daemon->bogus_addr = baddr;
1947 baddr->addr = addr;
1948 }
1949 else
c4a7f90e 1950 ret_err(gen_err); /* error */
849a8357
SK
1951 break;
1952 }
1953
f2621c7f 1954 case 'a': /* --listen-address */
49678767 1955 case LOPT_AUTHPEER: /* --auth-peer */
849a8357 1956 do {
824af85b 1957 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1958 comma = split(arg);
849a8357 1959 unhide_metas(arg);
ddd9a6b4 1960 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
849a8357
SK
1961 {
1962 new->addr.sa.sa_family = AF_INET;
49678767 1963 new->addr.in.sin_port = 0;
849a8357
SK
1964#ifdef HAVE_SOCKADDR_SA_LEN
1965 new->addr.in.sin_len = sizeof(new->addr.in);
1966#endif
1967 }
1968#ifdef HAVE_IPV6
1969 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1970 {
1971 new->addr.sa.sa_family = AF_INET6;
1972 new->addr.in6.sin6_flowinfo = 0;
1973 new->addr.in6.sin6_scope_id = 0;
49678767 1974 new->addr.in6.sin6_port = 0;
849a8357
SK
1975#ifdef HAVE_SOCKADDR_SA_LEN
1976 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1977#endif
1978 }
1979#endif
1980 else
c4a7f90e 1981 ret_err(gen_err);
4ce4f377
SK
1982
1983 new->used = 0;
49678767
SK
1984 if (option == 'a')
1985 {
1986 new->next = daemon->if_addrs;
1987 daemon->if_addrs = new;
1988 }
1989 else
1990 {
1991 new->next = daemon->auth_peers;
1992 daemon->auth_peers = new;
1993 }
849a8357
SK
1994 arg = comma;
1995 } while (arg);
1996 break;
1997
8ef5ada2
SK
1998 case 'S': /* --server */
1999 case LOPT_LOCAL: /* --local */
2000 case 'A': /* --address */
2001 case LOPT_NO_REBIND: /* --rebind-domain-ok */
849a8357
SK
2002 {
2003 struct server *serv, *newlist = NULL;
2004
2005 unhide_metas(arg);
2006
8ef5ada2 2007 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
849a8357 2008 {
8ef5ada2
SK
2009 int rebind = !(*arg == '/');
2010 char *end = NULL;
2011 if (!rebind)
2012 arg++;
2013 while (rebind || (end = split_chr(arg, '/')))
fd9fa481 2014 {
849a8357 2015 char *domain = NULL;
8ef5ada2
SK
2016 /* elide leading dots - they are implied in the search algorithm */
2017 while (*arg == '.') arg++;
849a8357
SK
2018 /* # matches everything and becomes a zero length domain string */
2019 if (strcmp(arg, "#") == 0)
2020 domain = "";
1f15b81d 2021 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
849a8357 2022 option = '?';
824af85b
SK
2023 serv = opt_malloc(sizeof(struct server));
2024 memset(serv, 0, sizeof(struct server));
849a8357
SK
2025 serv->next = newlist;
2026 newlist = serv;
849a8357
SK
2027 serv->domain = domain;
2028 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
73a08a24 2029 arg = end;
8ef5ada2
SK
2030 if (rebind)
2031 break;
fd9fa481 2032 }
849a8357 2033 if (!newlist)
c4a7f90e 2034 ret_err(gen_err);
849a8357
SK
2035 }
2036 else
2037 {
824af85b
SK
2038 newlist = opt_malloc(sizeof(struct server));
2039 memset(newlist, 0, sizeof(struct server));
849a8357
SK
2040 }
2041
2042 if (option == 'A')
2043 {
2044 newlist->flags |= SERV_LITERAL_ADDRESS;
2045 if (!(newlist->flags & SERV_TYPE))
c4a7f90e 2046 ret_err(gen_err);
849a8357 2047 }
8ef5ada2
SK
2048 else if (option == LOPT_NO_REBIND)
2049 newlist->flags |= SERV_NO_REBIND;
849a8357
SK
2050
2051 if (!arg || !*arg)
2052 {
8ef5ada2
SK
2053 if (!(newlist->flags & SERV_NO_REBIND))
2054 newlist->flags |= SERV_NO_ADDR; /* no server */
2055 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 2056 ret_err(gen_err);
8ef5ada2
SK
2057 }
2058
2059 else if (strcmp(arg, "#") == 0)
2060 {
2061 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
849a8357 2062 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 2063 ret_err(gen_err);
849a8357
SK
2064 }
2065 else
2066 {
faafb3f7
SK
2067 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2068 if (err)
2069 ret_err(err);
849a8357
SK
2070 }
2071
f2621c7f
SK
2072 serv = newlist;
2073 while (serv->next)
849a8357 2074 {
f2621c7f
SK
2075 serv->next->flags = serv->flags;
2076 serv->next->addr = serv->addr;
2077 serv->next->source_addr = serv->source_addr;
faafb3f7 2078 strcpy(serv->next->interface, serv->interface);
f2621c7f 2079 serv = serv->next;
849a8357 2080 }
f2621c7f
SK
2081 serv->next = daemon->servers;
2082 daemon->servers = newlist;
849a8357
SK
2083 break;
2084 }
13d86c73
JD
2085
2086 case LOPT_IPSET: /* --ipset */
2087#ifndef HAVE_IPSET
2088 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2089 break;
2090#else
2091 {
2092 struct ipsets ipsets_head;
2093 struct ipsets *ipsets = &ipsets_head;
2094 int size;
2095 char *end;
2096 char **sets, **sets_pos;
2097 memset(ipsets, 0, sizeof(struct ipsets));
2098 unhide_metas(arg);
2099 if (arg && *arg == '/')
2100 {
2101 arg++;
2102 while ((end = split_chr(arg, '/')))
2103 {
2104 char *domain = NULL;
2105 /* elide leading dots - they are implied in the search algorithm */
2106 while (*arg == '.')
2107 arg++;
2108 /* # matches everything and becomes a zero length domain string */
2109 if (strcmp(arg, "#") == 0 || !*arg)
2110 domain = "";
2111 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2112 option = '?';
2113 ipsets->next = opt_malloc(sizeof(struct ipsets));
2114 ipsets = ipsets->next;
2115 memset(ipsets, 0, sizeof(struct ipsets));
2116 ipsets->domain = domain;
2117 arg = end;
2118 }
2119 }
2120 else
2121 {
2122 ipsets->next = opt_malloc(sizeof(struct ipsets));
2123 ipsets = ipsets->next;
2124 memset(ipsets, 0, sizeof(struct ipsets));
2125 ipsets->domain = "";
2126 }
2127 if (!arg || !*arg)
2128 {
2129 option = '?';
2130 break;
2131 }
2132 size = 2;
2133 for (end = arg; *end; ++end)
2134 if (*end == ',')
2135 ++size;
2136
2137 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2138
2139 do {
2140 end = split(arg);
2141 *sets_pos++ = opt_string_alloc(arg);
2142 arg = end;
2143 } while (end);
2144 *sets_pos = 0;
2145 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2146 ipsets->next->sets = sets;
2147 ipsets->next = daemon->ipsets;
2148 daemon->ipsets = ipsets_head.next;
2149
2150 break;
2151 }
2152#endif
849a8357 2153
f2621c7f 2154 case 'c': /* --cache-size */
849a8357
SK
2155 {
2156 int size;
2157
2158 if (!atoi_check(arg, &size))
c4a7f90e 2159 ret_err(gen_err);
849a8357
SK
2160 else
2161 {
2162 /* zero is OK, and means no caching. */
2163
2164 if (size < 0)
2165 size = 0;
2166 else if (size > 10000)
2167 size = 10000;
2168
2169 daemon->cachesize = size;
2170 }
2171 break;
2172 }
2173
f2621c7f 2174 case 'p': /* --port */
1ad24ae1 2175 if (!atoi_check16(arg, &daemon->port))
c4a7f90e 2176 ret_err(gen_err);
849a8357 2177 break;
208b65c5 2178
1a6bca81 2179 case LOPT_MINPORT: /* --min-port */
1ad24ae1 2180 if (!atoi_check16(arg, &daemon->min_port))
c4a7f90e 2181 ret_err(gen_err);
1a6bca81
SK
2182 break;
2183
f2621c7f 2184 case '0': /* --dns-forward-max */
208b65c5 2185 if (!atoi_check(arg, &daemon->ftabsize))
c4a7f90e 2186 ret_err(gen_err);
208b65c5
SK
2187 break;
2188
f2621c7f
SK
2189 case LOPT_MAX_LOGS: /* --log-async */
2190 daemon->max_logs = LOG_MAX; /* default */
2191 if (arg && !atoi_check(arg, &daemon->max_logs))
c4a7f90e 2192 ret_err(gen_err);
f2621c7f
SK
2193 else if (daemon->max_logs > 100)
2194 daemon->max_logs = 100;
2195 break;
2196
2197 case 'P': /* --edns-packet-max */
849a8357
SK
2198 {
2199 int i;
2200 if (!atoi_check(arg, &i))
c4a7f90e 2201 ret_err(gen_err);
849a8357
SK
2202 daemon->edns_pktsz = (unsigned short)i;
2203 break;
2204 }
2205
f2621c7f 2206 case 'Q': /* --query-port */
1ad24ae1 2207 if (!atoi_check16(arg, &daemon->query_port))
c4a7f90e 2208 ret_err(gen_err);
1a6bca81
SK
2209 /* if explicitly set to zero, use single OS ephemeral port
2210 and disable random ports */
2211 if (daemon->query_port == 0)
2212 daemon->osport = 1;
849a8357
SK
2213 break;
2214
824af85b
SK
2215 case 'T': /* --local-ttl */
2216 case LOPT_NEGTTL: /* --neg-ttl */
8ef5ada2 2217 case LOPT_MAXTTL: /* --max-ttl */
1d860415 2218 case LOPT_MAXCTTL: /* --max-cache-ttl */
4f7b304f 2219 case LOPT_AUTHTTL: /* --auth-ttl */
849a8357
SK
2220 {
2221 int ttl;
2222 if (!atoi_check(arg, &ttl))
c4a7f90e 2223 ret_err(gen_err);
824af85b
SK
2224 else if (option == LOPT_NEGTTL)
2225 daemon->neg_ttl = (unsigned long)ttl;
8ef5ada2
SK
2226 else if (option == LOPT_MAXTTL)
2227 daemon->max_ttl = (unsigned long)ttl;
1d860415
SK
2228 else if (option == LOPT_MAXCTTL)
2229 daemon->max_cache_ttl = (unsigned long)ttl;
4f7b304f
SK
2230 else if (option == LOPT_AUTHTTL)
2231 daemon->auth_ttl = (unsigned long)ttl;
849a8357
SK
2232 else
2233 daemon->local_ttl = (unsigned long)ttl;
2234 break;
2235 }
2236
7622fc06 2237#ifdef HAVE_DHCP
f2621c7f 2238 case 'X': /* --dhcp-lease-max */
849a8357 2239 if (!atoi_check(arg, &daemon->dhcp_max))
c4a7f90e 2240 ret_err(gen_err);
849a8357 2241 break;
7622fc06 2242#endif
849a8357 2243
7622fc06 2244#ifdef HAVE_TFTP
f2621c7f 2245 case LOPT_TFTP_MAX: /* --tftp-max */
832af0ba 2246 if (!atoi_check(arg, &daemon->tftp_max))
c4a7f90e 2247 ret_err(gen_err);
832af0ba
SK
2248 break;
2249
824af85b 2250 case LOPT_PREFIX: /* --tftp-prefix */
8ef5ada2
SK
2251 comma = split(arg);
2252 if (comma)
2253 {
2254 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2255 new->interface = opt_string_alloc(comma);
2256 new->prefix = opt_string_alloc(arg);
2257 new->next = daemon->if_prefix;
2258 daemon->if_prefix = new;
2259 }
2260 else
2261 daemon->tftp_prefix = opt_string_alloc(arg);
832af0ba
SK
2262 break;
2263
824af85b
SK
2264 case LOPT_TFTPPORTS: /* --tftp-port-range */
2265 if (!(comma = split(arg)) ||
1ad24ae1
SK
2266 !atoi_check16(arg, &daemon->start_tftp_port) ||
2267 !atoi_check16(comma, &daemon->end_tftp_port))
c4a7f90e 2268 ret_err(_("bad port range"));
824af85b
SK
2269
2270 if (daemon->start_tftp_port > daemon->end_tftp_port)
2271 {
2272 int tmp = daemon->start_tftp_port;
2273 daemon->start_tftp_port = daemon->end_tftp_port;
2274 daemon->end_tftp_port = tmp;
2275 }
2276
2277 break;
7622fc06 2278#endif
824af85b 2279
f2621c7f 2280 case LOPT_BRIDGE: /* --bridge-interface */
832af0ba 2281 {
824af85b 2282 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
316e2730 2283 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
c4a7f90e 2284 ret_err(_("bad bridge-interface"));
832af0ba 2285
316e2730 2286 strcpy(new->iface, arg);
832af0ba
SK
2287 new->alias = NULL;
2288 new->next = daemon->bridges;
2289 daemon->bridges = new;
2290
2291 do {
f2621c7f
SK
2292 arg = comma;
2293 comma = split(arg);
316e2730 2294 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
832af0ba 2295 {
824af85b 2296 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
832af0ba
SK
2297 b->next = new->alias;
2298 new->alias = b;
316e2730 2299 strcpy(b->iface, arg);
832af0ba
SK
2300 }
2301 } while (comma);
2302
2303 break;
2304 }
832af0ba 2305
7622fc06 2306#ifdef HAVE_DHCP
f2621c7f 2307 case 'F': /* --dhcp-range */
849a8357
SK
2308 {
2309 int k, leasepos = 2;
8445f5d2 2310 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
824af85b 2311 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
849a8357 2312
52b92f4d 2313 memset (new, 0, sizeof(*new));
849a8357 2314 new->lease_time = DEFLEASE;
52b92f4d 2315
849a8357
SK
2316 if (!arg)
2317 {
2318 option = '?';
2319 break;
2320 }
2321
2322 while(1)
2323 {
2324 for (cp = arg; *cp; cp++)
52b92f4d
SK
2325 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2326 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2327 (*cp >='0' && *cp <= '9')))
849a8357
SK
2328 break;
2329
f2621c7f 2330 if (*cp != ',' && (comma = split(arg)))
849a8357 2331 {
8bc4cece 2332 if (is_tag_prefix(arg))
9e4abcb5 2333 {
824af85b
SK
2334 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2335 tt->net = opt_string_alloc(arg+4);
849a8357
SK
2336 tt->next = new->filter;
2337 new->filter = tt;
9e4abcb5
SK
2338 }
2339 else
2340 {
849a8357 2341 if (new->netid.net)
c4a7f90e 2342 ret_err(_("only one tag allowed"));
8ef5ada2
SK
2343 else if (strstr(arg, "set:") == arg)
2344 new->netid.net = opt_string_alloc(arg+4);
9e4abcb5 2345 else
824af85b 2346 new->netid.net = opt_string_alloc(arg);
9e4abcb5 2347 }
f2621c7f 2348 arg = comma;
9e4abcb5 2349 }
849a8357 2350 else
9e4abcb5 2351 {
849a8357 2352 a[0] = arg;
9e4abcb5
SK
2353 break;
2354 }
849a8357
SK
2355 }
2356
1f776932 2357 for (k = 1; k < 8; k++)
f2621c7f
SK
2358 if (!(a[k] = split(a[k-1])))
2359 break;
849a8357 2360
52b92f4d 2361 if (k < 2)
c4a7f90e
SK
2362 ret_err(_("bad dhcp-range"));
2363
2364 if (inet_pton(AF_INET, a[0], &new->start))
849a8357 2365 {
52b92f4d
SK
2366 new->next = daemon->dhcp;
2367 daemon->dhcp = new;
30cd9666 2368 new->end = new->start;
52b92f4d 2369 if (strcmp(a[1], "static") == 0)
30cd9666 2370 new->flags |= CONTEXT_STATIC;
52b92f4d 2371 else if (strcmp(a[1], "proxy") == 0)
30cd9666
SK
2372 new->flags |= CONTEXT_PROXY;
2373 else if (!inet_pton(AF_INET, a[1], &new->end))
c4a7f90e 2374 ret_err(_("bad dhcp-range"));
52b92f4d
SK
2375
2376 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2377 {
2378 struct in_addr tmp = new->start;
2379 new->start = new->end;
2380 new->end = tmp;
2381 }
2382
c4a7f90e 2383 if (k >= 3 && strchr(a[2], '.') &&
ddd9a6b4 2384 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
52b92f4d
SK
2385 {
2386 new->flags |= CONTEXT_NETMASK;
2387 leasepos = 3;
2388 if (!is_same_net(new->start, new->end, new->netmask))
c4a7f90e 2389 ret_err(_("inconsistent DHCP range"));
52b92f4d
SK
2390 }
2391
2392 if (k >= 4 && strchr(a[3], '.') &&
ddd9a6b4 2393 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
52b92f4d
SK
2394 {
2395 new->flags |= CONTEXT_BRDCAST;
2396 leasepos = 4;
2397 }
849a8357 2398 }
52b92f4d
SK
2399#ifdef HAVE_DHCP6
2400 else if (inet_pton(AF_INET6, a[0], &new->start6))
849a8357 2401 {
52b92f4d 2402 new->prefix = 64; /* default */
30cd9666 2403 new->end6 = new->start6;
819ff4dd
SK
2404
2405 /* dhcp-range=:: enables DHCP stateless on any interface */
2406 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6))
2407 new->prefix = 0;
2408
30cd9666 2409 for (leasepos = 1; leasepos < k; leasepos++)
801ca9a7 2410 {
30cd9666
SK
2411 if (strcmp(a[leasepos], "static") == 0)
2412 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2413 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
1f776932 2414 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
30cd9666 2415 else if (strcmp(a[leasepos], "ra-names") == 0)
1f776932 2416 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
30cd9666 2417 else if (strcmp(a[leasepos], "ra-stateless") == 0)
1f776932 2418 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
30cd9666
SK
2419 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2420 new->flags |= CONTEXT_DHCP;
1f776932
SK
2421 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2422 {
2423 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2424 new->flags |= CONTEXT_TEMPLATE;
2425 }
921360ce
SK
2426 else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
2427 {
2428 new->template_interface = opt_string_alloc(a[leasepos] + 19);
2429 new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
2430 }
30cd9666
SK
2431 else
2432 break;
801ca9a7 2433 }
52b92f4d 2434
1f776932
SK
2435 new->next = daemon->dhcp6;
2436 daemon->dhcp6 = new;
2437
52b92f4d 2438 /* bare integer < 128 is prefix value */
c4a7f90e 2439 if (leasepos < k)
52b92f4d
SK
2440 {
2441 int pref;
30cd9666 2442 for (cp = a[leasepos]; *cp; cp++)
52b92f4d
SK
2443 if (!(*cp >= '0' && *cp <= '9'))
2444 break;
30cd9666 2445 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
52b92f4d
SK
2446 {
2447 new->prefix = pref;
30cd9666 2448 leasepos++;
1f776932
SK
2449 if (new->prefix != 64)
2450 {
2451 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2452 ret_err(_("prefix must be exactly 64 for RA subnets"));
2453 else if (new->template_interface)
2454 ret_err(_("prefix must be exactly 64 for subnet constructors"));
2455 }
2456 if (new->prefix < 64)
c4a7f90e 2457 ret_err(_("prefix must be at least 64"));
52b92f4d
SK
2458 }
2459 }
30cd9666 2460
c4a7f90e
SK
2461 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2462 ret_err(_("inconsistent DHCPv6 range"));
66409193
SK
2463
2464 if (new->flags & CONTEXT_TEMPLATE)
2465 {
2466 struct in6_addr zero;
2467 memset(&zero, 0, sizeof(zero));
2468 if (!is_same_net6(&zero, &new->start6, new->prefix))
2469 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2470 }
2471
c4a7f90e 2472 if (addr6part(&new->start6) > addr6part(&new->end6))
52b92f4d
SK
2473 {
2474 struct in6_addr tmp = new->start6;
2475 new->start6 = new->end6;
2476 new->end6 = tmp;
2477 }
849a8357 2478 }
52b92f4d 2479#endif
d9ee9c08
SK
2480 else
2481 ret_err(_("bad dhcp-range"));
849a8357 2482
30cd9666 2483 if (leasepos < k)
849a8357
SK
2484 {
2485 if (strcmp(a[leasepos], "infinite") == 0)
2486 new->lease_time = 0xffffffff;
c8257540
SK
2487 else if (strcmp(a[leasepos], "deprecated") == 0)
2488 new->flags |= CONTEXT_DEPRECATE;
849a8357 2489 else
9e4abcb5 2490 {
849a8357
SK
2491 int fac = 1;
2492 if (strlen(a[leasepos]) > 0)
36717eee 2493 {
849a8357 2494 switch (a[leasepos][strlen(a[leasepos]) - 1])
36717eee 2495 {
42243214
SK
2496 case 'w':
2497 case 'W':
2498 fac *= 7;
2499 /* fall through */
849a8357
SK
2500 case 'd':
2501 case 'D':
2502 fac *= 24;
2503 /* fall though */
2504 case 'h':
2505 case 'H':
2506 fac *= 60;
2507 /* fall through */
2508 case 'm':
2509 case 'M':
2510 fac *= 60;
2511 /* fall through */
2512 case 's':
2513 case 'S':
f2621c7f 2514 a[leasepos][strlen(a[leasepos]) - 1] = 0;
9e4abcb5 2515 }
849a8357 2516
be37986a
SK
2517 for (cp = a[leasepos]; *cp; cp++)
2518 if (!(*cp >= '0' && *cp <= '9'))
2519 break;
2520
54dae552 2521 if (*cp || (leasepos+1 < k))
be37986a
SK
2522 ret_err(_("bad dhcp-range"));
2523
849a8357
SK
2524 new->lease_time = atoi(a[leasepos]) * fac;
2525 /* Leases of a minute or less confuse
2526 some clients, notably Apple's */
2527 if (new->lease_time < 120)
2528 new->lease_time = 120;
9e4abcb5 2529 }
9e4abcb5 2530 }
849a8357
SK
2531 }
2532 break;
2533 }
5aabfc78 2534
5aabfc78 2535 case LOPT_BANK:
f2621c7f 2536 case 'G': /* --dhcp-host */
849a8357 2537 {
f2621c7f 2538 int j, k = 0;
3e8ed78b 2539 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
5aabfc78 2540 struct dhcp_config *new;
849a8357
SK
2541 struct in_addr in;
2542
824af85b
SK
2543 new = opt_malloc(sizeof(struct dhcp_config));
2544
849a8357 2545 new->next = daemon->dhcp_conf;
9009d746
SK
2546 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2547 new->hwaddr = NULL;
8ef5ada2
SK
2548 new->netid = NULL;
2549
849a8357 2550 if ((a[0] = arg))
3e8ed78b 2551 for (k = 1; k < 7; k++)
f2621c7f
SK
2552 if (!(a[k] = split(a[k-1])))
2553 break;
849a8357
SK
2554
2555 for (j = 0; j < k; j++)
2556 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2557 {
2558 char *arg = a[j];
2559
2560 if ((arg[0] == 'i' || arg[0] == 'I') &&
2561 (arg[1] == 'd' || arg[1] == 'D') &&
2562 arg[2] == ':')
2563 {
2564 if (arg[3] == '*')
2565 new->flags |= CONFIG_NOCLID;
2566 else
3d8df260 2567 {
849a8357
SK
2568 int len;
2569 arg += 3; /* dump id: */
2570 if (strchr(arg, ':'))
2571 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2572 else
5aabfc78
SK
2573 {
2574 unhide_metas(arg);
2575 len = (int) strlen(arg);
2576 }
2577
28866e95 2578 if (len == -1)
9f7f3b12 2579
c4a7f90e 2580 ret_err(_("bad hex constant"));
28866e95 2581 else if ((new->clid = opt_malloc(len)))
5aabfc78
SK
2582 {
2583 new->flags |= CONFIG_CLID;
2584 new->clid_len = len;
2585 memcpy(new->clid, arg, len);
2586 }
3d8df260 2587 }
849a8357 2588 }
8ef5ada2
SK
2589 /* dhcp-host has strange backwards-compat needs. */
2590 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
849a8357 2591 {
8ef5ada2
SK
2592 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2593 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2594 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2595 newlist->next = new->netid;
2596 new->netid = newlist;
2597 newlist->list = newtag;
2598 strcpy(newtag->net, arg+4);
2599 unhide_metas(newtag->net);
849a8357 2600 }
7de060b0 2601 else if (strstr(arg, "tag:") == arg)
c4a7f90e 2602 ret_err(_("cannot match tags in --dhcp-host"));
4cb1b320
SK
2603#ifdef HAVE_DHCP6
2604 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2605 {
2606 arg[strlen(arg)-1] = 0;
2607 arg++;
2608
2609 if (!inet_pton(AF_INET6, arg, &new->addr6))
c4a7f90e 2610 ret_err(_("bad IPv6 address"));
30393100
SK
2611
2612 for (i= 0; i < 8; i++)
2613 if (new->addr6.s6_addr[i] != 0)
2614 break;
2615
2616 /* set WILDCARD if network part all zeros */
2617 if (i == 8)
2618 new->flags |= CONFIG_WILDCARD;
4cb1b320
SK
2619
2620 new->flags |= CONFIG_ADDR6;
2621 }
2622#endif
7de060b0 2623 else
849a8357 2624 {
9009d746 2625 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
28866e95
SK
2626 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2627 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
c4a7f90e 2628 ret_err(_("bad hex constant"));
28866e95
SK
2629 else
2630 {
2631
2632 newhw->next = new->hwaddr;
2633 new->hwaddr = newhw;
2634 }
849a8357
SK
2635 }
2636 }
ddd9a6b4 2637 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
849a8357 2638 {
c4a7f90e
SK
2639 struct dhcp_config *configs;
2640
849a8357
SK
2641 new->addr = in;
2642 new->flags |= CONFIG_ADDR;
c4a7f90e
SK
2643
2644 /* If the same IP appears in more than one host config, then DISCOVER
2645 for one of the hosts will get the address, but REQUEST will be NAKed,
2646 since the address is reserved by the other one -> protocol loop. */
2647 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2648 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2649 {
2650 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2651 return 0;
2652 }
849a8357
SK
2653 }
2654 else
2655 {
2656 char *cp, *lastp = NULL, last = 0;
2657 int fac = 1;
2658
2659 if (strlen(a[j]) > 1)
2660 {
2661 lastp = a[j] + strlen(a[j]) - 1;
2662 last = *lastp;
2663 switch (last)
9e4abcb5 2664 {
42243214
SK
2665 case 'w':
2666 case 'W':
2667 fac *= 7;
2668 /* fall through */
849a8357
SK
2669 case 'd':
2670 case 'D':
2671 fac *= 24;
2672 /* fall through */
2673 case 'h':
2674 case 'H':
2675 fac *= 60;
2676 /* fall through */
2677 case 'm':
2678 case 'M':
2679 fac *= 60;
2680 /* fall through */
2681 case 's':
2682 case 'S':
2683 *lastp = 0;
9e4abcb5 2684 }
849a8357
SK
2685 }
2686
2687 for (cp = a[j]; *cp; cp++)
572b41eb 2688 if (!isdigit((unsigned char)*cp) && *cp != ' ')
849a8357
SK
2689 break;
2690
2691 if (*cp)
2692 {
2693 if (lastp)
2694 *lastp = last;
2695 if (strcmp(a[j], "infinite") == 0)
33820b7e 2696 {
849a8357
SK
2697 new->lease_time = 0xffffffff;
2698 new->flags |= CONFIG_TIME;
33820b7e 2699 }
849a8357
SK
2700 else if (strcmp(a[j], "ignore") == 0)
2701 new->flags |= CONFIG_DISABLE;
9e4abcb5
SK
2702 else
2703 {
1f15b81d
SK
2704 if (!(new->hostname = canonicalise_opt(a[j])) ||
2705 !legal_hostname(new->hostname))
c4a7f90e
SK
2706 ret_err(_("bad DHCP host name"));
2707
2708 new->flags |= CONFIG_NAME;
2709 new->domain = strip_hostname(new->hostname);
9e4abcb5 2710 }
849a8357
SK
2711 }
2712 else
2713 {
2714 new->lease_time = atoi(a[j]) * fac;
2715 /* Leases of a minute or less confuse
2716 some clients, notably Apple's */
2717 if (new->lease_time < 120)
2718 new->lease_time = 120;
2719 new->flags |= CONFIG_TIME;
2720 }
2721 }
2722
5aabfc78 2723 daemon->dhcp_conf = new;
849a8357
SK
2724 break;
2725 }
8ef5ada2
SK
2726
2727 case LOPT_TAG_IF: /* --tag-if */
2728 {
2729 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2730
2731 new->tag = NULL;
2732 new->set = NULL;
2733 new->next = NULL;
2734
2735 /* preserve order */
2736 if (!daemon->tag_if)
2737 daemon->tag_if = new;
2738 else
2739 {
2740 struct tag_if *tmp;
2741 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2742 tmp->next = new;
2743 }
2744
2745 while (arg)
2746 {
2747 size_t len;
2748
2749 comma = split(arg);
2750 len = strlen(arg);
2751
2752 if (len < 5)
2753 {
2754 new->set = NULL;
2755 break;
2756 }
2757 else
2758 {
2759 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2760 newtag->net = opt_malloc(len - 3);
2761 strcpy(newtag->net, arg+4);
2762 unhide_metas(newtag->net);
2763
2764 if (strstr(arg, "set:") == arg)
2765 {
2766 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2767 newlist->next = new->set;
2768 new->set = newlist;
2769 newlist->list = newtag;
2770 }
2771 else if (strstr(arg, "tag:") == arg)
2772 {
2773 newtag->next = new->tag;
2774 new->tag = newtag;
2775 }
2776 else
2777 {
2778 new->set = NULL;
4dc9c657 2779 free(newtag);
8ef5ada2
SK
2780 break;
2781 }
2782 }
2783
2784 arg = comma;
2785 }
2786
2787 if (!new->set)
c4a7f90e 2788 ret_err(_("bad tag-if"));
8ef5ada2
SK
2789
2790 break;
2791 }
2792
849a8357 2793
73a08a24
SK
2794 case 'O': /* --dhcp-option */
2795 case LOPT_FORCE: /* --dhcp-option-force */
824af85b 2796 case LOPT_OPTS:
73a08a24 2797 case LOPT_MATCH: /* --dhcp-match */
c4a7f90e
SK
2798 return parse_dhcp_opt(errstr, arg,
2799 option == LOPT_FORCE ? DHOPT_FORCE :
2800 (option == LOPT_MATCH ? DHOPT_MATCH :
2801 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2802
f2621c7f 2803 case 'M': /* --dhcp-boot */
849a8357
SK
2804 {
2805 struct dhcp_netid *id = NULL;
8ef5ada2 2806 while (is_tag_prefix(arg))
849a8357 2807 {
824af85b 2808 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
849a8357
SK
2809 newid->next = id;
2810 id = newid;
f2621c7f 2811 comma = split(arg);
824af85b 2812 newid->net = opt_string_alloc(arg+4);
849a8357
SK
2813 arg = comma;
2814 };
2815
2816 if (!arg)
c4a7f90e 2817 ret_err(gen_err);
849a8357
SK
2818 else
2819 {
7de060b0 2820 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
849a8357 2821 struct in_addr dhcp_next_server;
c4a7f90e 2822 struct dhcp_boot *new;
f2621c7f 2823 comma = split(arg);
824af85b 2824 dhcp_file = opt_string_alloc(arg);
849a8357
SK
2825 dhcp_next_server.s_addr = 0;
2826 if (comma)
a84fa1d0 2827 {
849a8357 2828 arg = comma;
f2621c7f 2829 comma = split(arg);
824af85b 2830 dhcp_sname = opt_string_alloc(arg);
849a8357 2831 if (comma)
a84fa1d0 2832 {
849a8357 2833 unhide_metas(comma);
ddd9a6b4
SK
2834 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2835 {
2836 /*
2837 * The user may have specified the tftp hostname here.
2838 * save it so that it can be resolved/looked up during
2839 * actual dhcp_reply().
2840 */
2841
2842 tftp_sname = opt_string_alloc(comma);
2843 dhcp_next_server.s_addr = 0;
2844 }
a84fa1d0 2845 }
a84fa1d0 2846 }
c4a7f90e
SK
2847
2848 new = opt_malloc(sizeof(struct dhcp_boot));
2849 new->file = dhcp_file;
2850 new->sname = dhcp_sname;
2851 new->tftp_sname = tftp_sname;
2852 new->next_server = dhcp_next_server;
2853 new->netid = id;
2854 new->next = daemon->boot_config;
2855 daemon->boot_config = new;
849a8357 2856 }
ddd9a6b4 2857
849a8357
SK
2858 break;
2859 }
7622fc06
SK
2860
2861 case LOPT_PXE_PROMT: /* --pxe-prompt */
2862 {
2863 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2864 int timeout;
2865
2866 new->netid = NULL;
2867 new->opt = 10; /* PXE_MENU_PROMPT */
2868
8ef5ada2
SK
2869 while (is_tag_prefix(arg))
2870 {
7622fc06
SK
2871 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2872 comma = split(arg);
2873 nn->next = new->netid;
2874 new->netid = nn;
2875 nn->net = opt_string_alloc(arg+4);
2876 arg = comma;
2877 }
2878
2879 if (!arg)
c4a7f90e 2880 ret_err(gen_err);
7622fc06
SK
2881 else
2882 {
2883 comma = split(arg);
2884 unhide_metas(arg);
2885 new->len = strlen(arg) + 1;
2886 new->val = opt_malloc(new->len);
2887 memcpy(new->val + 1, arg, new->len - 1);
2888
2889 new->u.vendor_class = (unsigned char *)"PXEClient";
2890 new->flags = DHOPT_VENDOR;
2891
2892 if (comma && atoi_check(comma, &timeout))
2893 *(new->val) = timeout;
2894 else
2895 *(new->val) = 255;
2896
2897 new->next = daemon->dhcp_opts;
2898 daemon->dhcp_opts = new;
1f15b81d 2899 daemon->enable_pxe = 1;
7622fc06
SK
2900 }
2901
2902 break;
2903 }
2904
2905 case LOPT_PXE_SERV: /* --pxe-service */
2906 {
2907 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2908 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2909 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2910 static int boottype = 32768;
2911
2912 new->netid = NULL;
751d6f4a 2913 new->sname = NULL;
7622fc06
SK
2914 new->server.s_addr = 0;
2915
8ef5ada2 2916 while (is_tag_prefix(arg))
7622fc06
SK
2917 {
2918 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2919 comma = split(arg);
2920 nn->next = new->netid;
2921 new->netid = nn;
2922 nn->net = opt_string_alloc(arg+4);
2923 arg = comma;
2924 }
2925
2926 if (arg && (comma = split(arg)))
2927 {
2928 for (i = 0; CSA[i]; i++)
2929 if (strcasecmp(CSA[i], arg) == 0)
2930 break;
2931
2932 if (CSA[i] || atoi_check(arg, &i))
2933 {
2934 arg = comma;
2935 comma = split(arg);
2936
2937 new->CSA = i;
2938 new->menu = opt_string_alloc(arg);
2939
316e2730
SK
2940 if (!comma)
2941 {
2942 new->type = 0; /* local boot */
2943 new->basename = NULL;
2944 }
2945 else
7622fc06
SK
2946 {
2947 arg = comma;
2948 comma = split(arg);
2949 if (atoi_check(arg, &i))
2950 {
2951 new->type = i;
2952 new->basename = NULL;
2953 }
2954 else
2955 {
2956 new->type = boottype++;
2957 new->basename = opt_string_alloc(arg);
2958 }
2959
751d6f4a
SK
2960 if (comma)
2961 {
2962 if (!inet_pton(AF_INET, comma, &new->server))
2963 {
2964 new->server.s_addr = 0;
2965 new->sname = opt_string_alloc(comma);
2966 }
2967
2968 }
7622fc06 2969 }
751d6f4a 2970
316e2730
SK
2971 /* Order matters */
2972 new->next = NULL;
2973 if (!daemon->pxe_services)
2974 daemon->pxe_services = new;
2975 else
2976 {
2977 struct pxe_service *s;
2978 for (s = daemon->pxe_services; s->next; s = s->next);
2979 s->next = new;
2980 }
2981
2982 daemon->enable_pxe = 1;
2983 break;
2984
7622fc06
SK
2985 }
2986 }
2987
c4a7f90e 2988 ret_err(gen_err);
7622fc06
SK
2989 }
2990
f2621c7f 2991 case '4': /* --dhcp-mac */
849a8357 2992 {
f2621c7f 2993 if (!(comma = split(arg)))
c4a7f90e 2994 ret_err(gen_err);
849a8357
SK
2995 else
2996 {
824af85b 2997 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
8ef5ada2 2998 new->netid.net = opt_string_alloc(set_prefix(arg));
f2621c7f
SK
2999 unhide_metas(comma);
3000 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
28866e95 3001 if (new->hwaddr_len == -1)
c4a7f90e 3002 ret_err(gen_err);
28866e95
SK
3003 else
3004 {
3005 new->next = daemon->dhcp_macs;
3006 daemon->dhcp_macs = new;
3007 }
849a8357
SK
3008 }
3009 }
3010 break;
c630924d
SK
3011
3012#ifdef OPTION6_PREFIX_CLASS
3013 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3014 {
3015 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3016
3017 if (!(comma = split(arg)) ||
3018 !atoi_check16(comma, &new->class))
3019 ret_err(gen_err);
3020
3021 new->tag.net = opt_string_alloc(set_prefix(arg));
3022 new->next = daemon->prefix_classes;
3023 daemon->prefix_classes = new;
3024
3025 break;
3026 }
3027#endif
3028
3029
f2621c7f
SK
3030 case 'U': /* --dhcp-vendorclass */
3031 case 'j': /* --dhcp-userclass */
3032 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3033 case LOPT_REMOTE: /* --dhcp-remoteid */
3034 case LOPT_SUBSCR: /* --dhcp-subscrid */
849a8357 3035 {
c4a7f90e
SK
3036 unsigned char *p;
3037 int dig = 0;
3038 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3039
3040 if (!(comma = split(arg)))
3041 ret_err(gen_err);
3042
3043 new->netid.net = opt_string_alloc(set_prefix(arg));
3044 /* check for hex string - must digits may include : must not have nothing else,
3045 only allowed for agent-options. */
3046
3047 arg = comma;
3048 if ((comma = split(arg)))
3049 {
3050 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3051 ret_err(gen_err);
3052 else
3053 new->enterprise = atoi(arg+11);
3054 }
3055 else
3056 comma = arg;
3057
3058 for (p = (unsigned char *)comma; *p; p++)
3059 if (isxdigit(*p))
3060 dig = 1;
3061 else if (*p != ':')
3062 break;
3063 unhide_metas(comma);
3064 if (option == 'U' || option == 'j' || *p || !dig)
3065 {
3066 new->len = strlen(comma);
3067 new->data = opt_malloc(new->len);
3068 memcpy(new->data, comma, new->len);
3069 }
3070 else
3071 {
3072 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3073 new->data = opt_malloc(new->len);
3074 memcpy(new->data, comma, new->len);
3075 }
3076
3077 switch (option)
3078 {
3079 case 'j':
3080 new->match_type = MATCH_USER;
3081 break;
3082 case 'U':
3083 new->match_type = MATCH_VENDOR;
3084 break;
3085 case LOPT_CIRCUIT:
3086 new->match_type = MATCH_CIRCUIT;
3087 break;
3088 case LOPT_REMOTE:
3089 new->match_type = MATCH_REMOTE;
3090 break;
3091 case LOPT_SUBSCR:
3092 new->match_type = MATCH_SUBSCRIBER;
3093 break;
3094 }
3095 new->next = daemon->dhcp_vendors;
3096 daemon->dhcp_vendors = new;
824af85b 3097
c4a7f90e 3098 break;
849a8357
SK
3099 }
3100
9e038946
SK
3101 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3102 if (!arg)
3103 {
3104 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3105 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3106 }
3107 else
3108 {
3109 comma = split(arg);
1ad24ae1
SK
3110 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3111 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
c4a7f90e 3112 ret_err(_("invalid port number"));
9e038946
SK
3113 if (!comma)
3114 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3115 }
3116 break;
3117
824af85b
SK
3118 case 'J': /* --dhcp-ignore */
3119 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3120 case LOPT_BROADCAST: /* --dhcp-broadcast */
8ef5ada2
SK
3121 case '3': /* --bootp-dynamic */
3122 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
849a8357 3123 {
824af85b 3124 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
849a8357 3125 struct dhcp_netid *list = NULL;
832af0ba
SK
3126 if (option == 'J')
3127 {
3128 new->next = daemon->dhcp_ignore;
3129 daemon->dhcp_ignore = new;
3130 }
824af85b
SK
3131 else if (option == LOPT_BROADCAST)
3132 {
3133 new->next = daemon->force_broadcast;
3134 daemon->force_broadcast = new;
3135 }
9009d746
SK
3136 else if (option == '3')
3137 {
3138 new->next = daemon->bootp_dynamic;
3139 daemon->bootp_dynamic = new;
3140 }
8ef5ada2
SK
3141 else if (option == LOPT_GEN_NAMES)
3142 {
3143 new->next = daemon->dhcp_gen_names;
3144 daemon->dhcp_gen_names = new;
3145 }
832af0ba
SK
3146 else
3147 {
3148 new->next = daemon->dhcp_ignore_names;
3149 daemon->dhcp_ignore_names = new;
3150 }
3151
3152 while (arg) {
824af85b 3153 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
f2621c7f 3154 comma = split(arg);
849a8357
SK
3155 member->next = list;
3156 list = member;
8ef5ada2 3157 if (is_tag_prefix(arg))
9009d746
SK
3158 member->net = opt_string_alloc(arg+4);
3159 else
3160 member->net = opt_string_alloc(arg);
849a8357 3161 arg = comma;
832af0ba 3162 }
849a8357
SK
3163
3164 new->list = list;
3165 break;
3166 }
8ef5ada2
SK
3167
3168 case LOPT_PROXY: /* --dhcp-proxy */
3169 daemon->override = 1;
3170 while (arg) {
3171 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3172 comma = split(arg);
ddd9a6b4 3173 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
c4a7f90e 3174 ret_err(_("bad dhcp-proxy address"));
8ef5ada2
SK
3175 new->next = daemon->override_relays;
3176 daemon->override_relays = new;
3177 arg = comma;
3178 }
3179 break;
7622fc06 3180#endif
849a8357 3181
8b372704
SK
3182#ifdef HAVE_DHCP6
3183 case LOPT_DUID: /* --dhcp-duid */
3184 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
c4a7f90e 3185 ret_err(_("bad DUID"));
8b372704
SK
3186 else
3187 {
3188 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3189 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3190 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3191 }
3192 break;
3193#endif
3194
f2621c7f 3195 case 'V': /* --alias */
849a8357 3196 {
73a08a24 3197 char *dash, *a[3] = { NULL, NULL, NULL };
f2621c7f 3198 int k = 0;
73a08a24
SK
3199 struct doctor *new = opt_malloc(sizeof(struct doctor));
3200 new->next = daemon->doctors;
3201 daemon->doctors = new;
3202 new->mask.s_addr = 0xffffffff;
3203 new->end.s_addr = 0;
3204
849a8357
SK
3205 if ((a[0] = arg))
3206 for (k = 1; k < 3; k++)
3207 {
f2621c7f 3208 if (!(a[k] = split(a[k-1])))
849a8357 3209 break;
849a8357
SK
3210 unhide_metas(a[k]);
3211 }
849a8357 3212
73a08a24
SK
3213 dash = split_chr(a[0], '-');
3214
849a8357 3215 if ((k < 2) ||
ddd9a6b4
SK
3216 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3217 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
73a08a24 3218 option = '?';
849a8357
SK
3219
3220 if (k == 3)
ddd9a6b4 3221 inet_pton(AF_INET, a[2], &new->mask);
849a8357 3222
73a08a24 3223 if (dash &&
ddd9a6b4 3224 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
73a08a24
SK
3225 !is_same_net(new->in, new->end, new->mask) ||
3226 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
c4a7f90e 3227 ret_err(_("invalid alias range"));
849a8357
SK
3228
3229 break;
3230 }
3231
f2621c7f 3232 case LOPT_INTNAME: /* --interface-name */
832af0ba 3233 {
f2621c7f 3234 struct interface_name *new, **up;
1f15b81d
SK
3235 char *domain = NULL;
3236
f2621c7f
SK
3237 comma = split(arg);
3238
1f15b81d 3239 if (!comma || !(domain = canonicalise_opt(arg)))
c4a7f90e 3240 ret_err(_("bad interface name"));
1f15b81d 3241
824af85b 3242 new = opt_malloc(sizeof(struct interface_name));
f2621c7f 3243 new->next = NULL;
115ac3e4
SK
3244 new->addr4 = NULL;
3245#ifdef HAVE_IPV6
3246 new->addr6 = NULL;
3247#endif
f2621c7f
SK
3248 /* Add to the end of the list, so that first name
3249 of an interface is used for PTR lookups. */
824af85b 3250 for (up = &daemon->int_names; *up; up = &((*up)->next));
f2621c7f 3251 *up = new;
1f15b81d 3252 new->name = domain;
824af85b 3253 new->intr = opt_string_alloc(comma);
f2621c7f
SK
3254 break;
3255 }
9009d746
SK
3256
3257 case LOPT_CNAME: /* --cname */
3258 {
3259 struct cname *new;
c4a7f90e
SK
3260 char *alias;
3261 char *target;
3262
9009d746 3263 if (!(comma = split(arg)))
c4a7f90e
SK
3264 ret_err(gen_err);
3265
3266 alias = canonicalise_opt(arg);
3267 target = canonicalise_opt(comma);
3268
3269 if (!alias || !target)
3270 ret_err(_("bad CNAME"));
9009d746
SK
3271 else
3272 {
c4a7f90e
SK
3273 for (new = daemon->cnames; new; new = new->next)
3274 if (hostname_isequal(new->alias, arg))
3275 ret_err(_("duplicate CNAME"));
3276 new = opt_malloc(sizeof(struct cname));
3277 new->next = daemon->cnames;
3278 daemon->cnames = new;
3279 new->alias = alias;
3280 new->target = target;
9009d746 3281 }
c4a7f90e 3282
9009d746
SK
3283 break;
3284 }
f2621c7f
SK
3285
3286 case LOPT_PTR: /* --ptr-record */
3287 {
3288 struct ptr_record *new;
1f15b81d
SK
3289 char *dom, *target = NULL;
3290
f2621c7f
SK
3291 comma = split(arg);
3292
1f15b81d
SK
3293 if (!(dom = canonicalise_opt(arg)) ||
3294 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 3295 ret_err(_("bad PTR record"));
1f15b81d
SK
3296 else
3297 {
3298 new = opt_malloc(sizeof(struct ptr_record));
3299 new->next = daemon->ptr;
3300 daemon->ptr = new;
3301 new->name = dom;
3302 new->ptr = target;
3303 }
832af0ba
SK
3304 break;
3305 }
3306
1a6bca81
SK
3307 case LOPT_NAPTR: /* --naptr-record */
3308 {
3309 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3310 int k = 0;
3311 struct naptr *new;
3312 int order, pref;
1f15b81d 3313 char *name, *replace = NULL;
1a6bca81
SK
3314
3315 if ((a[0] = arg))
3316 for (k = 1; k < 7; k++)
3317 if (!(a[k] = split(a[k-1])))
3318 break;
3319
3320
3321 if (k < 6 ||
1f15b81d 3322 !(name = canonicalise_opt(a[0])) ||
1ad24ae1
SK
3323 !atoi_check16(a[1], &order) ||
3324 !atoi_check16(a[2], &pref) ||
1f15b81d 3325 (k == 7 && !(replace = canonicalise_opt(a[6]))))
c4a7f90e 3326 ret_err(_("bad NAPTR record"));
1a6bca81
SK
3327 else
3328 {
3329 new = opt_malloc(sizeof(struct naptr));
3330 new->next = daemon->naptr;
3331 daemon->naptr = new;
1f15b81d 3332 new->name = name;
1a6bca81
SK
3333 new->flags = opt_string_alloc(a[3]);
3334 new->services = opt_string_alloc(a[4]);
3335 new->regexp = opt_string_alloc(a[5]);
1f15b81d 3336 new->replace = replace;
1a6bca81
SK
3337 new->order = order;
3338 new->pref = pref;
3339 }
3340 break;
3341 }
9f7f3b12
SK
3342
3343 case LOPT_RR: /* dns-rr */
3344 {
3345 struct txt_record *new;
3346 size_t len;
3347 char *data;
3348 int val;
3349
3350 comma = split(arg);
3351 data = split(comma);
3352
3353 new = opt_malloc(sizeof(struct txt_record));
3354 new->next = daemon->rr;
3355 daemon->rr = new;
3356
3357 if (!atoi_check(comma, &val) ||
3358 !(new->name = canonicalise_opt(arg)) ||
51931b88 3359 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
c4a7f90e
SK
3360 ret_err(_("bad RR record"));
3361
9f7f3b12
SK
3362 new->class = val;
3363 new->len = 0;
3364
3365 if (data)
3366 {
3367 new->txt=opt_malloc(len);
3368 new->len = len;
3369 memcpy(new->txt, data, len);
3370 }
3371
3372 break;
3373 }
3374
f2621c7f 3375 case 'Y': /* --txt-record */
849a8357
SK
3376 {
3377 struct txt_record *new;
28866e95
SK
3378 unsigned char *p, *cnt;
3379 size_t len;
3380
3381 comma = split(arg);
3382
824af85b 3383 new = opt_malloc(sizeof(struct txt_record));
849a8357
SK
3384 new->next = daemon->txt;
3385 daemon->txt = new;
3386 new->class = C_IN;
849a8357 3387
1f15b81d 3388 if (!(new->name = canonicalise_opt(arg)))
c4a7f90e
SK
3389 ret_err(_("bad TXT record"));
3390
28866e95
SK
3391 len = comma ? strlen(comma) : 0;
3392 len += (len/255) + 1; /* room for extra counts */
3393 new->txt = p = opt_malloc(len);
3394
3395 cnt = p++;
3396 *cnt = 0;
3397
3398 while (comma && *comma)
3399 {
3400 unsigned char c = (unsigned char)*comma++;
3401
3402 if (c == ',' || *cnt == 255)
3403 {
3404 if (c != ',')
3405 comma--;
3406 cnt = p++;
3407 *cnt = 0;
3408 }
3409 else
3410 {
3411 *p++ = unhide_meta(c);
3412 (*cnt)++;
3413 }
3414 }
3415
3416 new->len = p - new->txt;
3417
849a8357
SK
3418 break;
3419 }
3420
f2621c7f 3421 case 'W': /* --srv-host */
849a8357
SK
3422 {
3423 int port = 1, priority = 0, weight = 0;
3424 char *name, *target = NULL;
3425 struct mx_srv_record *new;
3426
f2621c7f 3427 comma = split(arg);
849a8357 3428
1f15b81d 3429 if (!(name = canonicalise_opt(arg)))
c4a7f90e
SK
3430 ret_err(_("bad SRV record"));
3431
849a8357
SK
3432 if (comma)
3433 {
3434 arg = comma;
f2621c7f 3435 comma = split(arg);
c4a7f90e
SK
3436 if (!(target = canonicalise_opt(arg)))
3437 ret_err(_("bad SRV target"));
824af85b 3438
849a8357 3439 if (comma)
f6b7dc47 3440 {
849a8357 3441 arg = comma;
f2621c7f 3442 comma = split(arg);
1ad24ae1 3443 if (!atoi_check16(arg, &port))
c4a7f90e 3444 ret_err(_("invalid port number"));
824af85b 3445
f6b7dc47
SK
3446 if (comma)
3447 {
91dccd09 3448 arg = comma;
f2621c7f 3449 comma = split(arg);
1ad24ae1 3450 if (!atoi_check16(arg, &priority))
c4a7f90e 3451 ret_err(_("invalid priority"));
824af85b 3452
f6b7dc47
SK
3453 if (comma)
3454 {
91dccd09 3455 arg = comma;
f2621c7f 3456 comma = split(arg);
1ad24ae1 3457 if (!atoi_check16(arg, &weight))
c4a7f90e 3458 ret_err(_("invalid weight"));
f6b7dc47
SK
3459 }
3460 }
f6b7dc47 3461 }
849a8357
SK
3462 }
3463
824af85b 3464 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
3465 new->next = daemon->mxnames;
3466 daemon->mxnames = new;
3467 new->issrv = 1;
3468 new->name = name;
3469 new->target = target;
3470 new->srvport = port;
3471 new->priority = priority;
3472 new->weight = weight;
3473 break;
3474 }
7622fc06 3475
e759d426
SK
3476 case LOPT_HOST_REC: /* --host-record */
3477 {
3478 struct host_record *new = opt_malloc(sizeof(struct host_record));
3479 memset(new, 0, sizeof(struct host_record));
3480
3481 if (!arg || !(comma = split(arg)))
c4a7f90e
SK
3482 ret_err(_("Bad host-record"));
3483
3484 while (arg)
3485 {
3486 struct all_addr addr;
3487 if (inet_pton(AF_INET, arg, &addr))
3488 new->addr = addr.addr.addr4;
e759d426 3489#ifdef HAVE_IPV6
c4a7f90e
SK
3490 else if (inet_pton(AF_INET6, arg, &addr))
3491 new->addr6 = addr.addr.addr6;
e759d426 3492#endif
c4a7f90e
SK
3493 else
3494 {
3495 int nomem;
3496 char *canon = canonicalise(arg, &nomem);
3497 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3498 if (!canon)
3499 ret_err(_("Bad name in host-record"));
3500
3501 nl->name = canon;
3502 /* keep order, so that PTR record goes to first name */
3503 nl->next = NULL;
3504 if (!new->names)
3505 new->names = nl;
3506 else
3507 {
3508 struct name_list *tmp;
3509 for (tmp = new->names; tmp->next; tmp = tmp->next);
3510 tmp->next = nl;
3511 }
c4a7f90e 3512 }
e4807d8b
SK
3513
3514 arg = comma;
3515 comma = split(arg);
c4a7f90e 3516 }
e759d426
SK
3517
3518 /* Keep list order */
3519 if (!daemon->host_records_tail)
3520 daemon->host_records = new;
3521 else
3522 daemon->host_records_tail->next = new;
3523 new->next = NULL;
3524 daemon->host_records_tail = new;
3525 break;
3526 }
c4a7f90e 3527
7622fc06 3528 default:
c4a7f90e
SK
3529 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3530
849a8357 3531 }
824af85b 3532
c4a7f90e 3533 return 1;
849a8357
SK
3534}
3535
28866e95 3536static void read_file(char *file, FILE *f, int hard_opt)
849a8357 3537{
824af85b 3538 volatile int lineno = 0;
8ef5ada2 3539 char *buff = daemon->namebuff;
849a8357
SK
3540
3541 while (fgets(buff, MAXDNAME, f))
3542 {
611ebc5f
SK
3543 int white, i, option = hard_opt;
3544 char *errmess, *p, *arg = NULL, *start;
8ef5ada2 3545 size_t len;
832af0ba 3546
824af85b 3547 /* Memory allocation failure longjmps here if mem_recover == 1 */
611ebc5f 3548 if (option != 0)
824af85b
SK
3549 {
3550 if (setjmp(mem_jmp))
3551 continue;
3552 mem_recover = 1;
3553 }
3554
849a8357 3555 lineno++;
824af85b
SK
3556 errmess = NULL;
3557
849a8357
SK
3558 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3559 metacharacters get hidden also strip comments */
8ef5ada2 3560 for (white = 1, p = buff; *p; p++)
849a8357
SK
3561 {
3562 if (*p == '"')
3563 {
3564 memmove(p, p+1, strlen(p+1)+1);
8ef5ada2 3565
849a8357
SK
3566 for(; *p && *p != '"'; p++)
3567 {
5aabfc78 3568 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
849a8357
SK
3569 {
3570 if (p[1] == 't')
3571 p[1] = '\t';
3572 else if (p[1] == 'n')
3573 p[1] = '\n';
849a8357
SK
3574 else if (p[1] == 'b')
3575 p[1] = '\b';
3576 else if (p[1] == 'r')
3577 p[1] = '\r';
6b01084f
SK
3578 else if (p[1] == 'e') /* escape */
3579 p[1] = '\033';
849a8357
SK
3580 memmove(p, p+1, strlen(p+1)+1);
3581 }
3582 *p = hide_meta(*p);
3583 }
8ef5ada2
SK
3584
3585 if (*p == 0)
f2621c7f
SK
3586 {
3587 errmess = _("missing \"");
3588 goto oops;
3589 }
8ef5ada2
SK
3590
3591 memmove(p, p+1, strlen(p+1)+1);
849a8357 3592 }
f2621c7f 3593
8ef5ada2
SK
3594 if (isspace(*p))
3595 {
3596 *p = ' ';
3597 white = 1;
9e4abcb5 3598 }
8ef5ada2
SK
3599 else
3600 {
3601 if (white && *p == '#')
3602 {
3603 *p = 0;
3604 break;
3605 }
3606 white = 0;
3607 }
849a8357
SK
3608 }
3609
8ef5ada2
SK
3610
3611 /* strip leading spaces */
3612 for (start = buff; *start && *start == ' '; start++);
3613
3614 /* strip trailing spaces */
3615 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3616
3617 if (len == 0)
849a8357 3618 continue;
8ef5ada2
SK
3619 else
3620 start[len] = 0;
3621
611ebc5f 3622 if (option != 0)
8ef5ada2
SK
3623 arg = start;
3624 else if ((p=strchr(start, '=')))
849a8357
SK
3625 {
3626 /* allow spaces around "=" */
8ef5ada2
SK
3627 for (arg = p+1; *arg == ' '; arg++);
3628 for (; p >= start && (*p == ' ' || *p == '='); p--)
849a8357 3629 *p = 0;
9e4abcb5 3630 }
849a8357
SK
3631 else
3632 arg = NULL;
832af0ba 3633
611ebc5f 3634 if (option == 0)
5aabfc78 3635 {
5aabfc78
SK
3636 for (option = 0, i = 0; opts[i].name; i++)
3637 if (strcmp(opts[i].name, start) == 0)
3638 {
3639 option = opts[i].val;
3640 break;
3641 }
3642
3643 if (!option)
3644 errmess = _("bad option");
3645 else if (opts[i].has_arg == 0 && arg)
3646 errmess = _("extraneous parameter");
3647 else if (opts[i].has_arg == 1 && !arg)
3648 errmess = _("missing parameter");
3649 }
c4a7f90e
SK
3650
3651 oops:
832af0ba 3652 if (errmess)
c4a7f90e
SK
3653 strcpy(daemon->namebuff, errmess);
3654
3655 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
f2621c7f 3656 {
c4a7f90e 3657 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
824af85b 3658 if (hard_opt != 0)
c4a7f90e 3659 my_syslog(LOG_ERR, "%s", daemon->namebuff);
5aabfc78 3660 else
c4a7f90e 3661 die("%s", daemon->namebuff, EC_BADCONF);
f2621c7f 3662 }
849a8357
SK
3663 }
3664
8ef5ada2 3665 mem_recover = 0;
849a8357
SK
3666 fclose(f);
3667}
3668
395eb719 3669static int one_file(char *file, int hard_opt)
28866e95
SK
3670{
3671 FILE *f;
3672 int nofile_ok = 0;
3673 static int read_stdin = 0;
3674 static struct fileread {
3675 dev_t dev;
3676 ino_t ino;
3677 struct fileread *next;
3678 } *filesread = NULL;
3679
3680 if (hard_opt == '7')
3681 {
3682 /* default conf-file reading */
3683 hard_opt = 0;
3684 nofile_ok = 1;
3685 }
3686
3687 if (hard_opt == 0 && strcmp(file, "-") == 0)
3688 {
3689 if (read_stdin == 1)
395eb719 3690 return 1;
28866e95
SK
3691 read_stdin = 1;
3692 file = "stdin";
3693 f = stdin;
3694 }
3695 else
3696 {
3697 /* ignore repeated files. */
3698 struct stat statbuf;
3699
3700 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3701 {
3702 struct fileread *r;
3703
3704 for (r = filesread; r; r = r->next)
3705 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
395eb719 3706 return 1;
28866e95
SK
3707
3708 r = safe_malloc(sizeof(struct fileread));
3709 r->next = filesread;
3710 filesread = r;
3711 r->dev = statbuf.st_dev;
3712 r->ino = statbuf.st_ino;
3713 }
3714
3715 if (!(f = fopen(file, "r")))
3716 {
3717 if (errno == ENOENT && nofile_ok)
395eb719 3718 return 1; /* No conffile, all done. */
28866e95
SK
3719 else
3720 {
3721 char *str = _("cannot read %s: %s");
3722 if (hard_opt != 0)
3723 {
3724 my_syslog(LOG_ERR, str, file, strerror(errno));
395eb719 3725 return 0;
28866e95
SK
3726 }
3727 else
3728 die(str, file, EC_FILE);
3729 }
3730 }
3731 }
3732
3733 read_file(file, f, hard_opt);
395eb719 3734 return 1;
28866e95
SK
3735}
3736
3737/* expand any name which is a directory */
3738struct hostsfile *expand_filelist(struct hostsfile *list)
3739{
3740 int i;
3741 struct hostsfile *ah;
3742
3743 for (i = 0, ah = list; ah; ah = ah->next)
3744 {
3745 if (i <= ah->index)
3746 i = ah->index + 1;
3747
3748 if (ah->flags & AH_DIR)
3749 ah->flags |= AH_INACTIVE;
3750 else
3751 ah->flags &= ~AH_INACTIVE;
3752 }
3753
3754 for (ah = list; ah; ah = ah->next)
3755 if (!(ah->flags & AH_INACTIVE))
3756 {
3757 struct stat buf;
3758 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3759 {
3760 DIR *dir_stream;
3761 struct dirent *ent;
3762
3763 /* don't read this as a file */
3764 ah->flags |= AH_INACTIVE;
3765
3766 if (!(dir_stream = opendir(ah->fname)))
3767 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3768 ah->fname, strerror(errno));
3769 else
3770 {
3771 while ((ent = readdir(dir_stream)))
3772 {
3773 size_t lendir = strlen(ah->fname);
3774 size_t lenfile = strlen(ent->d_name);
3775 struct hostsfile *ah1;
3776 char *path;
3777
3778 /* ignore emacs backups and dotfiles */
3779 if (lenfile == 0 ||
3780 ent->d_name[lenfile - 1] == '~' ||
3781 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3782 ent->d_name[0] == '.')
3783 continue;
3784
3785 /* see if we have an existing record.
3786 dir is ah->fname
3787 file is ent->d_name
3788 path to match is ah1->fname */
3789
3790 for (ah1 = list; ah1; ah1 = ah1->next)
3791 {
3792 if (lendir < strlen(ah1->fname) &&
3793 strstr(ah1->fname, ah->fname) == ah1->fname &&
3794 ah1->fname[lendir] == '/' &&
3795 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3796 {
3797 ah1->flags &= ~AH_INACTIVE;
3798 break;
3799 }
3800 }
3801
3802 /* make new record */
3803 if (!ah1)
3804 {
3805 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3806 continue;
3807
3808 if (!(path = whine_malloc(lendir + lenfile + 2)))
3809 {
3810 free(ah1);
3811 continue;
3812 }
3813
3814 strcpy(path, ah->fname);
3815 strcat(path, "/");
3816 strcat(path, ent->d_name);
3817 ah1->fname = path;
3818 ah1->index = i++;
3819 ah1->flags = AH_DIR;
3820 ah1->next = list;
3821 list = ah1;
3822 }
3823
3824 /* inactivate record if not regular file */
3825 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3826 ah1->flags |= AH_INACTIVE;
3827
3828 }
3829 closedir(dir_stream);
3830 }
3831 }
3832 }
3833
3834 return list;
3835}
3836
3837
7622fc06 3838#ifdef HAVE_DHCP
824af85b
SK
3839void reread_dhcp(void)
3840{
28866e95
SK
3841 struct hostsfile *hf;
3842
824af85b
SK
3843 if (daemon->dhcp_hosts_file)
3844 {
3845 struct dhcp_config *configs, *cp, **up;
28866e95 3846
824af85b
SK
3847 /* remove existing... */
3848 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3849 {
3850 cp = configs->next;
3851
3852 if (configs->flags & CONFIG_BANK)
3853 {
9009d746 3854 struct hwaddr_config *mac, *tmp;
8ef5ada2 3855 struct dhcp_netid_list *list, *tmplist;
9009d746
SK
3856
3857 for (mac = configs->hwaddr; mac; mac = tmp)
3858 {
3859 tmp = mac->next;
3860 free(mac);
3861 }
8ef5ada2 3862
824af85b
SK
3863 if (configs->flags & CONFIG_CLID)
3864 free(configs->clid);
8ef5ada2
SK
3865
3866 for (list = configs->netid; list; list = tmplist)
3867 {
3868 free(list->list);
3869 tmplist = list->next;
3870 free(list);
3871 }
3872
824af85b
SK
3873 if (configs->flags & CONFIG_NAME)
3874 free(configs->hostname);
3875
3876 *up = configs->next;
3877 free(configs);
3878 }
3879 else
3880 up = &configs->next;
3881 }
3882
28866e95
SK
3883 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3884 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3885 if (!(hf->flags & AH_INACTIVE))
3886 {
395eb719
SK
3887 if (one_file(hf->fname, LOPT_BANK))
3888 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 3889 }
824af85b
SK
3890 }
3891
3892 if (daemon->dhcp_opts_file)
3893 {
3894 struct dhcp_opt *opts, *cp, **up;
3895 struct dhcp_netid *id, *next;
3896
3897 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3898 {
3899 cp = opts->next;
3900
3901 if (opts->flags & DHOPT_BANK)
3902 {
73a08a24
SK
3903 if ((opts->flags & DHOPT_VENDOR))
3904 free(opts->u.vendor_class);
824af85b
SK
3905 free(opts->val);
3906 for (id = opts->netid; id; id = next)
3907 {
3908 next = id->next;
3909 free(id->net);
3910 free(id);
3911 }
3912 *up = opts->next;
3913 free(opts);
3914 }
3915 else
3916 up = &opts->next;
3917 }
3918
28866e95
SK
3919 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3920 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3921 if (!(hf->flags & AH_INACTIVE))
3922 {
395eb719
SK
3923 if (one_file(hf->fname, LOPT_OPTS))
3924 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 3925 }
824af85b
SK
3926 }
3927}
7622fc06 3928#endif
824af85b 3929
5aabfc78 3930void read_opts(int argc, char **argv, char *compile_opts)
849a8357 3931{
824af85b 3932 char *buff = opt_malloc(MAXDNAME);
28866e95 3933 int option, conffile_opt = '7', testmode = 0;
c4a7f90e 3934 char *arg, *conffile = CONFFILE;
849a8357
SK
3935
3936 opterr = 0;
5aabfc78 3937
824af85b 3938 daemon = opt_malloc(sizeof(struct daemon));
849a8357
SK
3939 memset(daemon, 0, sizeof(struct daemon));
3940 daemon->namebuff = buff;
3941
3942 /* Set defaults - everything else is zero or NULL */
3943 daemon->cachesize = CACHESIZ;
208b65c5 3944 daemon->ftabsize = FTABSIZ;
849a8357 3945 daemon->port = NAMESERVER_PORT;
9e038946
SK
3946 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3947 daemon->dhcp_server_port = DHCP_SERVER_PORT;
849a8357
SK
3948 daemon->default_resolv.is_default = 1;
3949 daemon->default_resolv.name = RESOLVFILE;
3950 daemon->resolv_files = &daemon->default_resolv;
3951 daemon->username = CHUSER;
849a8357
SK
3952 daemon->runfile = RUNFILE;
3953 daemon->dhcp_max = MAXLEASES;
832af0ba 3954 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
849a8357
SK
3955 daemon->edns_pktsz = EDNS_PKTSZ;
3956 daemon->log_fac = -1;
4f7b304f
SK
3957 daemon->auth_ttl = AUTH_TTL;
3958 daemon->soa_refresh = SOA_REFRESH;
3959 daemon->soa_retry = SOA_RETRY;
3960 daemon->soa_expiry = SOA_EXPIRY;
5aabfc78
SK
3961 add_txt("version.bind", "dnsmasq-" VERSION );
3962 add_txt("authors.bind", "Simon Kelley");
3963 add_txt("copyright.bind", COPYRIGHT);
849a8357
SK
3964
3965 while (1)
3966 {
26128d27 3967#ifdef HAVE_GETOPT_LONG
849a8357 3968 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
26128d27 3969#else
849a8357 3970 option = getopt(argc, argv, OPTSTRING);
26128d27 3971#endif
849a8357
SK
3972
3973 if (option == -1)
28866e95 3974 {
572b41eb
SK
3975 for (; optind < argc; optind++)
3976 {
3977 unsigned char *c = (unsigned char *)argv[optind];
3978 for (; *c != 0; c++)
3979 if (!isspace(*c))
3980 die(_("junk found in command line"), NULL, EC_BADCONF);
3981 }
28866e95
SK
3982 break;
3983 }
3984
849a8357
SK
3985 /* Copy optarg so that argv doesn't get changed */
3986 if (optarg)
3987 {
3988 strncpy(buff, optarg, MAXDNAME);
3989 buff[MAXDNAME-1] = 0;
3990 arg = buff;
9e4abcb5 3991 }
849a8357
SK
3992 else
3993 arg = NULL;
9e4abcb5 3994
849a8357 3995 /* command-line only stuff */
7622fc06
SK
3996 if (option == LOPT_TEST)
3997 testmode = 1;
3998 else if (option == 'w')
849a8357 3999 {
7622fc06 4000#ifdef HAVE_DHCP
4cb1b320 4001 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
7622fc06 4002 display_opts();
4cb1b320
SK
4003#ifdef HAVE_DHCP6
4004 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4005 display_opts6();
7622fc06 4006#endif
4cb1b320 4007 else
7622fc06 4008#endif
4cb1b320
SK
4009 do_usage();
4010
849a8357
SK
4011 exit(0);
4012 }
4013 else if (option == 'v')
4014 {
4015 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
c72daea8 4016 printf(_("Compile time options: %s\n\n"), compile_opts);
849a8357
SK
4017 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4018 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
824af85b 4019 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
849a8357
SK
4020 exit(0);
4021 }
4022 else if (option == 'C')
4023 {
28866e95 4024 conffile_opt = 0; /* file must exist */
824af85b 4025 conffile = opt_string_alloc(arg);
849a8357
SK
4026 }
4027 else
4028 {
4029#ifdef HAVE_GETOPT_LONG
c4a7f90e 4030 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
849a8357 4031#else
c4a7f90e 4032 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
849a8357 4033#endif
c4a7f90e 4034 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
849a8357
SK
4035 }
4036 }
4037
4038 if (conffile)
28866e95 4039 one_file(conffile, conffile_opt);
849a8357 4040
1a6bca81 4041 /* port might not be known when the address is parsed - fill in here */
3be34541 4042 if (daemon->servers)
9e4abcb5
SK
4043 {
4044 struct server *tmp;
3be34541 4045 for (tmp = daemon->servers; tmp; tmp = tmp->next)
9e4abcb5
SK
4046 if (!(tmp->flags & SERV_HAS_SOURCE))
4047 {
4048 if (tmp->source_addr.sa.sa_family == AF_INET)
3be34541 4049 tmp->source_addr.in.sin_port = htons(daemon->query_port);
9e4abcb5
SK
4050#ifdef HAVE_IPV6
4051 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3be34541 4052 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
5aabfc78
SK
4053#endif
4054 }
9e4abcb5
SK
4055 }
4056
3be34541 4057 if (daemon->if_addrs)
9e4abcb5
SK
4058 {
4059 struct iname *tmp;
3be34541 4060 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
9e4abcb5 4061 if (tmp->addr.sa.sa_family == AF_INET)
3be34541 4062 tmp->addr.in.sin_port = htons(daemon->port);
9e4abcb5
SK
4063#ifdef HAVE_IPV6
4064 else if (tmp->addr.sa.sa_family == AF_INET6)
3be34541 4065 tmp->addr.in6.sin6_port = htons(daemon->port);
9e4abcb5
SK
4066#endif /* IPv6 */
4067 }
4f7b304f
SK
4068
4069 /* create default, if not specified */
4070 if (daemon->authserver && !daemon->hostmaster)
4071 {
4072 strcpy(buff, "hostmaster.");
4073 strcat(buff, daemon->authserver);
4074 daemon->hostmaster = opt_string_alloc(buff);
4075 }
4076
f6b7dc47 4077 /* only one of these need be specified: the other defaults to the host-name */
28866e95 4078 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
9e4abcb5 4079 {
0a852541
SK
4080 struct mx_srv_record *mx;
4081
9e4abcb5 4082 if (gethostname(buff, MAXDNAME) == -1)
5aabfc78 4083 die(_("cannot get host-name: %s"), NULL, EC_MISC);
f6b7dc47 4084
0a852541
SK
4085 for (mx = daemon->mxnames; mx; mx = mx->next)
4086 if (!mx->issrv && hostname_isequal(mx->name, buff))
4087 break;
4088
28866e95 4089 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
de37951c 4090 {
824af85b 4091 mx = opt_malloc(sizeof(struct mx_srv_record));
91dccd09
SK
4092 mx->next = daemon->mxnames;
4093 mx->issrv = 0;
4094 mx->target = NULL;
824af85b 4095 mx->name = opt_string_alloc(buff);
91dccd09 4096 daemon->mxnames = mx;
f6b7dc47 4097 }
9e4abcb5 4098
3be34541 4099 if (!daemon->mxtarget)
824af85b 4100 daemon->mxtarget = opt_string_alloc(buff);
0a852541
SK
4101
4102 for (mx = daemon->mxnames; mx; mx = mx->next)
4103 if (!mx->issrv && !mx->target)
4104 mx->target = daemon->mxtarget;
9e4abcb5 4105 }
f6b7dc47 4106
28866e95 4107 if (!option_bool(OPT_NO_RESOLV) &&
208b65c5
SK
4108 daemon->resolv_files &&
4109 daemon->resolv_files->next &&
28866e95 4110 option_bool(OPT_NO_POLL))
5aabfc78 4111 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
de37951c 4112
28866e95 4113 if (option_bool(OPT_RESOLV_DOMAIN))
de37951c
SK
4114 {
4115 char *line;
849a8357
SK
4116 FILE *f;
4117
28866e95 4118 if (option_bool(OPT_NO_RESOLV) ||
208b65c5
SK
4119 !daemon->resolv_files ||
4120 (daemon->resolv_files)->next)
5aabfc78 4121 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
de37951c 4122
3be34541 4123 if (!(f = fopen((daemon->resolv_files)->name, "r")))
5aabfc78 4124 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
de37951c
SK
4125
4126 while ((line = fgets(buff, MAXDNAME, f)))
4127 {
4128 char *token = strtok(line, " \t\n\r");
4129
4130 if (!token || strcmp(token, "search") != 0)
4131 continue;
4132
4133 if ((token = strtok(NULL, " \t\n\r")) &&
1f15b81d 4134 (daemon->domain_suffix = canonicalise_opt(token)))
de37951c
SK
4135 break;
4136 }
3be34541 4137
de37951c 4138 fclose(f);
8a911ccc 4139
3be34541 4140 if (!daemon->domain_suffix)
5aabfc78 4141 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
de37951c 4142 }
3d8df260
SK
4143
4144 if (daemon->domain_suffix)
4145 {
4146 /* add domain for any srv record without one. */
4147 struct mx_srv_record *srv;
de37951c 4148
3d8df260
SK
4149 for (srv = daemon->mxnames; srv; srv = srv->next)
4150 if (srv->issrv &&
4151 strchr(srv->name, '.') &&
4152 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4153 {
4154 strcpy(buff, srv->name);
4155 strcat(buff, ".");
4156 strcat(buff, daemon->domain_suffix);
4157 free(srv->name);
824af85b 4158 srv->name = opt_string_alloc(buff);
3d8df260
SK
4159 }
4160 }
28866e95 4161 else if (option_bool(OPT_DHCP_FQDN))
9009d746 4162 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
7622fc06
SK
4163
4164 if (testmode)
4165 {
4166 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4167 exit(0);
4168 }
849a8357 4169}