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