dnsmasq latest
[tomato.git] / release / src / router / dnsmasq / src / option.c
blob2d860d55636bc59db5f08920e78e3cc98a60c968
1 /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
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.
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.
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/>.
17 /* define this to get facilitynames */
18 #define SYSLOG_NAMES
19 #include "dnsmasq.h"
20 #include <setjmp.h>
22 static volatile int mem_recover = 0;
23 static jmp_buf mem_jmp;
24 static int one_file(char *file, int hard_opt);
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 }
53 #endif
55 #ifndef HAVE_GETOPT_LONG
56 struct myoption {
57 const char *name;
58 int has_arg;
59 int *flag;
60 int val;
62 #endif
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:"
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
147 #ifdef HAVE_GETOPT_LONG
148 static const struct option opts[] =
149 #else
150 static const struct myoption opts[] =
151 #endif
153 { "version", 0, 0, 'v' },
154 { "no-hosts", 0, 0, 'h' },
155 { "no-poll", 0, 0, 'n' },
156 { "help", 0, 0, 'w' },
157 { "no-daemon", 0, 0, 'd' },
158 { "log-queries", 0, 0, 'q' },
159 { "user", 2, 0, 'u' },
160 { "group", 2, 0, 'g' },
161 { "resolv-file", 2, 0, 'r' },
162 { "servers-file", 1, 0, LOPT_SERVERS_FILE },
163 { "mx-host", 1, 0, 'm' },
164 { "mx-target", 1, 0, 't' },
165 { "cache-size", 2, 0, 'c' },
166 { "port", 1, 0, 'p' },
167 { "dhcp-leasefile", 2, 0, 'l' },
168 { "dhcp-lease", 1, 0, 'l' },
169 { "dhcp-host", 1, 0, 'G' },
170 { "dhcp-range", 1, 0, 'F' },
171 { "dhcp-option", 1, 0, 'O' },
172 { "dhcp-boot", 1, 0, 'M' },
173 { "domain", 1, 0, 's' },
174 { "domain-suffix", 1, 0, 's' },
175 { "interface", 1, 0, 'i' },
176 { "listen-address", 1, 0, 'a' },
177 { "bogus-priv", 0, 0, 'b' },
178 { "bogus-nxdomain", 1, 0, 'B' },
179 { "selfmx", 0, 0, 'e' },
180 { "filterwin2k", 0, 0, 'f' },
181 { "pid-file", 2, 0, 'x' },
182 { "strict-order", 0, 0, 'o' },
183 { "server", 1, 0, 'S' },
184 { "rev-server", 1, 0, LOPT_REV_SERV },
185 { "local", 1, 0, LOPT_LOCAL },
186 { "address", 1, 0, 'A' },
187 { "conf-file", 2, 0, 'C' },
188 { "no-resolv", 0, 0, 'R' },
189 { "expand-hosts", 0, 0, 'E' },
190 { "localmx", 0, 0, 'L' },
191 { "local-ttl", 1, 0, 'T' },
192 { "no-negcache", 0, 0, 'N' },
193 { "addn-hosts", 1, 0, 'H' },
194 { "query-port", 1, 0, 'Q' },
195 { "except-interface", 1, 0, 'I' },
196 { "no-dhcp-interface", 1, 0, '2' },
197 { "domain-needed", 0, 0, 'D' },
198 { "dhcp-lease-max", 1, 0, 'X' },
199 { "bind-interfaces", 0, 0, 'z' },
200 { "read-ethers", 0, 0, 'Z' },
201 { "alias", 1, 0, 'V' },
202 { "dhcp-vendorclass", 1, 0, 'U' },
203 { "dhcp-userclass", 1, 0, 'j' },
204 { "dhcp-ignore", 1, 0, 'J' },
205 { "edns-packet-max", 1, 0, 'P' },
206 { "keep-in-foreground", 0, 0, 'k' },
207 { "dhcp-authoritative", 0, 0, 'K' },
208 { "srv-host", 1, 0, 'W' },
209 { "localise-queries", 0, 0, 'y' },
210 { "txt-record", 1, 0, 'Y' },
211 { "dns-rr", 1, 0, LOPT_RR },
212 { "enable-dbus", 2, 0, '1' },
213 { "bootp-dynamic", 2, 0, '3' },
214 { "dhcp-mac", 1, 0, '4' },
215 { "no-ping", 0, 0, '5' },
216 { "dhcp-script", 1, 0, '6' },
217 { "conf-dir", 1, 0, '7' },
218 { "log-facility", 1, 0 ,'8' },
219 { "leasefile-ro", 0, 0, '9' },
220 { "dns-forward-max", 1, 0, '0' },
221 { "clear-on-reload", 0, 0, LOPT_RELOAD },
222 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
223 { "enable-tftp", 2, 0, LOPT_TFTP },
224 { "tftp-secure", 0, 0, LOPT_SECURE },
225 { "tftp-unique-root", 0, 0, LOPT_APREF },
226 { "tftp-root", 1, 0, LOPT_PREFIX },
227 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
228 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
229 { "ptr-record", 1, 0, LOPT_PTR },
230 { "naptr-record", 1, 0, LOPT_NAPTR },
231 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
232 { "dhcp-option-force", 1, 0, LOPT_FORCE },
233 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
234 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
235 { "log-async", 2, 0, LOPT_MAX_LOGS },
236 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
237 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
238 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
239 { "interface-name", 1, 0, LOPT_INTNAME },
240 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
241 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
242 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
243 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
244 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
245 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
246 { "all-servers", 0, 0, LOPT_NOLAST },
247 { "dhcp-match", 1, 0, LOPT_MATCH },
248 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
249 { "neg-ttl", 1, 0, LOPT_NEGTTL },
250 { "max-ttl", 1, 0, LOPT_MAXTTL },
251 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
252 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
253 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
254 { "min-port", 1, 0, LOPT_MINPORT },
255 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
256 { "cname", 1, 0, LOPT_CNAME },
257 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
258 { "pxe-service", 1, 0, LOPT_PXE_SERV },
259 { "test", 0, 0, LOPT_TEST },
260 { "tag-if", 1, 0, LOPT_TAG_IF },
261 { "dhcp-proxy", 2, 0, LOPT_PROXY },
262 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
263 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
264 { "add-mac", 0, 0, LOPT_ADD_MAC },
265 { "add-subnet", 2, 0, LOPT_ADD_SBNET },
266 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
267 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
268 { "conntrack", 0, 0, LOPT_CONNTRACK },
269 { "dhcp-client-update", 0, 0, LOPT_FQDN },
270 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
271 { "enable-ra", 0, 0, LOPT_RA },
272 { "dhcp-duid", 1, 0, LOPT_DUID },
273 { "host-record", 1, 0, LOPT_HOST_REC },
274 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
275 { "auth-zone", 1, 0, LOPT_AUTHZONE },
276 { "auth-server", 1, 0, LOPT_AUTHSERV },
277 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
278 { "auth-soa", 1, 0, LOPT_AUTHSOA },
279 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
280 { "auth-peer", 1, 0, LOPT_AUTHPEER },
281 { "ipset", 1, 0, LOPT_IPSET },
282 { "synth-domain", 1, 0, LOPT_SYNTH },
283 { "dnssec", 0, 0, LOPT_SEC_VALID },
284 { "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
285 { "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
286 #ifdef OPTION6_PREFIX_CLASS
287 { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
288 #endif
289 { "dhcp-relay", 1, 0, LOPT_RELAY },
290 { "ra-param", 1, 0, LOPT_RA_PARAM },
291 { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
292 { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
293 { "quiet-ra", 0, 0, LOPT_QUIET_RA },
294 { NULL, 0, 0, 0 }
298 #define ARG_DUP OPT_LAST
299 #define ARG_ONE OPT_LAST + 1
300 #define ARG_USED_CL OPT_LAST + 2
301 #define ARG_USED_FILE OPT_LAST + 3
303 static struct {
304 int opt;
305 unsigned int rept;
306 char * const flagdesc;
307 char * const desc;
308 char * const arg;
309 } usage[] = {
310 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
311 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
312 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
313 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
314 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
315 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
316 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
317 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
318 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
319 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
320 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
321 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
322 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
323 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
324 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
325 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
326 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
327 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
328 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
329 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
330 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
331 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
332 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
333 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
334 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
335 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
336 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
337 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
338 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
339 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
340 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
341 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
342 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
343 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
344 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
345 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
346 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
347 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
348 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
349 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
350 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
351 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
352 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
353 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
354 { LOPT_SERVERS_FILE, ARG_ONE, "<path>", gettext_noop("Specify path to file with server= options"), NULL },
355 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
356 { LOPT_REV_SERV, ARG_DUP, "<addr>/<prefix>,<ipaddr>", gettext_noop("Specify address of upstream servers for reverse address queries"), NULL },
357 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
358 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
359 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
360 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
361 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
362 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
363 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
364 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
365 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
366 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
367 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
368 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
369 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
370 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
371 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
372 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
373 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
374 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
375 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
376 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
377 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
378 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
379 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
380 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
381 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
382 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
383 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
384 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
385 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
386 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
387 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
388 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
389 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
390 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
391 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
392 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
393 { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
394 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
395 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
396 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
397 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
398 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
399 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
400 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
401 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
402 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
403 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
404 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
405 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
406 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
407 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
408 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
409 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
410 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
411 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
412 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
413 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
414 { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
415 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
416 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
417 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
418 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
419 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
420 { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL },
421 { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
422 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
423 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
424 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
425 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
426 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
427 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
428 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
429 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
430 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
431 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
432 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
433 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
434 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
435 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
436 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
437 { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
438 { LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
439 { LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
440 { LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
441 #ifdef OPTION6_PREFIX_CLASS
442 { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
443 #endif
444 { LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
445 { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
446 { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
447 { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
448 { 0, 0, NULL, NULL, NULL }
451 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
452 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
453 following sequence so that they map to themselves: it is therefore possible to call
454 unhide_metas repeatedly on string without breaking things.
455 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
456 couple of other places.
457 Note that space is included here so that
458 --dhcp-option=3, string
459 has five characters, whilst
460 --dhcp-option=3," string"
461 has six.
464 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
466 static char hide_meta(char c)
468 unsigned int i;
470 for (i = 0; i < (sizeof(meta) - 1); i++)
471 if (c == meta[i])
472 return (char)i;
474 return c;
477 static char unhide_meta(char cr)
479 unsigned int c = cr;
481 if (c < (sizeof(meta) - 1))
482 cr = meta[c];
484 return cr;
487 static void unhide_metas(char *cp)
489 if (cp)
490 for(; *cp; cp++)
491 *cp = unhide_meta(*cp);
494 static void *opt_malloc(size_t size)
496 void *ret;
498 if (mem_recover)
500 ret = whine_malloc(size);
501 if (!ret)
502 longjmp(mem_jmp, 1);
504 else
505 ret = safe_malloc(size);
507 return ret;
510 static char *opt_string_alloc(char *cp)
512 char *ret = NULL;
514 if (cp && strlen(cp) != 0)
516 ret = opt_malloc(strlen(cp)+1);
517 strcpy(ret, cp);
519 /* restore hidden metachars */
520 unhide_metas(ret);
523 return ret;
527 /* find next comma, split string with zero and eliminate spaces.
528 return start of string following comma */
530 static char *split_chr(char *s, char c)
532 char *comma, *p;
534 if (!s || !(comma = strchr(s, c)))
535 return NULL;
537 p = comma;
538 *comma = ' ';
540 for (; *comma == ' '; comma++);
542 for (; (p >= s) && *p == ' '; p--)
543 *p = 0;
545 return comma;
548 static char *split(char *s)
550 return split_chr(s, ',');
553 static char *canonicalise_opt(char *s)
555 char *ret;
556 int nomem;
558 if (!s)
559 return 0;
561 unhide_metas(s);
562 if (!(ret = canonicalise(s, &nomem)) && nomem)
564 if (mem_recover)
565 longjmp(mem_jmp, 1);
566 else
567 die(_("could not get memory"), NULL, EC_NOMEM);
570 return ret;
573 static int atoi_check(char *a, int *res)
575 char *p;
577 if (!a)
578 return 0;
580 unhide_metas(a);
582 for (p = a; *p; p++)
583 if (*p < '0' || *p > '9')
584 return 0;
586 *res = atoi(a);
587 return 1;
590 static int atoi_check16(char *a, int *res)
592 if (!(atoi_check(a, res)) ||
593 *res < 0 ||
594 *res > 0xffff)
595 return 0;
597 return 1;
600 #ifdef HAVE_DNSSEC
601 static int atoi_check8(char *a, int *res)
603 if (!(atoi_check(a, res)) ||
604 *res < 0 ||
605 *res > 0xff)
606 return 0;
608 return 1;
610 #endif
612 static void add_txt(char *name, char *txt)
614 size_t len = strlen(txt);
615 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
617 r->name = opt_string_alloc(name);
618 r->next = daemon->txt;
619 daemon->txt = r;
620 r->class = C_CHAOS;
621 r->txt = opt_malloc(len+1);
622 r->len = len+1;
623 *(r->txt) = len;
624 memcpy((r->txt)+1, txt, len);
627 static void do_usage(void)
629 char buff[100];
630 int i, j;
632 struct {
633 char handle;
634 int val;
635 } tab[] = {
636 { '$', CACHESIZ },
637 { '*', EDNS_PKTSZ },
638 { '&', MAXLEASES },
639 { '!', FTABSIZ },
640 { '#', TFTP_MAX_CONNECTIONS },
641 { '\0', 0 }
644 printf(_("Usage: dnsmasq [options]\n\n"));
645 #ifndef HAVE_GETOPT_LONG
646 printf(_("Use short options only on the command line.\n"));
647 #endif
648 printf(_("Valid options are:\n"));
650 for (i = 0; usage[i].opt != 0; i++)
652 char *desc = usage[i].flagdesc;
653 char *eq = "=";
655 if (!desc || *desc == '[')
656 eq = "";
658 if (!desc)
659 desc = "";
661 for ( j = 0; opts[j].name; j++)
662 if (opts[j].val == usage[i].opt)
663 break;
664 if (usage[i].opt < 256)
665 sprintf(buff, "-%c, ", usage[i].opt);
666 else
667 sprintf(buff, " ");
669 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
670 printf("%-40.40s", buff);
672 if (usage[i].arg)
674 strcpy(buff, usage[i].arg);
675 for (j = 0; tab[j].handle; j++)
676 if (tab[j].handle == *(usage[i].arg))
677 sprintf(buff, "%d", tab[j].val);
679 printf(_(usage[i].desc), buff);
680 printf("\n");
684 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
686 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
688 int source_port = 0, serv_port = NAMESERVER_PORT;
689 char *portno, *source;
690 #ifdef HAVE_IPV6
691 int scope_index = 0;
692 char *scope_id;
693 #endif
695 if (!arg || strlen(arg) == 0)
697 *flags |= SERV_NO_ADDR;
698 *interface = 0;
699 return NULL;
702 if ((source = split_chr(arg, '@')) && /* is there a source. */
703 (portno = split_chr(source, '#')) &&
704 !atoi_check16(portno, &source_port))
705 return _("bad port");
707 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
708 !atoi_check16(portno, &serv_port))
709 return _("bad port");
711 #ifdef HAVE_IPV6
712 scope_id = split_chr(arg, '%');
713 #endif
715 if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
717 addr->in.sin_port = htons(serv_port);
718 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
719 #ifdef HAVE_SOCKADDR_SA_LEN
720 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
721 #endif
722 source_addr->in.sin_addr.s_addr = INADDR_ANY;
723 source_addr->in.sin_port = htons(daemon->query_port);
725 if (source)
727 if (flags)
728 *flags |= SERV_HAS_SOURCE;
729 source_addr->in.sin_port = htons(source_port);
730 if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
732 #if defined(SO_BINDTODEVICE)
733 source_addr->in.sin_addr.s_addr = INADDR_ANY;
734 strncpy(interface, source, IF_NAMESIZE - 1);
735 #else
736 return _("interface binding not supported");
737 #endif
741 #ifdef HAVE_IPV6
742 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
744 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
745 return _("bad interface name");
747 addr->in6.sin6_port = htons(serv_port);
748 addr->in6.sin6_scope_id = scope_index;
749 source_addr->in6.sin6_addr = in6addr_any;
750 source_addr->in6.sin6_port = htons(daemon->query_port);
751 source_addr->in6.sin6_scope_id = 0;
752 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
753 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
754 #ifdef HAVE_SOCKADDR_SA_LEN
755 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
756 #endif
757 if (source)
759 if (flags)
760 *flags |= SERV_HAS_SOURCE;
761 source_addr->in6.sin6_port = htons(source_port);
762 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
764 #if defined(SO_BINDTODEVICE)
765 source_addr->in6.sin6_addr = in6addr_any;
766 strncpy(interface, source, IF_NAMESIZE - 1);
767 #else
768 return _("interface binding not supported");
769 #endif
773 #endif
774 else
775 return _("bad address");
777 return NULL;
780 static struct server *add_rev4(struct in_addr addr, int msize)
782 struct server *serv = opt_malloc(sizeof(struct server));
783 in_addr_t a = ntohl(addr.s_addr) >> 8;
784 char *p;
786 memset(serv, 0, sizeof(struct server));
787 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
789 if (msize == 24)
790 p += sprintf(p, "%d.", a & 0xff);
791 a = a >> 8;
792 if (msize != 8)
793 p += sprintf(p, "%d.", a & 0xff);
794 a = a >> 8;
795 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
797 serv->flags = SERV_HAS_DOMAIN;
798 serv->next = daemon->servers;
799 daemon->servers = serv;
801 return serv;
805 static struct server *add_rev6(struct in6_addr *addr, int msize)
807 struct server *serv = opt_malloc(sizeof(struct server));
808 char *p;
809 int i;
811 memset(serv, 0, sizeof(struct server));
812 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
814 for (i = msize-1; i >= 0; i -= 4)
816 int dig = ((unsigned char *)addr)[i>>3];
817 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
819 p += sprintf(p, "ip6.arpa");
821 serv->flags = SERV_HAS_DOMAIN;
822 serv->next = daemon->servers;
823 daemon->servers = serv;
825 return serv;
828 #ifdef HAVE_DHCP
830 static int is_tag_prefix(char *arg)
832 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
833 return 1;
835 return 0;
838 static char *set_prefix(char *arg)
840 if (strstr(arg, "set:") == arg)
841 return arg+4;
843 return arg;
846 /* This is too insanely large to keep in-line in the switch */
847 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
849 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
850 char lenchar = 0, *cp;
851 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
852 char *comma = NULL;
853 struct dhcp_netid *np = NULL;
854 u16 opt_len = 0;
855 int is6 = 0;
856 int option_ok = 0;
858 new->len = 0;
859 new->flags = flags;
860 new->netid = NULL;
861 new->val = NULL;
862 new->opt = 0;
864 while (arg)
866 comma = split(arg);
868 for (cp = arg; *cp; cp++)
869 if (*cp < '0' || *cp > '9')
870 break;
872 if (!*cp)
874 new->opt = atoi(arg);
875 opt_len = 0;
876 option_ok = 1;
877 break;
880 if (strstr(arg, "option:") == arg)
882 if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
884 opt_len = lookup_dhcp_len(AF_INET, new->opt);
885 /* option:<optname> must follow tag and vendor string. */
886 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
887 option_ok = 1;
889 break;
891 #ifdef HAVE_DHCP6
892 else if (strstr(arg, "option6:") == arg)
894 for (cp = arg+8; *cp; cp++)
895 if (*cp < '0' || *cp > '9')
896 break;
898 if (!*cp)
900 new->opt = atoi(arg+8);
901 opt_len = 0;
902 option_ok = 1;
904 else
906 if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
908 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
909 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
910 option_ok = 1;
913 /* option6:<opt>|<optname> must follow tag and vendor string. */
914 is6 = 1;
915 break;
917 #endif
918 else if (strstr(arg, "vendor:") == arg)
920 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
921 new->flags |= DHOPT_VENDOR;
923 else if (strstr(arg, "encap:") == arg)
925 new->u.encap = atoi(arg+6);
926 new->flags |= DHOPT_ENCAPSULATE;
928 else if (strstr(arg, "vi-encap:") == arg)
930 new->u.encap = atoi(arg+9);
931 new->flags |= DHOPT_RFC3925;
932 if (flags == DHOPT_MATCH)
934 option_ok = 1;
935 break;
938 else
940 new->netid = opt_malloc(sizeof (struct dhcp_netid));
941 /* allow optional "net:" or "tag:" for consistency */
942 if (is_tag_prefix(arg))
943 new->netid->net = opt_string_alloc(arg+4);
944 else
945 new->netid->net = opt_string_alloc(set_prefix(arg));
946 new->netid->next = np;
947 np = new->netid;
950 arg = comma;
953 #ifdef HAVE_DHCP6
954 if (is6)
956 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
957 ret_err(_("unsupported encapsulation for IPv6 option"));
959 if (opt_len == 0 &&
960 !(new->flags & DHOPT_RFC3925))
961 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
963 else
964 #endif
965 if (opt_len == 0 &&
966 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
967 opt_len = lookup_dhcp_len(AF_INET, new->opt);
969 /* option may be missing with rfc3925 match */
970 if (!option_ok)
971 ret_err(_("bad dhcp-option"));
973 if (comma)
975 /* characterise the value */
976 char c;
977 int found_dig = 0;
978 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
979 addrs = digs = 1;
980 dots = 0;
981 for (cp = comma; (c = *cp); cp++)
982 if (c == ',')
984 addrs++;
985 is_dec = is_hex = 0;
987 else if (c == ':')
989 digs++;
990 is_dec = is_addr = 0;
992 else if (c == '/')
994 is_addr6 = is_dec = is_hex = 0;
995 if (cp == comma) /* leading / means a pathname */
996 is_addr = 0;
998 else if (c == '.')
1000 is_addr6 = is_dec = is_hex = 0;
1001 dots++;
1003 else if (c == '-')
1004 is_hex = is_addr = is_addr6 = 0;
1005 else if (c == ' ')
1006 is_dec = is_hex = 0;
1007 else if (!(c >='0' && c <= '9'))
1009 is_addr = 0;
1010 if (cp[1] == 0 && is_dec &&
1011 (c == 'b' || c == 's' || c == 'i'))
1013 lenchar = c;
1014 *cp = 0;
1016 else
1017 is_dec = 0;
1018 if (!((c >='A' && c <= 'F') ||
1019 (c >='a' && c <= 'f') ||
1020 (c == '*' && (flags & DHOPT_MATCH))))
1022 is_hex = 0;
1023 if (c != '[' && c != ']')
1024 is_addr6 = 0;
1027 else
1028 found_dig = 1;
1030 if (!found_dig)
1031 is_dec = is_addr = 0;
1033 /* We know that some options take addresses */
1034 if (opt_len & OT_ADDR_LIST)
1036 is_string = is_dec = is_hex = 0;
1038 if (!is6 && (!is_addr || dots == 0))
1039 ret_err(_("bad IP address"));
1041 if (is6 && !is_addr6)
1042 ret_err(_("bad IPv6 address"));
1044 /* or names */
1045 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
1046 is_addr6 = is_addr = is_dec = is_hex = 0;
1048 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
1050 int val, fac = 1;
1052 switch (comma[strlen(comma) - 1])
1054 case 'w':
1055 case 'W':
1056 fac *= 7;
1057 /* fall through */
1058 case 'd':
1059 case 'D':
1060 fac *= 24;
1061 /* fall though */
1062 case 'h':
1063 case 'H':
1064 fac *= 60;
1065 /* fall through */
1066 case 'm':
1067 case 'M':
1068 fac *= 60;
1069 /* fall through */
1070 case 's':
1071 case 'S':
1072 comma[strlen(comma) - 1] = 0;
1075 new->len = 4;
1076 new->val = opt_malloc(4);
1077 val = atoi(comma);
1078 *((int *)new->val) = htonl(val * fac);
1080 else if (is_hex && digs > 1)
1082 new->len = digs;
1083 new->val = opt_malloc(new->len);
1084 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
1085 new->flags |= DHOPT_HEX;
1087 else if (is_dec)
1089 int i, val = atoi(comma);
1090 /* assume numeric arg is 1 byte except for
1091 options where it is known otherwise.
1092 For vendor class option, we have to hack. */
1093 if (opt_len != 0)
1094 new->len = opt_len;
1095 else if (val & 0xffff0000)
1096 new->len = 4;
1097 else if (val & 0xff00)
1098 new->len = 2;
1099 else
1100 new->len = 1;
1102 if (lenchar == 'b')
1103 new->len = 1;
1104 else if (lenchar == 's')
1105 new->len = 2;
1106 else if (lenchar == 'i')
1107 new->len = 4;
1109 new->val = opt_malloc(new->len);
1110 for (i=0; i<new->len; i++)
1111 new->val[i] = val>>((new->len - i - 1)*8);
1113 else if (is_addr && !is6)
1115 struct in_addr in;
1116 unsigned char *op;
1117 char *slash;
1118 /* max length of address/subnet descriptor is five bytes,
1119 add one for the option 120 enc byte too */
1120 new->val = op = opt_malloc((5 * addrs) + 1);
1121 new->flags |= DHOPT_ADDR;
1123 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1124 new->opt == OPTION_SIP_SERVER)
1126 *(op++) = 1; /* RFC 3361 "enc byte" */
1127 new->flags &= ~DHOPT_ADDR;
1129 while (addrs--)
1131 cp = comma;
1132 comma = split(cp);
1133 slash = split_chr(cp, '/');
1134 inet_pton(AF_INET, cp, &in);
1135 if (!slash)
1137 memcpy(op, &in, INADDRSZ);
1138 op += INADDRSZ;
1140 else
1142 unsigned char *p = (unsigned char *)&in;
1143 int netsize = atoi(slash);
1144 *op++ = netsize;
1145 if (netsize > 0)
1146 *op++ = *p++;
1147 if (netsize > 8)
1148 *op++ = *p++;
1149 if (netsize > 16)
1150 *op++ = *p++;
1151 if (netsize > 24)
1152 *op++ = *p++;
1153 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1156 new->len = op - new->val;
1158 else if (is_addr6 && is6)
1160 unsigned char *op;
1161 new->val = op = opt_malloc(16 * addrs);
1162 new->flags |= DHOPT_ADDR6;
1163 while (addrs--)
1165 cp = comma;
1166 comma = split(cp);
1168 /* check for [1234::7] */
1169 if (*cp == '[')
1170 cp++;
1171 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1172 cp[strlen(cp)-1] = 0;
1174 if (inet_pton(AF_INET6, cp, op))
1176 op += IN6ADDRSZ;
1177 continue;
1180 ret_err(_("bad IPv6 address"));
1182 new->len = op - new->val;
1184 else if (is_string)
1186 /* text arg */
1187 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
1188 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1190 /* dns search, RFC 3397, or SIP, RFC 3361 */
1191 unsigned char *q, *r, *tail;
1192 unsigned char *p, *m = NULL, *newp;
1193 size_t newlen, len = 0;
1194 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
1196 arg = comma;
1197 comma = split(arg);
1199 while (arg && *arg)
1201 char *in, *dom = NULL;
1202 size_t domlen = 1;
1203 /* Allow "." as an empty domain */
1204 if (strcmp (arg, ".") != 0)
1206 if (!(dom = canonicalise_opt(arg)))
1207 ret_err(_("bad domain in dhcp-option"));
1209 domlen = strlen(dom) + 2;
1212 newp = opt_malloc(len + domlen + header_size);
1213 if (m)
1215 memcpy(newp, m, header_size + len);
1216 free(m);
1218 m = newp;
1219 p = m + header_size;
1220 q = p + len;
1222 /* add string on the end in RFC1035 format */
1223 for (in = dom; in && *in;)
1225 unsigned char *cp = q++;
1226 int j;
1227 for (j = 0; *in && (*in != '.'); in++, j++)
1228 *q++ = *in;
1229 *cp = j;
1230 if (*in)
1231 in++;
1233 *q++ = 0;
1234 free(dom);
1236 /* Now tail-compress using earlier names. */
1237 newlen = q - p;
1238 for (tail = p + len; *tail; tail += (*tail) + 1)
1239 for (r = p; r - p < (int)len; r += (*r) + 1)
1240 if (strcmp((char *)r, (char *)tail) == 0)
1242 PUTSHORT((r - p) | 0xc000, tail);
1243 newlen = tail - p;
1244 goto end;
1246 end:
1247 len = newlen;
1249 arg = comma;
1250 comma = split(arg);
1253 /* RFC 3361, enc byte is zero for names */
1254 if (new->opt == OPTION_SIP_SERVER)
1255 m[0] = 0;
1256 new->len = (int) len + header_size;
1257 new->val = m;
1259 #ifdef HAVE_DHCP6
1260 else if (comma && (opt_len & OT_CSTRING))
1262 /* length fields are two bytes so need 16 bits for each string */
1263 int i, commas = 1;
1264 unsigned char *p, *newp;
1266 for (i = 0; comma[i]; i++)
1267 if (comma[i] == ',')
1268 commas++;
1270 newp = opt_malloc(strlen(comma)+(2*commas));
1271 p = newp;
1272 arg = comma;
1273 comma = split(arg);
1275 while (arg && *arg)
1277 u16 len = strlen(arg);
1278 unhide_metas(arg);
1279 PUTSHORT(len, p);
1280 memcpy(p, arg, len);
1281 p += len;
1283 arg = comma;
1284 comma = split(arg);
1287 new->val = newp;
1288 new->len = p - newp;
1290 else if (comma && (opt_len & OT_RFC1035_NAME))
1292 unsigned char *p = NULL, *newp, *end;
1293 int len = 0;
1294 arg = comma;
1295 comma = split(arg);
1297 while (arg && *arg)
1299 char *dom = canonicalise_opt(arg);
1300 if (!dom)
1301 ret_err(_("bad domain in dhcp-option"));
1303 newp = opt_malloc(len + strlen(dom) + 2);
1305 if (p)
1307 memcpy(newp, p, len);
1308 free(p);
1311 p = newp;
1312 end = do_rfc1035_name(p + len, dom);
1313 *end++ = 0;
1314 len = end - p;
1315 free(dom);
1317 arg = comma;
1318 comma = split(arg);
1321 new->val = p;
1322 new->len = len;
1324 #endif
1325 else
1327 new->len = strlen(comma);
1328 /* keep terminating zero on string */
1329 new->val = (unsigned char *)opt_string_alloc(comma);
1330 new->flags |= DHOPT_STRING;
1335 if (!is6 &&
1336 ((new->len > 255) ||
1337 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1338 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
1339 ret_err(_("dhcp-option too long"));
1341 if (flags == DHOPT_MATCH)
1343 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1344 !new->netid ||
1345 new->netid->next)
1346 ret_err(_("illegal dhcp-match"));
1348 if (is6)
1350 new->next = daemon->dhcp_match6;
1351 daemon->dhcp_match6 = new;
1353 else
1355 new->next = daemon->dhcp_match;
1356 daemon->dhcp_match = new;
1359 else if (is6)
1361 new->next = daemon->dhcp_opts6;
1362 daemon->dhcp_opts6 = new;
1364 else
1366 new->next = daemon->dhcp_opts;
1367 daemon->dhcp_opts = new;
1370 return 1;
1373 #endif
1375 void set_option_bool(unsigned int opt)
1377 if (opt < 32)
1378 daemon->options |= 1u << opt;
1379 else
1380 daemon->options2 |= 1u << (opt - 32);
1383 void reset_option_bool(unsigned int opt)
1385 if (opt < 32)
1386 daemon->options &= ~(1u << opt);
1387 else
1388 daemon->options2 &= ~(1u << (opt - 32));
1391 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only)
1393 int i;
1394 char *comma;
1396 if (option == '?')
1397 ret_err(gen_err);
1399 for (i=0; usage[i].opt != 0; i++)
1400 if (usage[i].opt == option)
1402 int rept = usage[i].rept;
1404 if (command_line)
1406 /* command line */
1407 if (rept == ARG_USED_CL)
1408 ret_err(_("illegal repeated flag"));
1409 if (rept == ARG_ONE)
1410 usage[i].rept = ARG_USED_CL;
1412 else
1414 /* allow file to override command line */
1415 if (rept == ARG_USED_FILE)
1416 ret_err(_("illegal repeated keyword"));
1417 if (rept == ARG_USED_CL || rept == ARG_ONE)
1418 usage[i].rept = ARG_USED_FILE;
1421 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1423 set_option_bool(rept);
1424 return 1;
1427 break;
1430 switch (option)
1432 case 'C': /* --conf-file */
1434 char *file = opt_string_alloc(arg);
1435 if (file)
1437 one_file(file, 0);
1438 free(file);
1440 break;
1443 case '7': /* --conf-dir */
1445 DIR *dir_stream;
1446 struct dirent *ent;
1447 char *directory, *path;
1448 struct list {
1449 char *suffix;
1450 struct list *next;
1451 } *ignore_suffix = NULL, *li;
1453 comma = split(arg);
1454 if (!(directory = opt_string_alloc(arg)))
1455 break;
1457 for (arg = comma; arg; arg = comma)
1459 comma = split(arg);
1460 li = opt_malloc(sizeof(struct list));
1461 li->next = ignore_suffix;
1462 ignore_suffix = li;
1463 /* Have to copy: buffer is overwritten */
1464 li->suffix = opt_string_alloc(arg);
1467 if (!(dir_stream = opendir(directory)))
1468 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1470 while ((ent = readdir(dir_stream)))
1472 size_t len = strlen(ent->d_name);
1473 struct stat buf;
1475 /* ignore emacs backups and dotfiles */
1476 if (len == 0 ||
1477 ent->d_name[len - 1] == '~' ||
1478 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1479 ent->d_name[0] == '.')
1480 continue;
1482 for (li = ignore_suffix; li; li = li->next)
1484 /* check for proscribed suffices */
1485 size_t ls = strlen(li->suffix);
1486 if (len > ls &&
1487 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1488 break;
1490 if (li)
1491 continue;
1493 path = opt_malloc(strlen(directory) + len + 2);
1494 strcpy(path, directory);
1495 strcat(path, "/");
1496 strcat(path, ent->d_name);
1498 /* files must be readable */
1499 if (stat(path, &buf) == -1)
1500 die(_("cannot access %s: %s"), path, EC_FILE);
1502 /* only reg files allowed. */
1503 if (S_ISREG(buf.st_mode))
1504 one_file(path, 0);
1506 free(path);
1509 closedir(dir_stream);
1510 free(directory);
1511 for(; ignore_suffix; ignore_suffix = li)
1513 li = ignore_suffix->next;
1514 free(ignore_suffix->suffix);
1515 free(ignore_suffix);
1518 break;
1521 case LOPT_ADD_SBNET: /* --add-subnet */
1522 set_option_bool(OPT_CLIENT_SUBNET);
1523 if (arg)
1525 comma = split(arg);
1526 if (!atoi_check(arg, &daemon->addr4_netmask) ||
1527 (comma && !atoi_check(comma, &daemon->addr6_netmask)))
1528 ret_err(gen_err);
1530 break;
1532 case '1': /* --enable-dbus */
1533 set_option_bool(OPT_DBUS);
1534 if (arg)
1535 daemon->dbus_name = opt_string_alloc(arg);
1536 else
1537 daemon->dbus_name = DNSMASQ_SERVICE;
1538 break;
1540 case '8': /* --log-facility */
1541 /* may be a filename */
1542 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1543 daemon->log_file = opt_string_alloc(arg);
1544 else
1546 #ifdef __ANDROID__
1547 ret_err(_("setting log facility is not possible under Android"));
1548 #else
1549 for (i = 0; facilitynames[i].c_name; i++)
1550 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1551 break;
1553 if (facilitynames[i].c_name)
1554 daemon->log_fac = facilitynames[i].c_val;
1555 else
1556 ret_err(_("bad log facility"));
1557 #endif
1559 break;
1561 case 'x': /* --pid-file */
1562 daemon->runfile = opt_string_alloc(arg);
1563 break;
1565 case 'r': /* --resolv-file */
1567 char *name = opt_string_alloc(arg);
1568 struct resolvc *new, *list = daemon->resolv_files;
1570 if (list && list->is_default)
1572 /* replace default resolv file - possibly with nothing */
1573 if (name)
1575 list->is_default = 0;
1576 list->name = name;
1578 else
1579 list = NULL;
1581 else if (name)
1583 new = opt_malloc(sizeof(struct resolvc));
1584 new->next = list;
1585 new->name = name;
1586 new->is_default = 0;
1587 new->mtime = 0;
1588 new->logged = 0;
1589 list = new;
1591 daemon->resolv_files = list;
1592 break;
1595 case LOPT_SERVERS_FILE:
1596 daemon->servers_file = opt_string_alloc(arg);
1597 break;
1599 case 'm': /* --mx-host */
1601 int pref = 1;
1602 struct mx_srv_record *new;
1603 char *name, *target = NULL;
1605 if ((comma = split(arg)))
1607 char *prefstr;
1608 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1609 ret_err(_("bad MX preference"));
1612 if (!(name = canonicalise_opt(arg)) ||
1613 (comma && !(target = canonicalise_opt(comma))))
1614 ret_err(_("bad MX name"));
1616 new = opt_malloc(sizeof(struct mx_srv_record));
1617 new->next = daemon->mxnames;
1618 daemon->mxnames = new;
1619 new->issrv = 0;
1620 new->name = name;
1621 new->target = target; /* may be NULL */
1622 new->weight = pref;
1623 break;
1626 case 't': /* --mx-target */
1627 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1628 ret_err(_("bad MX target"));
1629 break;
1631 #ifdef HAVE_DHCP
1632 case 'l': /* --dhcp-leasefile */
1633 daemon->lease_file = opt_string_alloc(arg);
1634 break;
1636 /* Sorry about the gross pre-processor abuse */
1637 case '6': /* --dhcp-script */
1638 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1639 # if defined(NO_FORK)
1640 ret_err(_("cannot run scripts under uClinux"));
1641 # elif !defined(HAVE_SCRIPT)
1642 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
1643 # else
1644 if (option == LOPT_LUASCRIPT)
1645 # if !defined(HAVE_LUASCRIPT)
1646 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
1647 # else
1648 daemon->luascript = opt_string_alloc(arg);
1649 # endif
1650 else
1651 daemon->lease_change_command = opt_string_alloc(arg);
1652 # endif
1653 break;
1654 #endif /* HAVE_DHCP */
1656 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1657 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1658 case 'H': /* --addn-hosts */
1660 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1661 static int hosts_index = 1;
1662 new->fname = opt_string_alloc(arg);
1663 new->index = hosts_index++;
1664 new->flags = 0;
1665 if (option == 'H')
1667 new->next = daemon->addn_hosts;
1668 daemon->addn_hosts = new;
1670 else if (option == LOPT_DHCP_HOST)
1672 new->next = daemon->dhcp_hosts_file;
1673 daemon->dhcp_hosts_file = new;
1675 else if (option == LOPT_DHCP_OPTS)
1677 new->next = daemon->dhcp_opts_file;
1678 daemon->dhcp_opts_file = new;
1680 break;
1684 #ifdef HAVE_AUTH
1685 case LOPT_AUTHSERV: /* --auth-server */
1686 if (!(comma = split(arg)))
1687 ret_err(gen_err);
1689 daemon->authserver = opt_string_alloc(arg);
1690 arg = comma;
1691 do {
1692 struct iname *new = opt_malloc(sizeof(struct iname));
1693 comma = split(arg);
1694 new->name = NULL;
1695 unhide_metas(arg);
1696 if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
1697 new->addr.sa.sa_family = AF_INET;
1698 #ifdef HAVE_IPV6
1699 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1700 new->addr.sa.sa_family = AF_INET6;
1701 #endif
1702 else
1704 char *fam = split_chr(arg, '/');
1705 new->name = opt_string_alloc(arg);
1706 new->addr.sa.sa_family = 0;
1707 if (fam)
1709 if (strcmp(fam, "4") == 0)
1710 new->addr.sa.sa_family = AF_INET;
1711 #ifdef HAVE_IPV6
1712 else if (strcmp(fam, "6") == 0)
1713 new->addr.sa.sa_family = AF_INET6;
1714 #endif
1715 else
1716 ret_err(gen_err);
1719 new->next = daemon->authinterface;
1720 daemon->authinterface = new;
1722 arg = comma;
1723 } while (arg);
1725 break;
1727 case LOPT_AUTHSFS: /* --auth-sec-servers */
1729 struct name_list *new;
1731 do {
1732 comma = split(arg);
1733 new = opt_malloc(sizeof(struct name_list));
1734 new->name = opt_string_alloc(arg);
1735 new->next = daemon->secondary_forward_server;
1736 daemon->secondary_forward_server = new;
1737 arg = comma;
1738 } while (arg);
1739 break;
1742 case LOPT_AUTHZONE: /* --auth-zone */
1744 struct auth_zone *new;
1746 comma = split(arg);
1748 new = opt_malloc(sizeof(struct auth_zone));
1749 new->domain = opt_string_alloc(arg);
1750 new->subnet = NULL;
1751 new->interface_names = NULL;
1752 new->next = daemon->auth_zones;
1753 daemon->auth_zones = new;
1755 while ((arg = comma))
1757 int prefixlen = 0;
1758 char *prefix;
1759 struct addrlist *subnet = NULL;
1760 struct all_addr addr;
1762 comma = split(arg);
1763 prefix = split_chr(arg, '/');
1765 if (prefix && !atoi_check(prefix, &prefixlen))
1766 ret_err(gen_err);
1768 if (inet_pton(AF_INET, arg, &addr.addr.addr4))
1770 subnet = opt_malloc(sizeof(struct addrlist));
1771 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
1772 subnet->flags = ADDRLIST_LITERAL;
1774 #ifdef HAVE_IPV6
1775 else if (inet_pton(AF_INET6, arg, &addr.addr.addr6))
1777 subnet = opt_malloc(sizeof(struct addrlist));
1778 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
1779 subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
1781 #endif
1782 else
1784 struct auth_name_list *name = opt_malloc(sizeof(struct auth_name_list));
1785 name->name = opt_string_alloc(arg);
1786 name->flags = AUTH4 | AUTH6;
1787 name->next = new->interface_names;
1788 new->interface_names = name;
1789 if (prefix)
1791 if (prefixlen == 4)
1792 name->flags &= ~AUTH6;
1793 #ifdef HAVE_IPV6
1794 else if (prefixlen == 6)
1795 name->flags &= ~AUTH4;
1796 #endif
1797 else
1798 ret_err(gen_err);
1802 if (subnet)
1804 subnet->addr = addr;
1805 subnet->next = new->subnet;
1806 new->subnet = subnet;
1809 break;
1812 case LOPT_AUTHSOA: /* --auth-soa */
1813 comma = split(arg);
1814 daemon->soa_sn = (u32)atoi(arg);
1815 if (comma)
1817 char *cp;
1818 arg = comma;
1819 comma = split(arg);
1820 daemon->hostmaster = opt_string_alloc(arg);
1821 for (cp = daemon->hostmaster; *cp; cp++)
1822 if (*cp == '@')
1823 *cp = '.';
1825 if (comma)
1827 arg = comma;
1828 comma = split(arg);
1829 daemon->soa_refresh = (u32)atoi(arg);
1830 if (comma)
1832 arg = comma;
1833 comma = split(arg);
1834 daemon->soa_retry = (u32)atoi(arg);
1835 if (comma)
1837 arg = comma;
1838 comma = split(arg);
1839 daemon->soa_expiry = (u32)atoi(arg);
1845 break;
1846 #endif
1848 case 's': /* --domain */
1849 case LOPT_SYNTH: /* --synth-domain */
1850 if (strcmp (arg, "#") == 0)
1851 set_option_bool(OPT_RESOLV_DOMAIN);
1852 else
1854 char *d;
1855 comma = split(arg);
1856 if (!(d = canonicalise_opt(arg)))
1857 ret_err(gen_err);
1858 else
1860 if (comma)
1862 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
1863 char *netpart;
1865 new->prefix = NULL;
1867 unhide_metas(comma);
1868 if ((netpart = split_chr(comma, '/')))
1870 int msize;
1872 arg = split(netpart);
1873 if (!atoi_check(netpart, &msize))
1874 ret_err(gen_err);
1875 else if (inet_pton(AF_INET, comma, &new->start))
1877 int mask = (1 << (32 - msize)) - 1;
1878 new->is6 = 0;
1879 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1880 new->end.s_addr = new->start.s_addr | htonl(mask);
1881 if (arg)
1883 if (option != 's')
1885 if (!(new->prefix = canonicalise_opt(arg)) ||
1886 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1887 ret_err(_("bad prefix"));
1889 else if (strcmp(arg, "local") != 0 ||
1890 (msize != 8 && msize != 16 && msize != 24))
1891 ret_err(gen_err);
1892 else
1894 /* generate the equivalent of
1895 local=/<domain>/
1896 local=/xxx.yyy.zzz.in-addr.arpa/ */
1897 struct server *serv = add_rev4(new->start, msize);
1898 serv->flags |= SERV_NO_ADDR;
1902 #ifdef HAVE_IPV6
1903 else if (inet_pton(AF_INET6, comma, &new->start6))
1905 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1906 u64 addrpart = addr6part(&new->start6);
1907 new->is6 = 1;
1909 /* prefix==64 overflows the mask calculation above */
1910 if (msize == 64)
1911 mask = (u64)-1LL;
1913 new->end6 = new->start6;
1914 setaddr6part(&new->start6, addrpart & ~mask);
1915 setaddr6part(&new->end6, addrpart | mask);
1917 if (msize < 64)
1918 ret_err(gen_err);
1919 else if (arg)
1921 if (option != 's')
1923 if (!(new->prefix = canonicalise_opt(arg)) ||
1924 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
1925 ret_err(_("bad prefix"));
1927 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
1928 ret_err(gen_err);
1929 else
1931 /* generate the equivalent of
1932 local=/<domain>/
1933 local=/xxx.yyy.zzz.ip6.arpa/ */
1934 struct server *serv = add_rev6(&new->start6, msize);
1935 serv->flags |= SERV_NO_ADDR;
1939 #endif
1940 else
1941 ret_err(gen_err);
1943 else
1945 char *prefstr;
1946 arg = split(comma);
1947 prefstr = split(arg);
1949 if (inet_pton(AF_INET, comma, &new->start))
1951 new->is6 = 0;
1952 if (!arg)
1953 new->end.s_addr = new->start.s_addr;
1954 else if (!inet_pton(AF_INET, arg, &new->end))
1955 ret_err(gen_err);
1957 #ifdef HAVE_IPV6
1958 else if (inet_pton(AF_INET6, comma, &new->start6))
1960 new->is6 = 1;
1961 if (!arg)
1962 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1963 else if (!inet_pton(AF_INET6, arg, &new->end6))
1964 ret_err(gen_err);
1966 #endif
1967 else
1968 ret_err(gen_err);
1970 if (option != 's' && prefstr)
1972 if (!(new->prefix = canonicalise_opt(prefstr)) ||
1973 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1974 ret_err(_("bad prefix"));
1978 new->domain = d;
1979 if (option == 's')
1981 new->next = daemon->cond_domain;
1982 daemon->cond_domain = new;
1984 else
1986 new->next = daemon->synth_domains;
1987 daemon->synth_domains = new;
1990 else if (option == 's')
1991 daemon->domain_suffix = d;
1992 else
1993 ret_err(gen_err);
1996 break;
1998 case 'u': /* --user */
1999 daemon->username = opt_string_alloc(arg);
2000 break;
2002 case 'g': /* --group */
2003 daemon->groupname = opt_string_alloc(arg);
2004 daemon->group_set = 1;
2005 break;
2007 #ifdef HAVE_DHCP
2008 case LOPT_SCRIPTUSR: /* --scriptuser */
2009 daemon->scriptuser = opt_string_alloc(arg);
2010 break;
2011 #endif
2013 case 'i': /* --interface */
2014 do {
2015 struct iname *new = opt_malloc(sizeof(struct iname));
2016 comma = split(arg);
2017 new->next = daemon->if_names;
2018 daemon->if_names = new;
2019 /* new->name may be NULL if someone does
2020 "interface=" to disable all interfaces except loop. */
2021 new->name = opt_string_alloc(arg);
2022 new->used = 0;
2023 arg = comma;
2024 } while (arg);
2025 break;
2027 case LOPT_TFTP: /* --enable-tftp */
2028 set_option_bool(OPT_TFTP);
2029 if (!arg)
2030 break;
2031 /* fall through */
2033 case 'I': /* --except-interface */
2034 case '2': /* --no-dhcp-interface */
2035 do {
2036 struct iname *new = opt_malloc(sizeof(struct iname));
2037 comma = split(arg);
2038 new->name = opt_string_alloc(arg);
2039 if (option == 'I')
2041 new->next = daemon->if_except;
2042 daemon->if_except = new;
2044 else if (option == LOPT_TFTP)
2046 new->next = daemon->tftp_interfaces;
2047 daemon->tftp_interfaces = new;
2049 else
2051 new->next = daemon->dhcp_except;
2052 daemon->dhcp_except = new;
2054 arg = comma;
2055 } while (arg);
2056 break;
2058 case 'B': /* --bogus-nxdomain */
2060 struct in_addr addr;
2061 unhide_metas(arg);
2062 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
2064 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
2065 baddr->next = daemon->bogus_addr;
2066 daemon->bogus_addr = baddr;
2067 baddr->addr = addr;
2069 else
2070 ret_err(gen_err); /* error */
2071 break;
2074 case 'a': /* --listen-address */
2075 case LOPT_AUTHPEER: /* --auth-peer */
2076 do {
2077 struct iname *new = opt_malloc(sizeof(struct iname));
2078 comma = split(arg);
2079 unhide_metas(arg);
2080 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
2082 new->addr.sa.sa_family = AF_INET;
2083 new->addr.in.sin_port = 0;
2084 #ifdef HAVE_SOCKADDR_SA_LEN
2085 new->addr.in.sin_len = sizeof(new->addr.in);
2086 #endif
2088 #ifdef HAVE_IPV6
2089 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
2091 new->addr.sa.sa_family = AF_INET6;
2092 new->addr.in6.sin6_flowinfo = 0;
2093 new->addr.in6.sin6_scope_id = 0;
2094 new->addr.in6.sin6_port = 0;
2095 #ifdef HAVE_SOCKADDR_SA_LEN
2096 new->addr.in6.sin6_len = sizeof(new->addr.in6);
2097 #endif
2099 #endif
2100 else
2101 ret_err(gen_err);
2103 new->used = 0;
2104 if (option == 'a')
2106 new->next = daemon->if_addrs;
2107 daemon->if_addrs = new;
2109 else
2111 new->next = daemon->auth_peers;
2112 daemon->auth_peers = new;
2114 arg = comma;
2115 } while (arg);
2116 break;
2118 case 'S': /* --server */
2119 case LOPT_LOCAL: /* --local */
2120 case 'A': /* --address */
2121 case LOPT_NO_REBIND: /* --rebind-domain-ok */
2123 struct server *serv, *newlist = NULL;
2125 unhide_metas(arg);
2127 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
2129 int rebind = !(*arg == '/');
2130 char *end = NULL;
2131 if (!rebind)
2132 arg++;
2133 while (rebind || (end = split_chr(arg, '/')))
2135 char *domain = NULL;
2136 /* elide leading dots - they are implied in the search algorithm */
2137 while (*arg == '.') arg++;
2138 /* # matches everything and becomes a zero length domain string */
2139 if (strcmp(arg, "#") == 0)
2140 domain = "";
2141 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
2142 option = '?';
2143 serv = opt_malloc(sizeof(struct server));
2144 memset(serv, 0, sizeof(struct server));
2145 serv->next = newlist;
2146 newlist = serv;
2147 serv->domain = domain;
2148 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
2149 arg = end;
2150 if (rebind)
2151 break;
2153 if (!newlist)
2154 ret_err(gen_err);
2156 else
2158 newlist = opt_malloc(sizeof(struct server));
2159 memset(newlist, 0, sizeof(struct server));
2162 if (servers_only && option == 'S')
2163 newlist->flags |= SERV_FROM_FILE;
2165 if (option == 'A')
2167 newlist->flags |= SERV_LITERAL_ADDRESS;
2168 if (!(newlist->flags & SERV_TYPE))
2169 ret_err(gen_err);
2171 else if (option == LOPT_NO_REBIND)
2172 newlist->flags |= SERV_NO_REBIND;
2174 if (!arg || !*arg)
2176 if (!(newlist->flags & SERV_NO_REBIND))
2177 newlist->flags |= SERV_NO_ADDR; /* no server */
2178 if (newlist->flags & SERV_LITERAL_ADDRESS)
2179 ret_err(gen_err);
2182 else if (strcmp(arg, "#") == 0)
2184 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
2185 if (newlist->flags & SERV_LITERAL_ADDRESS)
2186 ret_err(gen_err);
2188 else
2190 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2191 if (err)
2192 ret_err(err);
2195 serv = newlist;
2196 while (serv->next)
2198 serv->next->flags = serv->flags;
2199 serv->next->addr = serv->addr;
2200 serv->next->source_addr = serv->source_addr;
2201 strcpy(serv->next->interface, serv->interface);
2202 serv = serv->next;
2204 serv->next = daemon->servers;
2205 daemon->servers = newlist;
2206 break;
2209 case LOPT_REV_SERV: /* --rev-server */
2211 char *string;
2212 int size;
2213 struct server *serv;
2214 struct in_addr addr4;
2215 #ifdef HAVE_IPV6
2216 struct in6_addr addr6;
2217 #endif
2219 unhide_metas(arg);
2220 if (!arg || !(comma=split(arg)) || !(string = split_chr(arg, '/')) || !atoi_check(string, &size))
2221 ret_err(gen_err);
2223 if (inet_pton(AF_INET, arg, &addr4))
2224 serv = add_rev4(addr4, size);
2225 #ifdef HAVE_IPV6
2226 else if (inet_pton(AF_INET6, arg, &addr6))
2227 serv = add_rev6(&addr6, size);
2228 #endif
2229 else
2230 ret_err(gen_err);
2232 string = parse_server(comma, &serv->addr, &serv->source_addr, serv->interface, &serv->flags);
2234 if (string)
2235 ret_err(string);
2237 if (servers_only)
2238 serv->flags |= SERV_FROM_FILE;
2240 break;
2243 case LOPT_IPSET: /* --ipset */
2244 #ifndef HAVE_IPSET
2245 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2246 break;
2247 #else
2249 struct ipsets ipsets_head;
2250 struct ipsets *ipsets = &ipsets_head;
2251 int size;
2252 char *end;
2253 char **sets, **sets_pos;
2254 memset(ipsets, 0, sizeof(struct ipsets));
2255 unhide_metas(arg);
2256 if (arg && *arg == '/')
2258 arg++;
2259 while ((end = split_chr(arg, '/')))
2261 char *domain = NULL;
2262 /* elide leading dots - they are implied in the search algorithm */
2263 while (*arg == '.')
2264 arg++;
2265 /* # matches everything and becomes a zero length domain string */
2266 if (strcmp(arg, "#") == 0 || !*arg)
2267 domain = "";
2268 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2269 option = '?';
2270 ipsets->next = opt_malloc(sizeof(struct ipsets));
2271 ipsets = ipsets->next;
2272 memset(ipsets, 0, sizeof(struct ipsets));
2273 ipsets->domain = domain;
2274 arg = end;
2277 else
2279 ipsets->next = opt_malloc(sizeof(struct ipsets));
2280 ipsets = ipsets->next;
2281 memset(ipsets, 0, sizeof(struct ipsets));
2282 ipsets->domain = "";
2284 if (!arg || !*arg)
2286 option = '?';
2287 break;
2289 size = 2;
2290 for (end = arg; *end; ++end)
2291 if (*end == ',')
2292 ++size;
2294 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2296 do {
2297 end = split(arg);
2298 *sets_pos++ = opt_string_alloc(arg);
2299 arg = end;
2300 } while (end);
2301 *sets_pos = 0;
2302 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2303 ipsets->next->sets = sets;
2304 ipsets->next = daemon->ipsets;
2305 daemon->ipsets = ipsets_head.next;
2307 break;
2309 #endif
2311 case 'c': /* --cache-size */
2313 int size;
2315 if (!atoi_check(arg, &size))
2316 ret_err(gen_err);
2317 else
2319 /* zero is OK, and means no caching. */
2321 if (size < 0)
2322 size = 0;
2323 else if (size > 10000)
2324 size = 10000;
2326 daemon->cachesize = size;
2328 break;
2331 case 'p': /* --port */
2332 if (!atoi_check16(arg, &daemon->port))
2333 ret_err(gen_err);
2334 break;
2336 case LOPT_MINPORT: /* --min-port */
2337 if (!atoi_check16(arg, &daemon->min_port))
2338 ret_err(gen_err);
2339 break;
2341 case '0': /* --dns-forward-max */
2342 if (!atoi_check(arg, &daemon->ftabsize))
2343 ret_err(gen_err);
2344 break;
2346 case LOPT_MAX_LOGS: /* --log-async */
2347 daemon->max_logs = LOG_MAX; /* default */
2348 if (arg && !atoi_check(arg, &daemon->max_logs))
2349 ret_err(gen_err);
2350 else if (daemon->max_logs > 100)
2351 daemon->max_logs = 100;
2352 break;
2354 case 'P': /* --edns-packet-max */
2356 int i;
2357 if (!atoi_check(arg, &i))
2358 ret_err(gen_err);
2359 daemon->edns_pktsz = (unsigned short)i;
2360 break;
2363 case 'Q': /* --query-port */
2364 if (!atoi_check16(arg, &daemon->query_port))
2365 ret_err(gen_err);
2366 /* if explicitly set to zero, use single OS ephemeral port
2367 and disable random ports */
2368 if (daemon->query_port == 0)
2369 daemon->osport = 1;
2370 break;
2372 case 'T': /* --local-ttl */
2373 case LOPT_NEGTTL: /* --neg-ttl */
2374 case LOPT_MAXTTL: /* --max-ttl */
2375 case LOPT_MAXCTTL: /* --max-cache-ttl */
2376 case LOPT_AUTHTTL: /* --auth-ttl */
2378 int ttl;
2379 if (!atoi_check(arg, &ttl))
2380 ret_err(gen_err);
2381 else if (option == LOPT_NEGTTL)
2382 daemon->neg_ttl = (unsigned long)ttl;
2383 else if (option == LOPT_MAXTTL)
2384 daemon->max_ttl = (unsigned long)ttl;
2385 else if (option == LOPT_MAXCTTL)
2386 daemon->max_cache_ttl = (unsigned long)ttl;
2387 else if (option == LOPT_AUTHTTL)
2388 daemon->auth_ttl = (unsigned long)ttl;
2389 else
2390 daemon->local_ttl = (unsigned long)ttl;
2391 break;
2394 #ifdef HAVE_DHCP
2395 case 'X': /* --dhcp-lease-max */
2396 if (!atoi_check(arg, &daemon->dhcp_max))
2397 ret_err(gen_err);
2398 break;
2399 #endif
2401 #ifdef HAVE_TFTP
2402 case LOPT_TFTP_MAX: /* --tftp-max */
2403 if (!atoi_check(arg, &daemon->tftp_max))
2404 ret_err(gen_err);
2405 break;
2407 case LOPT_PREFIX: /* --tftp-prefix */
2408 comma = split(arg);
2409 if (comma)
2411 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2412 new->interface = opt_string_alloc(comma);
2413 new->prefix = opt_string_alloc(arg);
2414 new->next = daemon->if_prefix;
2415 daemon->if_prefix = new;
2417 else
2418 daemon->tftp_prefix = opt_string_alloc(arg);
2419 break;
2421 case LOPT_TFTPPORTS: /* --tftp-port-range */
2422 if (!(comma = split(arg)) ||
2423 !atoi_check16(arg, &daemon->start_tftp_port) ||
2424 !atoi_check16(comma, &daemon->end_tftp_port))
2425 ret_err(_("bad port range"));
2427 if (daemon->start_tftp_port > daemon->end_tftp_port)
2429 int tmp = daemon->start_tftp_port;
2430 daemon->start_tftp_port = daemon->end_tftp_port;
2431 daemon->end_tftp_port = tmp;
2434 break;
2435 #endif
2437 case LOPT_BRIDGE: /* --bridge-interface */
2439 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2440 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2441 ret_err(_("bad bridge-interface"));
2443 strcpy(new->iface, arg);
2444 new->alias = NULL;
2445 new->next = daemon->bridges;
2446 daemon->bridges = new;
2448 do {
2449 arg = comma;
2450 comma = split(arg);
2451 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2453 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2454 b->next = new->alias;
2455 new->alias = b;
2456 strcpy(b->iface, arg);
2458 } while (comma);
2460 break;
2463 #ifdef HAVE_DHCP
2464 case 'F': /* --dhcp-range */
2466 int k, leasepos = 2;
2467 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2468 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2470 memset (new, 0, sizeof(*new));
2471 new->lease_time = DEFLEASE;
2473 if (!arg)
2475 option = '?';
2476 break;
2479 while(1)
2481 for (cp = arg; *cp; cp++)
2482 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2483 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2484 (*cp >='0' && *cp <= '9')))
2485 break;
2487 if (*cp != ',' && (comma = split(arg)))
2489 if (is_tag_prefix(arg))
2491 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2492 tt->net = opt_string_alloc(arg+4);
2493 tt->next = new->filter;
2494 /* ignore empty tag */
2495 if (tt->net)
2496 new->filter = tt;
2498 else
2500 if (new->netid.net)
2501 ret_err(_("only one tag allowed"));
2502 else if (strstr(arg, "set:") == arg)
2503 new->netid.net = opt_string_alloc(arg+4);
2504 else
2505 new->netid.net = opt_string_alloc(arg);
2507 arg = comma;
2509 else
2511 a[0] = arg;
2512 break;
2516 for (k = 1; k < 8; k++)
2517 if (!(a[k] = split(a[k-1])))
2518 break;
2520 if (k < 2)
2521 ret_err(_("bad dhcp-range"));
2523 if (inet_pton(AF_INET, a[0], &new->start))
2525 new->next = daemon->dhcp;
2526 daemon->dhcp = new;
2527 new->end = new->start;
2528 if (strcmp(a[1], "static") == 0)
2529 new->flags |= CONTEXT_STATIC;
2530 else if (strcmp(a[1], "proxy") == 0)
2531 new->flags |= CONTEXT_PROXY;
2532 else if (!inet_pton(AF_INET, a[1], &new->end))
2533 ret_err(_("bad dhcp-range"));
2535 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2537 struct in_addr tmp = new->start;
2538 new->start = new->end;
2539 new->end = tmp;
2542 if (k >= 3 && strchr(a[2], '.') &&
2543 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
2545 new->flags |= CONTEXT_NETMASK;
2546 leasepos = 3;
2547 if (!is_same_net(new->start, new->end, new->netmask))
2548 ret_err(_("inconsistent DHCP range"));
2551 if (k >= 4 && strchr(a[3], '.') &&
2552 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
2554 new->flags |= CONTEXT_BRDCAST;
2555 leasepos = 4;
2558 #ifdef HAVE_DHCP6
2559 else if (inet_pton(AF_INET6, a[0], &new->start6))
2561 new->flags |= CONTEXT_V6;
2562 new->prefix = 64; /* default */
2563 new->end6 = new->start6;
2564 new->next = daemon->dhcp6;
2565 daemon->dhcp6 = new;
2567 for (leasepos = 1; leasepos < k; leasepos++)
2569 if (strcmp(a[leasepos], "static") == 0)
2570 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2571 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2572 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
2573 else if (strcmp(a[leasepos], "ra-names") == 0)
2574 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
2575 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2576 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
2577 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2578 new->flags |= CONTEXT_DHCP;
2579 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2581 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2582 new->flags |= CONTEXT_TEMPLATE;
2584 else
2585 break;
2588 /* bare integer < 128 is prefix value */
2589 if (leasepos < k)
2591 int pref;
2592 for (cp = a[leasepos]; *cp; cp++)
2593 if (!(*cp >= '0' && *cp <= '9'))
2594 break;
2595 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
2597 new->prefix = pref;
2598 leasepos++;
2602 if (new->prefix != 64)
2604 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2605 ret_err(_("prefix length must be exactly 64 for RA subnets"));
2606 else if (new->flags & CONTEXT_TEMPLATE)
2607 ret_err(_("prefix length must be exactly 64 for subnet constructors"));
2610 if (new->prefix < 64)
2611 ret_err(_("prefix length must be at least 64"));
2613 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2614 ret_err(_("inconsistent DHCPv6 range"));
2616 /* dhcp-range=:: enables DHCP stateless on any interface */
2617 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
2618 new->prefix = 0;
2620 if (new->flags & CONTEXT_TEMPLATE)
2622 struct in6_addr zero;
2623 memset(&zero, 0, sizeof(zero));
2624 if (!is_same_net6(&zero, &new->start6, new->prefix))
2625 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2628 if (addr6part(&new->start6) > addr6part(&new->end6))
2630 struct in6_addr tmp = new->start6;
2631 new->start6 = new->end6;
2632 new->end6 = tmp;
2635 #endif
2636 else
2637 ret_err(_("bad dhcp-range"));
2639 if (leasepos < k)
2641 if (strcmp(a[leasepos], "infinite") == 0)
2642 new->lease_time = 0xffffffff;
2643 else if (strcmp(a[leasepos], "deprecated") == 0)
2644 new->flags |= CONTEXT_DEPRECATE;
2645 else
2647 int fac = 1;
2648 if (strlen(a[leasepos]) > 0)
2650 switch (a[leasepos][strlen(a[leasepos]) - 1])
2652 case 'w':
2653 case 'W':
2654 fac *= 7;
2655 /* fall through */
2656 case 'd':
2657 case 'D':
2658 fac *= 24;
2659 /* fall though */
2660 case 'h':
2661 case 'H':
2662 fac *= 60;
2663 /* fall through */
2664 case 'm':
2665 case 'M':
2666 fac *= 60;
2667 /* fall through */
2668 case 's':
2669 case 'S':
2670 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2673 for (cp = a[leasepos]; *cp; cp++)
2674 if (!(*cp >= '0' && *cp <= '9'))
2675 break;
2677 if (*cp || (leasepos+1 < k))
2678 ret_err(_("bad dhcp-range"));
2680 new->lease_time = atoi(a[leasepos]) * fac;
2681 /* Leases of a minute or less confuse
2682 some clients, notably Apple's */
2683 if (new->lease_time < 120)
2684 new->lease_time = 120;
2688 break;
2691 case LOPT_BANK:
2692 case 'G': /* --dhcp-host */
2694 int j, k = 0;
2695 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2696 struct dhcp_config *new;
2697 struct in_addr in;
2699 new = opt_malloc(sizeof(struct dhcp_config));
2701 new->next = daemon->dhcp_conf;
2702 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2703 new->hwaddr = NULL;
2704 new->netid = NULL;
2706 if ((a[0] = arg))
2707 for (k = 1; k < 7; k++)
2708 if (!(a[k] = split(a[k-1])))
2709 break;
2711 for (j = 0; j < k; j++)
2712 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2714 char *arg = a[j];
2716 if ((arg[0] == 'i' || arg[0] == 'I') &&
2717 (arg[1] == 'd' || arg[1] == 'D') &&
2718 arg[2] == ':')
2720 if (arg[3] == '*')
2721 new->flags |= CONFIG_NOCLID;
2722 else
2724 int len;
2725 arg += 3; /* dump id: */
2726 if (strchr(arg, ':'))
2727 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2728 else
2730 unhide_metas(arg);
2731 len = (int) strlen(arg);
2734 if (len == -1)
2736 ret_err(_("bad hex constant"));
2737 else if ((new->clid = opt_malloc(len)))
2739 new->flags |= CONFIG_CLID;
2740 new->clid_len = len;
2741 memcpy(new->clid, arg, len);
2745 /* dhcp-host has strange backwards-compat needs. */
2746 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2748 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2749 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2750 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2751 newlist->next = new->netid;
2752 new->netid = newlist;
2753 newlist->list = newtag;
2754 strcpy(newtag->net, arg+4);
2755 unhide_metas(newtag->net);
2757 else if (strstr(arg, "tag:") == arg)
2758 ret_err(_("cannot match tags in --dhcp-host"));
2759 #ifdef HAVE_DHCP6
2760 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2762 arg[strlen(arg)-1] = 0;
2763 arg++;
2765 if (!inet_pton(AF_INET6, arg, &new->addr6))
2766 ret_err(_("bad IPv6 address"));
2768 for (i= 0; i < 8; i++)
2769 if (new->addr6.s6_addr[i] != 0)
2770 break;
2772 /* set WILDCARD if network part all zeros */
2773 if (i == 8)
2774 new->flags |= CONFIG_WILDCARD;
2776 new->flags |= CONFIG_ADDR6;
2778 #endif
2779 else
2781 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2782 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2783 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2784 ret_err(_("bad hex constant"));
2785 else
2788 newhw->next = new->hwaddr;
2789 new->hwaddr = newhw;
2793 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
2795 struct dhcp_config *configs;
2797 new->addr = in;
2798 new->flags |= CONFIG_ADDR;
2800 /* If the same IP appears in more than one host config, then DISCOVER
2801 for one of the hosts will get the address, but REQUEST will be NAKed,
2802 since the address is reserved by the other one -> protocol loop. */
2803 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2804 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2806 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2807 return 0;
2810 else
2812 char *cp, *lastp = NULL, last = 0;
2813 int fac = 1, isdig = 0;
2815 if (strlen(a[j]) > 1)
2817 lastp = a[j] + strlen(a[j]) - 1;
2818 last = *lastp;
2819 switch (last)
2821 case 'w':
2822 case 'W':
2823 fac *= 7;
2824 /* fall through */
2825 case 'd':
2826 case 'D':
2827 fac *= 24;
2828 /* fall through */
2829 case 'h':
2830 case 'H':
2831 fac *= 60;
2832 /* fall through */
2833 case 'm':
2834 case 'M':
2835 fac *= 60;
2836 /* fall through */
2837 case 's':
2838 case 'S':
2839 *lastp = 0;
2843 for (cp = a[j]; *cp; cp++)
2844 if (isdigit((unsigned char)*cp))
2845 isdig = 1;
2846 else if (*cp != ' ')
2847 break;
2849 if (*cp)
2851 if (lastp)
2852 *lastp = last;
2853 if (strcmp(a[j], "infinite") == 0)
2855 new->lease_time = 0xffffffff;
2856 new->flags |= CONFIG_TIME;
2858 else if (strcmp(a[j], "ignore") == 0)
2859 new->flags |= CONFIG_DISABLE;
2860 else
2862 if (!(new->hostname = canonicalise_opt(a[j])) ||
2863 !legal_hostname(new->hostname))
2864 ret_err(_("bad DHCP host name"));
2866 new->flags |= CONFIG_NAME;
2867 new->domain = strip_hostname(new->hostname);
2870 else if (isdig)
2872 new->lease_time = atoi(a[j]) * fac;
2873 /* Leases of a minute or less confuse
2874 some clients, notably Apple's */
2875 if (new->lease_time < 120)
2876 new->lease_time = 120;
2877 new->flags |= CONFIG_TIME;
2881 daemon->dhcp_conf = new;
2882 break;
2885 case LOPT_TAG_IF: /* --tag-if */
2887 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2889 new->tag = NULL;
2890 new->set = NULL;
2891 new->next = NULL;
2893 /* preserve order */
2894 if (!daemon->tag_if)
2895 daemon->tag_if = new;
2896 else
2898 struct tag_if *tmp;
2899 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2900 tmp->next = new;
2903 while (arg)
2905 size_t len;
2907 comma = split(arg);
2908 len = strlen(arg);
2910 if (len < 5)
2912 new->set = NULL;
2913 break;
2915 else
2917 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2918 newtag->net = opt_malloc(len - 3);
2919 strcpy(newtag->net, arg+4);
2920 unhide_metas(newtag->net);
2922 if (strstr(arg, "set:") == arg)
2924 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2925 newlist->next = new->set;
2926 new->set = newlist;
2927 newlist->list = newtag;
2929 else if (strstr(arg, "tag:") == arg)
2931 newtag->next = new->tag;
2932 new->tag = newtag;
2934 else
2936 new->set = NULL;
2937 free(newtag);
2938 break;
2942 arg = comma;
2945 if (!new->set)
2946 ret_err(_("bad tag-if"));
2948 break;
2952 case 'O': /* --dhcp-option */
2953 case LOPT_FORCE: /* --dhcp-option-force */
2954 case LOPT_OPTS:
2955 case LOPT_MATCH: /* --dhcp-match */
2956 return parse_dhcp_opt(errstr, arg,
2957 option == LOPT_FORCE ? DHOPT_FORCE :
2958 (option == LOPT_MATCH ? DHOPT_MATCH :
2959 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2961 case 'M': /* --dhcp-boot */
2963 struct dhcp_netid *id = NULL;
2964 while (is_tag_prefix(arg))
2966 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2967 newid->next = id;
2968 id = newid;
2969 comma = split(arg);
2970 newid->net = opt_string_alloc(arg+4);
2971 arg = comma;
2974 if (!arg)
2975 ret_err(gen_err);
2976 else
2978 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2979 struct in_addr dhcp_next_server;
2980 struct dhcp_boot *new;
2981 comma = split(arg);
2982 dhcp_file = opt_string_alloc(arg);
2983 dhcp_next_server.s_addr = 0;
2984 if (comma)
2986 arg = comma;
2987 comma = split(arg);
2988 dhcp_sname = opt_string_alloc(arg);
2989 if (comma)
2991 unhide_metas(comma);
2992 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2995 * The user may have specified the tftp hostname here.
2996 * save it so that it can be resolved/looked up during
2997 * actual dhcp_reply().
3000 tftp_sname = opt_string_alloc(comma);
3001 dhcp_next_server.s_addr = 0;
3006 new = opt_malloc(sizeof(struct dhcp_boot));
3007 new->file = dhcp_file;
3008 new->sname = dhcp_sname;
3009 new->tftp_sname = tftp_sname;
3010 new->next_server = dhcp_next_server;
3011 new->netid = id;
3012 new->next = daemon->boot_config;
3013 daemon->boot_config = new;
3016 break;
3019 case LOPT_PXE_PROMT: /* --pxe-prompt */
3021 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
3022 int timeout;
3024 new->netid = NULL;
3025 new->opt = 10; /* PXE_MENU_PROMPT */
3027 while (is_tag_prefix(arg))
3029 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
3030 comma = split(arg);
3031 nn->next = new->netid;
3032 new->netid = nn;
3033 nn->net = opt_string_alloc(arg+4);
3034 arg = comma;
3037 if (!arg)
3038 ret_err(gen_err);
3039 else
3041 comma = split(arg);
3042 unhide_metas(arg);
3043 new->len = strlen(arg) + 1;
3044 new->val = opt_malloc(new->len);
3045 memcpy(new->val + 1, arg, new->len - 1);
3047 new->u.vendor_class = (unsigned char *)"PXEClient";
3048 new->flags = DHOPT_VENDOR;
3050 if (comma && atoi_check(comma, &timeout))
3051 *(new->val) = timeout;
3052 else
3053 *(new->val) = 255;
3055 new->next = daemon->dhcp_opts;
3056 daemon->dhcp_opts = new;
3057 daemon->enable_pxe = 1;
3060 break;
3063 case LOPT_PXE_SERV: /* --pxe-service */
3065 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
3066 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
3067 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
3068 static int boottype = 32768;
3070 new->netid = NULL;
3071 new->sname = NULL;
3072 new->server.s_addr = 0;
3074 while (is_tag_prefix(arg))
3076 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
3077 comma = split(arg);
3078 nn->next = new->netid;
3079 new->netid = nn;
3080 nn->net = opt_string_alloc(arg+4);
3081 arg = comma;
3084 if (arg && (comma = split(arg)))
3086 for (i = 0; CSA[i]; i++)
3087 if (strcasecmp(CSA[i], arg) == 0)
3088 break;
3090 if (CSA[i] || atoi_check(arg, &i))
3092 arg = comma;
3093 comma = split(arg);
3095 new->CSA = i;
3096 new->menu = opt_string_alloc(arg);
3098 if (!comma)
3100 new->type = 0; /* local boot */
3101 new->basename = NULL;
3103 else
3105 arg = comma;
3106 comma = split(arg);
3107 if (atoi_check(arg, &i))
3109 new->type = i;
3110 new->basename = NULL;
3112 else
3114 new->type = boottype++;
3115 new->basename = opt_string_alloc(arg);
3118 if (comma)
3120 if (!inet_pton(AF_INET, comma, &new->server))
3122 new->server.s_addr = 0;
3123 new->sname = opt_string_alloc(comma);
3129 /* Order matters */
3130 new->next = NULL;
3131 if (!daemon->pxe_services)
3132 daemon->pxe_services = new;
3133 else
3135 struct pxe_service *s;
3136 for (s = daemon->pxe_services; s->next; s = s->next);
3137 s->next = new;
3140 daemon->enable_pxe = 1;
3141 break;
3146 ret_err(gen_err);
3149 case '4': /* --dhcp-mac */
3151 if (!(comma = split(arg)))
3152 ret_err(gen_err);
3153 else
3155 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
3156 new->netid.net = opt_string_alloc(set_prefix(arg));
3157 unhide_metas(comma);
3158 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
3159 if (new->hwaddr_len == -1)
3160 ret_err(gen_err);
3161 else
3163 new->next = daemon->dhcp_macs;
3164 daemon->dhcp_macs = new;
3168 break;
3170 #ifdef OPTION6_PREFIX_CLASS
3171 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3173 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3175 if (!(comma = split(arg)) ||
3176 !atoi_check16(comma, &new->class))
3177 ret_err(gen_err);
3179 new->tag.net = opt_string_alloc(set_prefix(arg));
3180 new->next = daemon->prefix_classes;
3181 daemon->prefix_classes = new;
3183 break;
3185 #endif
3188 case 'U': /* --dhcp-vendorclass */
3189 case 'j': /* --dhcp-userclass */
3190 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3191 case LOPT_REMOTE: /* --dhcp-remoteid */
3192 case LOPT_SUBSCR: /* --dhcp-subscrid */
3194 unsigned char *p;
3195 int dig = 0;
3196 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3198 if (!(comma = split(arg)))
3199 ret_err(gen_err);
3201 new->netid.net = opt_string_alloc(set_prefix(arg));
3202 /* check for hex string - must digits may include : must not have nothing else,
3203 only allowed for agent-options. */
3205 arg = comma;
3206 if ((comma = split(arg)))
3208 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3209 ret_err(gen_err);
3210 else
3211 new->enterprise = atoi(arg+11);
3213 else
3214 comma = arg;
3216 for (p = (unsigned char *)comma; *p; p++)
3217 if (isxdigit(*p))
3218 dig = 1;
3219 else if (*p != ':')
3220 break;
3221 unhide_metas(comma);
3222 if (option == 'U' || option == 'j' || *p || !dig)
3224 new->len = strlen(comma);
3225 new->data = opt_malloc(new->len);
3226 memcpy(new->data, comma, new->len);
3228 else
3230 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3231 new->data = opt_malloc(new->len);
3232 memcpy(new->data, comma, new->len);
3235 switch (option)
3237 case 'j':
3238 new->match_type = MATCH_USER;
3239 break;
3240 case 'U':
3241 new->match_type = MATCH_VENDOR;
3242 break;
3243 case LOPT_CIRCUIT:
3244 new->match_type = MATCH_CIRCUIT;
3245 break;
3246 case LOPT_REMOTE:
3247 new->match_type = MATCH_REMOTE;
3248 break;
3249 case LOPT_SUBSCR:
3250 new->match_type = MATCH_SUBSCRIBER;
3251 break;
3253 new->next = daemon->dhcp_vendors;
3254 daemon->dhcp_vendors = new;
3256 break;
3259 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3260 if (!arg)
3262 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3263 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3265 else
3267 comma = split(arg);
3268 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3269 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
3270 ret_err(_("invalid port number"));
3271 if (!comma)
3272 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3274 break;
3276 case 'J': /* --dhcp-ignore */
3277 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3278 case LOPT_BROADCAST: /* --dhcp-broadcast */
3279 case '3': /* --bootp-dynamic */
3280 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
3282 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
3283 struct dhcp_netid *list = NULL;
3284 if (option == 'J')
3286 new->next = daemon->dhcp_ignore;
3287 daemon->dhcp_ignore = new;
3289 else if (option == LOPT_BROADCAST)
3291 new->next = daemon->force_broadcast;
3292 daemon->force_broadcast = new;
3294 else if (option == '3')
3296 new->next = daemon->bootp_dynamic;
3297 daemon->bootp_dynamic = new;
3299 else if (option == LOPT_GEN_NAMES)
3301 new->next = daemon->dhcp_gen_names;
3302 daemon->dhcp_gen_names = new;
3304 else
3306 new->next = daemon->dhcp_ignore_names;
3307 daemon->dhcp_ignore_names = new;
3310 while (arg) {
3311 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3312 comma = split(arg);
3313 member->next = list;
3314 list = member;
3315 if (is_tag_prefix(arg))
3316 member->net = opt_string_alloc(arg+4);
3317 else
3318 member->net = opt_string_alloc(arg);
3319 arg = comma;
3322 new->list = list;
3323 break;
3326 case LOPT_PROXY: /* --dhcp-proxy */
3327 daemon->override = 1;
3328 while (arg) {
3329 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3330 comma = split(arg);
3331 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
3332 ret_err(_("bad dhcp-proxy address"));
3333 new->next = daemon->override_relays;
3334 daemon->override_relays = new;
3335 arg = comma;
3337 break;
3339 case LOPT_RELAY: /* --dhcp-relay */
3341 struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
3342 comma = split(arg);
3343 new->interface = opt_string_alloc(split(comma));
3344 new->iface_index = 0;
3345 if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
3347 new->next = daemon->relay4;
3348 daemon->relay4 = new;
3350 #ifdef HAVE_DHCP6
3351 else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
3353 new->next = daemon->relay6;
3354 daemon->relay6 = new;
3356 #endif
3357 else
3358 ret_err(_("Bad dhcp-relay"));
3360 break;
3363 #endif
3365 #ifdef HAVE_DHCP6
3366 case LOPT_RA_PARAM: /* --ra-param */
3367 if ((comma = split(arg)))
3369 struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
3370 new->lifetime = -1;
3371 new->prio = 0;
3372 new->name = opt_string_alloc(arg);
3373 if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
3375 if (*comma == 'l' || *comma == 'L')
3376 new->prio = 0x18;
3377 else
3378 new->prio = 0x08;
3379 comma = split(comma);
3381 arg = split(comma);
3382 if (!atoi_check(comma, &new->interval) ||
3383 (arg && !atoi_check(arg, &new->lifetime)))
3384 ret_err(_("bad RA-params"));
3386 new->next = daemon->ra_interfaces;
3387 daemon->ra_interfaces = new;
3389 break;
3391 case LOPT_DUID: /* --dhcp-duid */
3392 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
3393 ret_err(_("bad DUID"));
3394 else
3396 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3397 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3398 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3400 break;
3401 #endif
3403 case 'V': /* --alias */
3405 char *dash, *a[3] = { NULL, NULL, NULL };
3406 int k = 0;
3407 struct doctor *new = opt_malloc(sizeof(struct doctor));
3408 new->next = daemon->doctors;
3409 daemon->doctors = new;
3410 new->mask.s_addr = 0xffffffff;
3411 new->end.s_addr = 0;
3413 if ((a[0] = arg))
3414 for (k = 1; k < 3; k++)
3416 if (!(a[k] = split(a[k-1])))
3417 break;
3418 unhide_metas(a[k]);
3421 dash = split_chr(a[0], '-');
3423 if ((k < 2) ||
3424 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3425 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
3426 option = '?';
3428 if (k == 3)
3429 inet_pton(AF_INET, a[2], &new->mask);
3431 if (dash &&
3432 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
3433 !is_same_net(new->in, new->end, new->mask) ||
3434 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3435 ret_err(_("invalid alias range"));
3437 break;
3440 case LOPT_INTNAME: /* --interface-name */
3442 struct interface_name *new, **up;
3443 char *domain = NULL;
3445 comma = split(arg);
3447 if (!comma || !(domain = canonicalise_opt(arg)))
3448 ret_err(_("bad interface name"));
3450 new = opt_malloc(sizeof(struct interface_name));
3451 new->next = NULL;
3452 new->addr = NULL;
3454 /* Add to the end of the list, so that first name
3455 of an interface is used for PTR lookups. */
3456 for (up = &daemon->int_names; *up; up = &((*up)->next));
3457 *up = new;
3458 new->name = domain;
3459 new->family = 0;
3460 arg = split_chr(comma, '/');
3461 if (arg)
3463 if (strcmp(arg, "4") == 0)
3464 new->family = AF_INET;
3465 #ifdef HAVE_IPV6
3466 else if (strcmp(arg, "6") == 0)
3467 new->family = AF_INET6;
3468 #endif
3469 else
3470 ret_err(gen_err);
3472 new->intr = opt_string_alloc(comma);
3473 break;
3476 case LOPT_CNAME: /* --cname */
3478 struct cname *new;
3479 char *alias;
3480 char *target;
3482 if (!(comma = split(arg)))
3483 ret_err(gen_err);
3485 alias = canonicalise_opt(arg);
3486 target = canonicalise_opt(comma);
3488 if (!alias || !target)
3489 ret_err(_("bad CNAME"));
3490 else
3492 for (new = daemon->cnames; new; new = new->next)
3493 if (hostname_isequal(new->alias, arg))
3494 ret_err(_("duplicate CNAME"));
3495 new = opt_malloc(sizeof(struct cname));
3496 new->next = daemon->cnames;
3497 daemon->cnames = new;
3498 new->alias = alias;
3499 new->target = target;
3502 break;
3505 case LOPT_PTR: /* --ptr-record */
3507 struct ptr_record *new;
3508 char *dom, *target = NULL;
3510 comma = split(arg);
3512 if (!(dom = canonicalise_opt(arg)) ||
3513 (comma && !(target = canonicalise_opt(comma))))
3514 ret_err(_("bad PTR record"));
3515 else
3517 new = opt_malloc(sizeof(struct ptr_record));
3518 new->next = daemon->ptr;
3519 daemon->ptr = new;
3520 new->name = dom;
3521 new->ptr = target;
3523 break;
3526 case LOPT_NAPTR: /* --naptr-record */
3528 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3529 int k = 0;
3530 struct naptr *new;
3531 int order, pref;
3532 char *name, *replace = NULL;
3534 if ((a[0] = arg))
3535 for (k = 1; k < 7; k++)
3536 if (!(a[k] = split(a[k-1])))
3537 break;
3540 if (k < 6 ||
3541 !(name = canonicalise_opt(a[0])) ||
3542 !atoi_check16(a[1], &order) ||
3543 !atoi_check16(a[2], &pref) ||
3544 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3545 ret_err(_("bad NAPTR record"));
3546 else
3548 new = opt_malloc(sizeof(struct naptr));
3549 new->next = daemon->naptr;
3550 daemon->naptr = new;
3551 new->name = name;
3552 new->flags = opt_string_alloc(a[3]);
3553 new->services = opt_string_alloc(a[4]);
3554 new->regexp = opt_string_alloc(a[5]);
3555 new->replace = replace;
3556 new->order = order;
3557 new->pref = pref;
3559 break;
3562 case LOPT_RR: /* dns-rr */
3564 struct txt_record *new;
3565 size_t len = len;
3566 char *data;
3567 int val;
3569 comma = split(arg);
3570 data = split(comma);
3572 new = opt_malloc(sizeof(struct txt_record));
3573 new->next = daemon->rr;
3574 daemon->rr = new;
3576 if (!atoi_check(comma, &val) ||
3577 !(new->name = canonicalise_opt(arg)) ||
3578 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
3579 ret_err(_("bad RR record"));
3581 new->class = val;
3582 new->len = 0;
3584 if (data)
3586 new->txt=opt_malloc(len);
3587 new->len = len;
3588 memcpy(new->txt, data, len);
3591 break;
3594 case 'Y': /* --txt-record */
3596 struct txt_record *new;
3597 unsigned char *p, *cnt;
3598 size_t len;
3600 comma = split(arg);
3602 new = opt_malloc(sizeof(struct txt_record));
3603 new->next = daemon->txt;
3604 daemon->txt = new;
3605 new->class = C_IN;
3607 if (!(new->name = canonicalise_opt(arg)))
3608 ret_err(_("bad TXT record"));
3610 len = comma ? strlen(comma) : 0;
3611 len += (len/255) + 1; /* room for extra counts */
3612 new->txt = p = opt_malloc(len);
3614 cnt = p++;
3615 *cnt = 0;
3617 while (comma && *comma)
3619 unsigned char c = (unsigned char)*comma++;
3621 if (c == ',' || *cnt == 255)
3623 if (c != ',')
3624 comma--;
3625 cnt = p++;
3626 *cnt = 0;
3628 else
3630 *p++ = unhide_meta(c);
3631 (*cnt)++;
3635 new->len = p - new->txt;
3637 break;
3640 case 'W': /* --srv-host */
3642 int port = 1, priority = 0, weight = 0;
3643 char *name, *target = NULL;
3644 struct mx_srv_record *new;
3646 comma = split(arg);
3648 if (!(name = canonicalise_opt(arg)))
3649 ret_err(_("bad SRV record"));
3651 if (comma)
3653 arg = comma;
3654 comma = split(arg);
3655 if (!(target = canonicalise_opt(arg)))
3656 ret_err(_("bad SRV target"));
3658 if (comma)
3660 arg = comma;
3661 comma = split(arg);
3662 if (!atoi_check16(arg, &port))
3663 ret_err(_("invalid port number"));
3665 if (comma)
3667 arg = comma;
3668 comma = split(arg);
3669 if (!atoi_check16(arg, &priority))
3670 ret_err(_("invalid priority"));
3672 if (comma)
3674 arg = comma;
3675 comma = split(arg);
3676 if (!atoi_check16(arg, &weight))
3677 ret_err(_("invalid weight"));
3683 new = opt_malloc(sizeof(struct mx_srv_record));
3684 new->next = daemon->mxnames;
3685 daemon->mxnames = new;
3686 new->issrv = 1;
3687 new->name = name;
3688 new->target = target;
3689 new->srvport = port;
3690 new->priority = priority;
3691 new->weight = weight;
3692 break;
3695 case LOPT_HOST_REC: /* --host-record */
3697 struct host_record *new = opt_malloc(sizeof(struct host_record));
3698 memset(new, 0, sizeof(struct host_record));
3700 if (!arg || !(comma = split(arg)))
3701 ret_err(_("Bad host-record"));
3703 while (arg)
3705 struct all_addr addr;
3706 if (inet_pton(AF_INET, arg, &addr))
3707 new->addr = addr.addr.addr4;
3708 #ifdef HAVE_IPV6
3709 else if (inet_pton(AF_INET6, arg, &addr))
3710 new->addr6 = addr.addr.addr6;
3711 #endif
3712 else
3714 int nomem;
3715 char *canon = canonicalise(arg, &nomem);
3716 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3717 if (!canon)
3718 ret_err(_("Bad name in host-record"));
3720 nl->name = canon;
3721 /* keep order, so that PTR record goes to first name */
3722 nl->next = NULL;
3723 if (!new->names)
3724 new->names = nl;
3725 else
3727 struct name_list *tmp;
3728 for (tmp = new->names; tmp->next; tmp = tmp->next);
3729 tmp->next = nl;
3733 arg = comma;
3734 comma = split(arg);
3737 /* Keep list order */
3738 if (!daemon->host_records_tail)
3739 daemon->host_records = new;
3740 else
3741 daemon->host_records_tail->next = new;
3742 new->next = NULL;
3743 daemon->host_records_tail = new;
3744 break;
3747 #ifdef HAVE_DNSSEC
3748 case LOPT_TRUST_ANCHOR:
3750 struct ds_config *new = opt_malloc(sizeof(struct ds_config));
3751 char *cp, *cp1, *keyhex, *digest, *algo = NULL;
3752 int len;
3754 new->class = C_IN;
3756 if ((comma = split(arg)) && (algo = split(comma)))
3758 int class = 0;
3759 if (strcmp(comma, "IN") == 0)
3760 class = C_IN;
3761 else if (strcmp(comma, "CH") == 0)
3762 class = C_CHAOS;
3763 else if (strcmp(comma, "HS") == 0)
3764 class = C_HESIOD;
3766 if (class != 0)
3768 new->class = class;
3769 comma = algo;
3770 algo = split(comma);
3774 if (!comma || !algo || !(digest = split(algo)) || !(keyhex = split(digest)) ||
3775 !atoi_check16(comma, &new->keytag) ||
3776 !atoi_check8(algo, &new->algo) ||
3777 !atoi_check8(digest, &new->digest_type) ||
3778 !(new->name = canonicalise_opt(arg)))
3779 ret_err(_("bad trust anchor"));
3781 /* Upper bound on length */
3782 len = (2*strlen(keyhex))+1;
3783 new->digest = opt_malloc(len);
3784 unhide_metas(keyhex);
3785 /* 4034: "Whitespace is allowed within digits" */
3786 for (cp = keyhex; *cp; )
3787 if (isspace(*cp))
3788 for (cp1 = cp; *cp1; cp1++)
3789 *cp1 = *(cp1+1);
3790 else
3791 cp++;
3792 if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1)
3793 ret_err(_("bad HEX in trust anchor"));
3795 new->next = daemon->ds;
3796 daemon->ds = new;
3798 break;
3800 #endif
3802 default:
3803 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
3807 return 1;
3810 static void read_file(char *file, FILE *f, int hard_opt)
3812 volatile int lineno = 0;
3813 char *buff = daemon->namebuff;
3815 while (fgets(buff, MAXDNAME, f))
3817 int white, i;
3818 volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
3819 char *errmess, *p, *arg = NULL, *start;
3820 size_t len;
3822 /* Memory allocation failure longjmps here if mem_recover == 1 */
3823 if (option != 0 || hard_opt == LOPT_REV_SERV)
3825 if (setjmp(mem_jmp))
3826 continue;
3827 mem_recover = 1;
3830 lineno++;
3831 errmess = NULL;
3833 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3834 metacharacters get hidden also strip comments */
3835 for (white = 1, p = buff; *p; p++)
3837 if (*p == '"')
3839 memmove(p, p+1, strlen(p+1)+1);
3841 for(; *p && *p != '"'; p++)
3843 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3845 if (p[1] == 't')
3846 p[1] = '\t';
3847 else if (p[1] == 'n')
3848 p[1] = '\n';
3849 else if (p[1] == 'b')
3850 p[1] = '\b';
3851 else if (p[1] == 'r')
3852 p[1] = '\r';
3853 else if (p[1] == 'e') /* escape */
3854 p[1] = '\033';
3855 memmove(p, p+1, strlen(p+1)+1);
3857 *p = hide_meta(*p);
3860 if (*p == 0)
3862 errmess = _("missing \"");
3863 goto oops;
3866 memmove(p, p+1, strlen(p+1)+1);
3869 if (isspace(*p))
3871 *p = ' ';
3872 white = 1;
3874 else
3876 if (white && *p == '#')
3878 *p = 0;
3879 break;
3881 white = 0;
3886 /* strip leading spaces */
3887 for (start = buff; *start && *start == ' '; start++);
3889 /* strip trailing spaces */
3890 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3892 if (len == 0)
3893 continue;
3894 else
3895 start[len] = 0;
3897 if (option != 0)
3898 arg = start;
3899 else if ((p=strchr(start, '=')))
3901 /* allow spaces around "=" */
3902 for (arg = p+1; *arg == ' '; arg++);
3903 for (; p >= start && (*p == ' ' || *p == '='); p--)
3904 *p = 0;
3906 else
3907 arg = NULL;
3909 if (option == 0)
3911 for (option = 0, i = 0; opts[i].name; i++)
3912 if (strcmp(opts[i].name, start) == 0)
3914 option = opts[i].val;
3915 break;
3918 if (!option)
3919 errmess = _("bad option");
3920 else if (opts[i].has_arg == 0 && arg)
3921 errmess = _("extraneous parameter");
3922 else if (opts[i].has_arg == 1 && !arg)
3923 errmess = _("missing parameter");
3924 else if (hard_opt == LOPT_REV_SERV && option != 'S' && option != LOPT_REV_SERV)
3925 errmess = _("illegal option");
3928 oops:
3929 if (errmess)
3930 strcpy(daemon->namebuff, errmess);
3932 if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
3934 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
3935 if (hard_opt != 0)
3936 my_syslog(LOG_ERR, "%s", daemon->namebuff);
3937 else
3938 die("%s", daemon->namebuff, EC_BADCONF);
3942 mem_recover = 0;
3943 fclose(f);
3946 static int one_file(char *file, int hard_opt)
3948 FILE *f;
3949 int nofile_ok = 0;
3950 static int read_stdin = 0;
3951 static struct fileread {
3952 dev_t dev;
3953 ino_t ino;
3954 struct fileread *next;
3955 } *filesread = NULL;
3957 if (hard_opt == '7')
3959 /* default conf-file reading */
3960 hard_opt = 0;
3961 nofile_ok = 1;
3964 if (hard_opt == 0 && strcmp(file, "-") == 0)
3966 if (read_stdin == 1)
3967 return 1;
3968 read_stdin = 1;
3969 file = "stdin";
3970 f = stdin;
3972 else
3974 /* ignore repeated files. */
3975 struct stat statbuf;
3977 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3979 struct fileread *r;
3981 for (r = filesread; r; r = r->next)
3982 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3983 return 1;
3985 r = safe_malloc(sizeof(struct fileread));
3986 r->next = filesread;
3987 filesread = r;
3988 r->dev = statbuf.st_dev;
3989 r->ino = statbuf.st_ino;
3992 if (!(f = fopen(file, "r")))
3994 if (errno == ENOENT && nofile_ok)
3995 return 1; /* No conffile, all done. */
3996 else
3998 char *str = _("cannot read %s: %s");
3999 if (hard_opt != 0)
4001 my_syslog(LOG_ERR, str, file, strerror(errno));
4002 return 0;
4004 else
4005 die(str, file, EC_FILE);
4010 read_file(file, f, hard_opt);
4011 return 1;
4014 /* expand any name which is a directory */
4015 struct hostsfile *expand_filelist(struct hostsfile *list)
4017 int i;
4018 struct hostsfile *ah;
4020 for (i = 0, ah = list; ah; ah = ah->next)
4022 if (i <= ah->index)
4023 i = ah->index + 1;
4025 if (ah->flags & AH_DIR)
4026 ah->flags |= AH_INACTIVE;
4027 else
4028 ah->flags &= ~AH_INACTIVE;
4031 for (ah = list; ah; ah = ah->next)
4032 if (!(ah->flags & AH_INACTIVE))
4034 struct stat buf;
4035 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
4037 DIR *dir_stream;
4038 struct dirent *ent;
4040 /* don't read this as a file */
4041 ah->flags |= AH_INACTIVE;
4043 if (!(dir_stream = opendir(ah->fname)))
4044 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
4045 ah->fname, strerror(errno));
4046 else
4048 while ((ent = readdir(dir_stream)))
4050 size_t lendir = strlen(ah->fname);
4051 size_t lenfile = strlen(ent->d_name);
4052 struct hostsfile *ah1;
4053 char *path;
4055 /* ignore emacs backups and dotfiles */
4056 if (lenfile == 0 ||
4057 ent->d_name[lenfile - 1] == '~' ||
4058 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
4059 ent->d_name[0] == '.')
4060 continue;
4062 /* see if we have an existing record.
4063 dir is ah->fname
4064 file is ent->d_name
4065 path to match is ah1->fname */
4067 for (ah1 = list; ah1; ah1 = ah1->next)
4069 if (lendir < strlen(ah1->fname) &&
4070 strstr(ah1->fname, ah->fname) == ah1->fname &&
4071 ah1->fname[lendir] == '/' &&
4072 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
4074 ah1->flags &= ~AH_INACTIVE;
4075 break;
4079 /* make new record */
4080 if (!ah1)
4082 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
4083 continue;
4085 if (!(path = whine_malloc(lendir + lenfile + 2)))
4087 free(ah1);
4088 continue;
4091 strcpy(path, ah->fname);
4092 strcat(path, "/");
4093 strcat(path, ent->d_name);
4094 ah1->fname = path;
4095 ah1->index = i++;
4096 ah1->flags = AH_DIR;
4097 ah1->next = list;
4098 list = ah1;
4101 /* inactivate record if not regular file */
4102 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
4103 ah1->flags |= AH_INACTIVE;
4106 closedir(dir_stream);
4111 return list;
4114 void read_servers_file(void)
4116 FILE *f;
4118 if (!(f = fopen(daemon->servers_file, "r")))
4120 my_syslog(LOG_ERR, _("cannot read %s: %s"), daemon->servers_file, strerror(errno));
4121 return;
4124 mark_servers(SERV_FROM_FILE);
4125 cleanup_servers();
4127 read_file(daemon->servers_file, f, LOPT_REV_SERV);
4131 #ifdef HAVE_DHCP
4132 void reread_dhcp(void)
4134 struct hostsfile *hf;
4136 if (daemon->dhcp_hosts_file)
4138 struct dhcp_config *configs, *cp, **up;
4140 /* remove existing... */
4141 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
4143 cp = configs->next;
4145 if (configs->flags & CONFIG_BANK)
4147 struct hwaddr_config *mac, *tmp;
4148 struct dhcp_netid_list *list, *tmplist;
4150 for (mac = configs->hwaddr; mac; mac = tmp)
4152 tmp = mac->next;
4153 free(mac);
4156 if (configs->flags & CONFIG_CLID)
4157 free(configs->clid);
4159 for (list = configs->netid; list; list = tmplist)
4161 free(list->list);
4162 tmplist = list->next;
4163 free(list);
4166 if (configs->flags & CONFIG_NAME)
4167 free(configs->hostname);
4169 *up = configs->next;
4170 free(configs);
4172 else
4173 up = &configs->next;
4176 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
4177 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
4178 if (!(hf->flags & AH_INACTIVE))
4180 if (one_file(hf->fname, LOPT_BANK))
4181 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
4185 if (daemon->dhcp_opts_file)
4187 struct dhcp_opt *opts, *cp, **up;
4188 struct dhcp_netid *id, *next;
4190 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
4192 cp = opts->next;
4194 if (opts->flags & DHOPT_BANK)
4196 if ((opts->flags & DHOPT_VENDOR))
4197 free(opts->u.vendor_class);
4198 free(opts->val);
4199 for (id = opts->netid; id; id = next)
4201 next = id->next;
4202 free(id->net);
4203 free(id);
4205 *up = opts->next;
4206 free(opts);
4208 else
4209 up = &opts->next;
4212 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
4213 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
4214 if (!(hf->flags & AH_INACTIVE))
4216 if (one_file(hf->fname, LOPT_OPTS))
4217 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
4221 #endif
4223 void read_opts(int argc, char **argv, char *compile_opts)
4225 char *buff = opt_malloc(MAXDNAME);
4226 int option, conffile_opt = '7', testmode = 0;
4227 char *arg, *conffile = CONFFILE;
4229 opterr = 0;
4231 daemon = opt_malloc(sizeof(struct daemon));
4232 memset(daemon, 0, sizeof(struct daemon));
4233 daemon->namebuff = buff;
4235 /* Set defaults - everything else is zero or NULL */
4236 daemon->cachesize = CACHESIZ;
4237 daemon->ftabsize = FTABSIZ;
4238 daemon->port = NAMESERVER_PORT;
4239 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
4240 daemon->dhcp_server_port = DHCP_SERVER_PORT;
4241 daemon->default_resolv.is_default = 1;
4242 daemon->default_resolv.name = RESOLVFILE;
4243 daemon->resolv_files = &daemon->default_resolv;
4244 daemon->username = CHUSER;
4245 daemon->runfile = RUNFILE;
4246 daemon->dhcp_max = MAXLEASES;
4247 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
4248 daemon->edns_pktsz = EDNS_PKTSZ;
4249 daemon->log_fac = -1;
4250 daemon->auth_ttl = AUTH_TTL;
4251 daemon->soa_refresh = SOA_REFRESH;
4252 daemon->soa_retry = SOA_RETRY;
4253 daemon->soa_expiry = SOA_EXPIRY;
4254 add_txt("version.bind", "dnsmasq-" VERSION );
4255 add_txt("authors.bind", "Simon Kelley");
4256 add_txt("copyright.bind", COPYRIGHT);
4258 while (1)
4260 #ifdef HAVE_GETOPT_LONG
4261 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
4262 #else
4263 option = getopt(argc, argv, OPTSTRING);
4264 #endif
4266 if (option == -1)
4268 for (; optind < argc; optind++)
4270 unsigned char *c = (unsigned char *)argv[optind];
4271 for (; *c != 0; c++)
4272 if (!isspace(*c))
4273 die(_("junk found in command line"), NULL, EC_BADCONF);
4275 break;
4278 /* Copy optarg so that argv doesn't get changed */
4279 if (optarg)
4281 strncpy(buff, optarg, MAXDNAME);
4282 buff[MAXDNAME-1] = 0;
4283 arg = buff;
4285 else
4286 arg = NULL;
4288 /* command-line only stuff */
4289 if (option == LOPT_TEST)
4290 testmode = 1;
4291 else if (option == 'w')
4293 #ifdef HAVE_DHCP
4294 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
4295 display_opts();
4296 #ifdef HAVE_DHCP6
4297 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4298 display_opts6();
4299 #endif
4300 else
4301 #endif
4302 do_usage();
4304 exit(0);
4306 else if (option == 'v')
4308 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
4309 printf(_("Compile time options: %s\n\n"), compile_opts);
4310 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4311 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
4312 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
4313 exit(0);
4315 else if (option == 'C')
4317 conffile_opt = 0; /* file must exist */
4318 conffile = opt_string_alloc(arg);
4320 else
4322 #ifdef HAVE_GETOPT_LONG
4323 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1, 0))
4324 #else
4325 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0))
4326 #endif
4327 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
4331 if (conffile)
4332 one_file(conffile, conffile_opt);
4334 /* port might not be known when the address is parsed - fill in here */
4335 if (daemon->servers)
4337 struct server *tmp;
4338 for (tmp = daemon->servers; tmp; tmp = tmp->next)
4339 if (!(tmp->flags & SERV_HAS_SOURCE))
4341 if (tmp->source_addr.sa.sa_family == AF_INET)
4342 tmp->source_addr.in.sin_port = htons(daemon->query_port);
4343 #ifdef HAVE_IPV6
4344 else if (tmp->source_addr.sa.sa_family == AF_INET6)
4345 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
4346 #endif
4350 if (daemon->if_addrs)
4352 struct iname *tmp;
4353 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
4354 if (tmp->addr.sa.sa_family == AF_INET)
4355 tmp->addr.in.sin_port = htons(daemon->port);
4356 #ifdef HAVE_IPV6
4357 else if (tmp->addr.sa.sa_family == AF_INET6)
4358 tmp->addr.in6.sin6_port = htons(daemon->port);
4359 #endif /* IPv6 */
4362 /* create default, if not specified */
4363 if (daemon->authserver && !daemon->hostmaster)
4365 strcpy(buff, "hostmaster.");
4366 strcat(buff, daemon->authserver);
4367 daemon->hostmaster = opt_string_alloc(buff);
4370 /* only one of these need be specified: the other defaults to the host-name */
4371 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
4373 struct mx_srv_record *mx;
4375 if (gethostname(buff, MAXDNAME) == -1)
4376 die(_("cannot get host-name: %s"), NULL, EC_MISC);
4378 for (mx = daemon->mxnames; mx; mx = mx->next)
4379 if (!mx->issrv && hostname_isequal(mx->name, buff))
4380 break;
4382 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
4384 mx = opt_malloc(sizeof(struct mx_srv_record));
4385 mx->next = daemon->mxnames;
4386 mx->issrv = 0;
4387 mx->target = NULL;
4388 mx->name = opt_string_alloc(buff);
4389 daemon->mxnames = mx;
4392 if (!daemon->mxtarget)
4393 daemon->mxtarget = opt_string_alloc(buff);
4395 for (mx = daemon->mxnames; mx; mx = mx->next)
4396 if (!mx->issrv && !mx->target)
4397 mx->target = daemon->mxtarget;
4400 if (!option_bool(OPT_NO_RESOLV) &&
4401 daemon->resolv_files &&
4402 daemon->resolv_files->next &&
4403 option_bool(OPT_NO_POLL))
4404 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
4406 if (option_bool(OPT_RESOLV_DOMAIN))
4408 char *line;
4409 FILE *f;
4411 if (option_bool(OPT_NO_RESOLV) ||
4412 !daemon->resolv_files ||
4413 (daemon->resolv_files)->next)
4414 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
4416 if (!(f = fopen((daemon->resolv_files)->name, "r")))
4417 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
4419 while ((line = fgets(buff, MAXDNAME, f)))
4421 char *token = strtok(line, " \t\n\r");
4423 if (!token || strcmp(token, "search") != 0)
4424 continue;
4426 if ((token = strtok(NULL, " \t\n\r")) &&
4427 (daemon->domain_suffix = canonicalise_opt(token)))
4428 break;
4431 fclose(f);
4433 if (!daemon->domain_suffix)
4434 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
4437 if (daemon->domain_suffix)
4439 /* add domain for any srv record without one. */
4440 struct mx_srv_record *srv;
4442 for (srv = daemon->mxnames; srv; srv = srv->next)
4443 if (srv->issrv &&
4444 strchr(srv->name, '.') &&
4445 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4447 strcpy(buff, srv->name);
4448 strcat(buff, ".");
4449 strcat(buff, daemon->domain_suffix);
4450 free(srv->name);
4451 srv->name = opt_string_alloc(buff);
4454 else if (option_bool(OPT_DHCP_FQDN))
4455 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
4457 if (testmode)
4459 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4460 exit(0);