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