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