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