dnsmasq: Update to v2.67test14.
[tomato.git] / release / src / router / dnsmasq / src / option.c
blob70d43fe955fbe643b3b387af9cd8bd9ce8682bd1
1 /* dnsmasq is Copyright (c) 2000-2013 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_FAST_RA 322
136 #define LOPT_RELAY 323
138 #ifdef HAVE_QUIET_DHCP //Originally TOMATO option
139 #define LOPT_QUIET_DHCP 324
140 #define LOPT_QUIET_DHCP6 325
141 #define LOPT_QUIET_RA 326
142 #endif
144 #ifdef HAVE_GETOPT_LONG
145 static const struct option opts[] =
146 #else
147 static const struct myoption opts[] =
148 #endif
150 { "version", 0, 0, 'v' },
151 { "no-hosts", 0, 0, 'h' },
152 { "no-poll", 0, 0, 'n' },
153 { "help", 0, 0, 'w' },
154 { "no-daemon", 0, 0, 'd' },
155 { "log-queries", 0, 0, 'q' },
156 { "user", 2, 0, 'u' },
157 { "group", 2, 0, 'g' },
158 { "resolv-file", 2, 0, 'r' },
159 { "mx-host", 1, 0, 'm' },
160 { "mx-target", 1, 0, 't' },
161 { "cache-size", 2, 0, 'c' },
162 { "port", 1, 0, 'p' },
163 { "dhcp-leasefile", 2, 0, 'l' },
164 { "dhcp-lease", 1, 0, 'l' },
165 { "dhcp-host", 1, 0, 'G' },
166 { "dhcp-range", 1, 0, 'F' },
167 { "dhcp-option", 1, 0, 'O' },
168 { "dhcp-boot", 1, 0, 'M' },
169 { "domain", 1, 0, 's' },
170 { "domain-suffix", 1, 0, 's' },
171 { "interface", 1, 0, 'i' },
172 { "listen-address", 1, 0, 'a' },
173 { "bogus-priv", 0, 0, 'b' },
174 { "bogus-nxdomain", 1, 0, 'B' },
175 { "selfmx", 0, 0, 'e' },
176 { "filterwin2k", 0, 0, 'f' },
177 { "pid-file", 2, 0, 'x' },
178 { "strict-order", 0, 0, 'o' },
179 { "server", 1, 0, 'S' },
180 { "local", 1, 0, LOPT_LOCAL },
181 { "address", 1, 0, 'A' },
182 { "conf-file", 2, 0, 'C' },
183 { "no-resolv", 0, 0, 'R' },
184 { "expand-hosts", 0, 0, 'E' },
185 { "localmx", 0, 0, 'L' },
186 { "local-ttl", 1, 0, 'T' },
187 { "no-negcache", 0, 0, 'N' },
188 { "addn-hosts", 1, 0, 'H' },
189 { "query-port", 1, 0, 'Q' },
190 { "except-interface", 1, 0, 'I' },
191 { "no-dhcp-interface", 1, 0, '2' },
192 { "domain-needed", 0, 0, 'D' },
193 { "dhcp-lease-max", 1, 0, 'X' },
194 { "bind-interfaces", 0, 0, 'z' },
195 { "read-ethers", 0, 0, 'Z' },
196 { "alias", 1, 0, 'V' },
197 { "dhcp-vendorclass", 1, 0, 'U' },
198 { "dhcp-userclass", 1, 0, 'j' },
199 { "dhcp-ignore", 1, 0, 'J' },
200 { "edns-packet-max", 1, 0, 'P' },
201 { "keep-in-foreground", 0, 0, 'k' },
202 { "dhcp-authoritative", 0, 0, 'K' },
203 { "srv-host", 1, 0, 'W' },
204 { "localise-queries", 0, 0, 'y' },
205 { "txt-record", 1, 0, 'Y' },
206 { "dns-rr", 1, 0, LOPT_RR },
207 { "enable-dbus", 2, 0, '1' },
208 { "bootp-dynamic", 2, 0, '3' },
209 { "dhcp-mac", 1, 0, '4' },
210 { "no-ping", 0, 0, '5' },
211 { "dhcp-script", 1, 0, '6' },
212 { "conf-dir", 1, 0, '7' },
213 { "log-facility", 1, 0 ,'8' },
214 { "leasefile-ro", 0, 0, '9' },
215 { "dns-forward-max", 1, 0, '0' },
216 { "clear-on-reload", 0, 0, LOPT_RELOAD },
217 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
218 { "enable-tftp", 2, 0, LOPT_TFTP },
219 { "tftp-secure", 0, 0, LOPT_SECURE },
220 { "tftp-unique-root", 0, 0, LOPT_APREF },
221 { "tftp-root", 1, 0, LOPT_PREFIX },
222 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
223 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
224 { "ptr-record", 1, 0, LOPT_PTR },
225 { "naptr-record", 1, 0, LOPT_NAPTR },
226 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
227 { "dhcp-option-force", 1, 0, LOPT_FORCE },
228 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
229 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
230 { "log-async", 2, 0, LOPT_MAX_LOGS },
231 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
232 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
233 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
234 { "interface-name", 1, 0, LOPT_INTNAME },
235 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
236 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
237 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
238 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
239 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
240 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
241 { "all-servers", 0, 0, LOPT_NOLAST },
242 { "dhcp-match", 1, 0, LOPT_MATCH },
243 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
244 { "neg-ttl", 1, 0, LOPT_NEGTTL },
245 { "max-ttl", 1, 0, LOPT_MAXTTL },
246 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
247 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
248 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
249 { "min-port", 1, 0, LOPT_MINPORT },
250 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
251 { "cname", 1, 0, LOPT_CNAME },
252 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
253 { "pxe-service", 1, 0, LOPT_PXE_SERV },
254 { "test", 0, 0, LOPT_TEST },
255 { "tag-if", 1, 0, LOPT_TAG_IF },
256 { "dhcp-proxy", 2, 0, LOPT_PROXY },
257 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
258 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
259 { "add-mac", 0, 0, LOPT_ADD_MAC },
260 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
261 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
262 { "conntrack", 0, 0, LOPT_CONNTRACK },
263 { "dhcp-client-update", 0, 0, LOPT_FQDN },
264 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
265 { "enable-ra", 0, 0, LOPT_RA },
266 { "dhcp-duid", 1, 0, LOPT_DUID },
267 { "host-record", 1, 0, LOPT_HOST_REC },
268 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
269 { "auth-zone", 1, 0, LOPT_AUTHZONE },
270 { "auth-server", 1, 0, LOPT_AUTHSERV },
271 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
272 { "auth-soa", 1, 0, LOPT_AUTHSOA },
273 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
274 { "auth-peer", 1, 0, LOPT_AUTHPEER },
275 { "ipset", 1, 0, LOPT_IPSET },
276 { "synth-domain", 1, 0, LOPT_SYNTH },
277 #ifdef OPTION6_PREFIX_CLASS
278 { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
279 #endif
280 { "force-fast-ra", 0, 0, LOPT_FAST_RA },
281 { "dhcp-relay", 1, 0, LOPT_RELAY },
282 #ifdef HAVE_QUIET_DHCP //Originally TOMATO option
283 { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
284 { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
285 { "quiet-ra", 0, 0, LOPT_QUIET_RA },
286 #endif
287 { NULL, 0, 0, 0 }
291 #define ARG_DUP OPT_LAST
292 #define ARG_ONE OPT_LAST + 1
293 #define ARG_USED_CL OPT_LAST + 2
294 #define ARG_USED_FILE OPT_LAST + 3
296 static struct {
297 int opt;
298 unsigned int rept;
299 char * const flagdesc;
300 char * const desc;
301 char * const arg;
302 } usage[] = {
303 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
304 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
305 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
306 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
307 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
308 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
309 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
310 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
311 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
312 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
313 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
314 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
315 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
316 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
317 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
318 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
319 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
320 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
321 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
322 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
323 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
324 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
325 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
326 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
327 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
328 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
329 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
330 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
331 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
332 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
333 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
334 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
335 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
336 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
337 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
338 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
339 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
340 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
341 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
342 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
343 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
344 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
345 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
346 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
347 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
348 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
349 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
350 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
351 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
352 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
353 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
354 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
355 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
356 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
357 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
358 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
359 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
360 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
361 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
362 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
363 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
364 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
365 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
366 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
367 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
368 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
369 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
370 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
371 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
372 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
373 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
374 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
375 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
376 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
377 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
378 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
379 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
380 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
381 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
382 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
383 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
384 { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
385 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
386 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
387 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
388 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
389 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
390 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
391 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
392 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
393 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
394 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
395 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
396 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
397 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
398 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
399 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
400 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
401 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
402 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
403 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
404 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
405 { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
406 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
407 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
408 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
409 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
410 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
411 { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
412 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
413 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
414 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
415 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
416 { LOPT_FAST_RA, OPT_FAST_RA, NULL, gettext_noop("Always send frequent router-advertisements"), NULL },
417 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
418 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
419 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
420 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
421 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
422 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
423 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
424 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
425 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
426 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
427 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
428 { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
429 #ifdef OPTION6_PREFIX_CLASS
430 { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
431 #endif
432 #ifdef HAVE_QUIET_DHCP //originally TOMATO option
433 { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log DHCP packets."), NULL },
434 { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log DHCPv6 packets."), NULL },
435 { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA packets."), NULL },
436 #endif
437 { 0, 0, NULL, NULL, NULL }
440 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
441 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
442 following sequence so that they map to themselves: it is therefore possible to call
443 unhide_metas repeatedly on string without breaking things.
444 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
445 couple of other places.
446 Note that space is included here so that
447 --dhcp-option=3, string
448 has five characters, whilst
449 --dhcp-option=3," string"
450 has six.
453 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
455 static char hide_meta(char c)
457 unsigned int i;
459 for (i = 0; i < (sizeof(meta) - 1); i++)
460 if (c == meta[i])
461 return (char)i;
463 return c;
466 static char unhide_meta(char cr)
468 unsigned int c = cr;
470 if (c < (sizeof(meta) - 1))
471 cr = meta[c];
473 return cr;
476 static void unhide_metas(char *cp)
478 if (cp)
479 for(; *cp; cp++)
480 *cp = unhide_meta(*cp);
483 static void *opt_malloc(size_t size)
485 void *ret;
487 if (mem_recover)
489 ret = whine_malloc(size);
490 if (!ret)
491 longjmp(mem_jmp, 1);
493 else
494 ret = safe_malloc(size);
496 return ret;
499 static char *opt_string_alloc(char *cp)
501 char *ret = NULL;
503 if (cp && strlen(cp) != 0)
505 ret = opt_malloc(strlen(cp)+1);
506 strcpy(ret, cp);
508 /* restore hidden metachars */
509 unhide_metas(ret);
512 return ret;
516 /* find next comma, split string with zero and eliminate spaces.
517 return start of string following comma */
519 static char *split_chr(char *s, char c)
521 char *comma, *p;
523 if (!s || !(comma = strchr(s, c)))
524 return NULL;
526 p = comma;
527 *comma = ' ';
529 for (; *comma == ' '; comma++);
531 for (; (p >= s) && *p == ' '; p--)
532 *p = 0;
534 return comma;
537 static char *split(char *s)
539 return split_chr(s, ',');
542 static char *canonicalise_opt(char *s)
544 char *ret;
545 int nomem;
547 if (!s)
548 return 0;
550 unhide_metas(s);
551 if (!(ret = canonicalise(s, &nomem)) && nomem)
553 if (mem_recover)
554 longjmp(mem_jmp, 1);
555 else
556 die(_("could not get memory"), NULL, EC_NOMEM);
559 return ret;
562 static int atoi_check(char *a, int *res)
564 char *p;
566 if (!a)
567 return 0;
569 unhide_metas(a);
571 for (p = a; *p; p++)
572 if (*p < '0' || *p > '9')
573 return 0;
575 *res = atoi(a);
576 return 1;
579 static int atoi_check16(char *a, int *res)
581 if (!(atoi_check(a, res)) ||
582 *res < 0 ||
583 *res > 0xffff)
584 return 0;
586 return 1;
589 static void add_txt(char *name, char *txt)
591 size_t len = strlen(txt);
592 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
594 r->name = opt_string_alloc(name);
595 r->next = daemon->txt;
596 daemon->txt = r;
597 r->class = C_CHAOS;
598 r->txt = opt_malloc(len+1);
599 r->len = len+1;
600 *(r->txt) = len;
601 memcpy((r->txt)+1, txt, len);
604 static void do_usage(void)
606 char buff[100];
607 int i, j;
609 struct {
610 char handle;
611 int val;
612 } tab[] = {
613 { '$', CACHESIZ },
614 { '*', EDNS_PKTSZ },
615 { '&', MAXLEASES },
616 { '!', FTABSIZ },
617 { '#', TFTP_MAX_CONNECTIONS },
618 { '\0', 0 }
621 printf(_("Usage: dnsmasq [options]\n\n"));
622 #ifndef HAVE_GETOPT_LONG
623 printf(_("Use short options only on the command line.\n"));
624 #endif
625 printf(_("Valid options are:\n"));
627 for (i = 0; usage[i].opt != 0; i++)
629 char *desc = usage[i].flagdesc;
630 char *eq = "=";
632 if (!desc || *desc == '[')
633 eq = "";
635 if (!desc)
636 desc = "";
638 for ( j = 0; opts[j].name; j++)
639 if (opts[j].val == usage[i].opt)
640 break;
641 if (usage[i].opt < 256)
642 sprintf(buff, "-%c, ", usage[i].opt);
643 else
644 sprintf(buff, " ");
646 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
647 printf("%-40.40s", buff);
649 if (usage[i].arg)
651 strcpy(buff, usage[i].arg);
652 for (j = 0; tab[j].handle; j++)
653 if (tab[j].handle == *(usage[i].arg))
654 sprintf(buff, "%d", tab[j].val);
656 printf(_(usage[i].desc), buff);
657 printf("\n");
661 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
663 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
665 int source_port = 0, serv_port = NAMESERVER_PORT;
666 char *portno, *source;
667 #ifdef HAVE_IPV6
668 int scope_index = 0;
669 char *scope_id;
670 #endif
672 if ((source = split_chr(arg, '@')) && /* is there a source. */
673 (portno = split_chr(source, '#')) &&
674 !atoi_check16(portno, &source_port))
675 return _("bad port");
677 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
678 !atoi_check16(portno, &serv_port))
679 return _("bad port");
681 #ifdef HAVE_IPV6
682 scope_id = split_chr(arg, '%');
683 #endif
685 if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
687 addr->in.sin_port = htons(serv_port);
688 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
689 #ifdef HAVE_SOCKADDR_SA_LEN
690 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
691 #endif
692 source_addr->in.sin_addr.s_addr = INADDR_ANY;
693 source_addr->in.sin_port = htons(daemon->query_port);
695 if (source)
697 if (flags)
698 *flags |= SERV_HAS_SOURCE;
699 source_addr->in.sin_port = htons(source_port);
700 if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
702 #if defined(SO_BINDTODEVICE)
703 source_addr->in.sin_addr.s_addr = INADDR_ANY;
704 strncpy(interface, source, IF_NAMESIZE - 1);
705 #else
706 return _("interface binding not supported");
707 #endif
711 #ifdef HAVE_IPV6
712 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
714 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
715 return _("bad interface name");
717 addr->in6.sin6_port = htons(serv_port);
718 addr->in6.sin6_scope_id = scope_index;
719 source_addr->in6.sin6_addr = in6addr_any;
720 source_addr->in6.sin6_port = htons(daemon->query_port);
721 source_addr->in6.sin6_scope_id = 0;
722 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
723 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
724 #ifdef HAVE_SOCKADDR_SA_LEN
725 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
726 #endif
727 if (source)
729 if (flags)
730 *flags |= SERV_HAS_SOURCE;
731 source_addr->in6.sin6_port = htons(source_port);
732 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
734 #if defined(SO_BINDTODEVICE)
735 source_addr->in6.sin6_addr = in6addr_any;
736 strncpy(interface, source, IF_NAMESIZE - 1);
737 #else
738 return _("interface binding not supported");
739 #endif
743 #endif
744 else
745 return _("bad address");
747 return NULL;
750 #ifdef HAVE_DHCP
752 static int is_tag_prefix(char *arg)
754 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
755 return 1;
757 return 0;
760 static char *set_prefix(char *arg)
762 if (strstr(arg, "set:") == arg)
763 return arg+4;
765 return arg;
768 /* This is too insanely large to keep in-line in the switch */
769 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
771 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
772 char lenchar = 0, *cp;
773 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
774 char *comma = NULL;
775 struct dhcp_netid *np = NULL;
776 u16 opt_len = 0;
777 int is6 = 0;
778 int option_ok = 0;
780 new->len = 0;
781 new->flags = flags;
782 new->netid = NULL;
783 new->val = NULL;
784 new->opt = 0;
786 while (arg)
788 comma = split(arg);
790 for (cp = arg; *cp; cp++)
791 if (*cp < '0' || *cp > '9')
792 break;
794 if (!*cp)
796 new->opt = atoi(arg);
797 opt_len = 0;
798 option_ok = 1;
799 break;
802 if (strstr(arg, "option:") == arg)
804 if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
806 opt_len = lookup_dhcp_len(AF_INET, new->opt);
807 /* option:<optname> must follow tag and vendor string. */
808 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
809 option_ok = 1;
811 break;
813 #ifdef HAVE_DHCP6
814 else if (strstr(arg, "option6:") == arg)
816 for (cp = arg+8; *cp; cp++)
817 if (*cp < '0' || *cp > '9')
818 break;
820 if (!*cp)
822 new->opt = atoi(arg+8);
823 opt_len = 0;
824 option_ok = 1;
826 else
828 if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
830 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
831 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
832 option_ok = 1;
835 /* option6:<opt>|<optname> must follow tag and vendor string. */
836 is6 = 1;
837 break;
839 #endif
840 else if (strstr(arg, "vendor:") == arg)
842 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
843 new->flags |= DHOPT_VENDOR;
845 else if (strstr(arg, "encap:") == arg)
847 new->u.encap = atoi(arg+6);
848 new->flags |= DHOPT_ENCAPSULATE;
850 else if (strstr(arg, "vi-encap:") == arg)
852 new->u.encap = atoi(arg+9);
853 new->flags |= DHOPT_RFC3925;
854 if (flags == DHOPT_MATCH)
856 option_ok = 1;
857 break;
860 else
862 new->netid = opt_malloc(sizeof (struct dhcp_netid));
863 /* allow optional "net:" or "tag:" for consistency */
864 if (is_tag_prefix(arg))
865 new->netid->net = opt_string_alloc(arg+4);
866 else
867 new->netid->net = opt_string_alloc(set_prefix(arg));
868 new->netid->next = np;
869 np = new->netid;
872 arg = comma;
875 #ifdef HAVE_DHCP6
876 if (is6)
878 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
879 ret_err(_("unsupported encapsulation for IPv6 option"));
881 if (opt_len == 0 &&
882 !(new->flags & DHOPT_RFC3925))
883 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
885 else
886 #endif
887 if (opt_len == 0 &&
888 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
889 opt_len = lookup_dhcp_len(AF_INET, new->opt);
891 /* option may be missing with rfc3925 match */
892 if (!option_ok)
893 ret_err(_("bad dhcp-option"));
895 if (comma)
897 /* characterise the value */
898 char c;
899 int found_dig = 0;
900 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
901 addrs = digs = 1;
902 dots = 0;
903 for (cp = comma; (c = *cp); cp++)
904 if (c == ',')
906 addrs++;
907 is_dec = is_hex = 0;
909 else if (c == ':')
911 digs++;
912 is_dec = is_addr = 0;
914 else if (c == '/')
916 is_addr6 = is_dec = is_hex = 0;
917 if (cp == comma) /* leading / means a pathname */
918 is_addr = 0;
920 else if (c == '.')
922 is_addr6 = is_dec = is_hex = 0;
923 dots++;
925 else if (c == '-')
926 is_hex = is_addr = is_addr6 = 0;
927 else if (c == ' ')
928 is_dec = is_hex = 0;
929 else if (!(c >='0' && c <= '9'))
931 is_addr = 0;
932 if (cp[1] == 0 && is_dec &&
933 (c == 'b' || c == 's' || c == 'i'))
935 lenchar = c;
936 *cp = 0;
938 else
939 is_dec = 0;
940 if (!((c >='A' && c <= 'F') ||
941 (c >='a' && c <= 'f') ||
942 (c == '*' && (flags & DHOPT_MATCH))))
944 is_hex = 0;
945 if (c != '[' && c != ']')
946 is_addr6 = 0;
949 else
950 found_dig = 1;
952 if (!found_dig)
953 is_dec = is_addr = 0;
955 /* We know that some options take addresses */
956 if (opt_len & OT_ADDR_LIST)
958 is_string = is_dec = is_hex = 0;
960 if (!is6 && (!is_addr || dots == 0))
961 ret_err(_("bad IP address"));
963 if (is6 && !is_addr6)
964 ret_err(_("bad IPv6 address"));
966 /* or names */
967 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
968 is_addr6 = is_addr = is_dec = is_hex = 0;
970 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
972 int val, fac = 1;
974 switch (comma[strlen(comma) - 1])
976 case 'w':
977 case 'W':
978 fac *= 7;
979 /* fall through */
980 case 'd':
981 case 'D':
982 fac *= 24;
983 /* fall though */
984 case 'h':
985 case 'H':
986 fac *= 60;
987 /* fall through */
988 case 'm':
989 case 'M':
990 fac *= 60;
991 /* fall through */
992 case 's':
993 case 'S':
994 comma[strlen(comma) - 1] = 0;
997 new->len = 4;
998 new->val = opt_malloc(4);
999 val = atoi(comma);
1000 *((int *)new->val) = htonl(val * fac);
1002 else if (is_hex && digs > 1)
1004 new->len = digs;
1005 new->val = opt_malloc(new->len);
1006 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
1007 new->flags |= DHOPT_HEX;
1009 else if (is_dec)
1011 int i, val = atoi(comma);
1012 /* assume numeric arg is 1 byte except for
1013 options where it is known otherwise.
1014 For vendor class option, we have to hack. */
1015 if (opt_len != 0)
1016 new->len = opt_len;
1017 else if (val & 0xffff0000)
1018 new->len = 4;
1019 else if (val & 0xff00)
1020 new->len = 2;
1021 else
1022 new->len = 1;
1024 if (lenchar == 'b')
1025 new->len = 1;
1026 else if (lenchar == 's')
1027 new->len = 2;
1028 else if (lenchar == 'i')
1029 new->len = 4;
1031 new->val = opt_malloc(new->len);
1032 for (i=0; i<new->len; i++)
1033 new->val[i] = val>>((new->len - i - 1)*8);
1035 else if (is_addr && !is6)
1037 struct in_addr in;
1038 unsigned char *op;
1039 char *slash;
1040 /* max length of address/subnet descriptor is five bytes,
1041 add one for the option 120 enc byte too */
1042 new->val = op = opt_malloc((5 * addrs) + 1);
1043 new->flags |= DHOPT_ADDR;
1045 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1046 new->opt == OPTION_SIP_SERVER)
1048 *(op++) = 1; /* RFC 3361 "enc byte" */
1049 new->flags &= ~DHOPT_ADDR;
1051 while (addrs--)
1053 cp = comma;
1054 comma = split(cp);
1055 slash = split_chr(cp, '/');
1056 inet_pton(AF_INET, cp, &in);
1057 if (!slash)
1059 memcpy(op, &in, INADDRSZ);
1060 op += INADDRSZ;
1062 else
1064 unsigned char *p = (unsigned char *)&in;
1065 int netsize = atoi(slash);
1066 *op++ = netsize;
1067 if (netsize > 0)
1068 *op++ = *p++;
1069 if (netsize > 8)
1070 *op++ = *p++;
1071 if (netsize > 16)
1072 *op++ = *p++;
1073 if (netsize > 24)
1074 *op++ = *p++;
1075 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1078 new->len = op - new->val;
1080 else if (is_addr6 && is6)
1082 unsigned char *op;
1083 new->val = op = opt_malloc(16 * addrs);
1084 new->flags |= DHOPT_ADDR6;
1085 while (addrs--)
1087 cp = comma;
1088 comma = split(cp);
1090 /* check for [1234::7] */
1091 if (*cp == '[')
1092 cp++;
1093 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1094 cp[strlen(cp)-1] = 0;
1096 if (inet_pton(AF_INET6, cp, op))
1098 op += IN6ADDRSZ;
1099 continue;
1102 ret_err(_("bad IPv6 address"));
1104 new->len = op - new->val;
1106 else if (is_string)
1108 /* text arg */
1109 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
1110 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1112 /* dns search, RFC 3397, or SIP, RFC 3361 */
1113 unsigned char *q, *r, *tail;
1114 unsigned char *p, *m = NULL, *newp;
1115 size_t newlen, len = 0;
1116 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
1118 arg = comma;
1119 comma = split(arg);
1121 while (arg && *arg)
1123 char *in, *dom = NULL;
1124 size_t domlen = 1;
1125 /* Allow "." as an empty domain */
1126 if (strcmp (arg, ".") != 0)
1128 if (!(dom = canonicalise_opt(arg)))
1129 ret_err(_("bad domain in dhcp-option"));
1131 domlen = strlen(dom) + 2;
1134 newp = opt_malloc(len + domlen + header_size);
1135 if (m)
1137 memcpy(newp, m, header_size + len);
1138 free(m);
1140 m = newp;
1141 p = m + header_size;
1142 q = p + len;
1144 /* add string on the end in RFC1035 format */
1145 for (in = dom; in && *in;)
1147 unsigned char *cp = q++;
1148 int j;
1149 for (j = 0; *in && (*in != '.'); in++, j++)
1150 *q++ = *in;
1151 *cp = j;
1152 if (*in)
1153 in++;
1155 *q++ = 0;
1156 free(dom);
1158 /* Now tail-compress using earlier names. */
1159 newlen = q - p;
1160 for (tail = p + len; *tail; tail += (*tail) + 1)
1161 for (r = p; r - p < (int)len; r += (*r) + 1)
1162 if (strcmp((char *)r, (char *)tail) == 0)
1164 PUTSHORT((r - p) | 0xc000, tail);
1165 newlen = tail - p;
1166 goto end;
1168 end:
1169 len = newlen;
1171 arg = comma;
1172 comma = split(arg);
1175 /* RFC 3361, enc byte is zero for names */
1176 if (new->opt == OPTION_SIP_SERVER)
1177 m[0] = 0;
1178 new->len = (int) len + header_size;
1179 new->val = m;
1181 #ifdef HAVE_DHCP6
1182 else if (comma && (opt_len & OT_CSTRING))
1184 /* length fields are two bytes so need 16 bits for each string */
1185 int i, commas = 1;
1186 unsigned char *p, *newp;
1188 for (i = 0; comma[i]; i++)
1189 if (comma[i] == ',')
1190 commas++;
1192 newp = opt_malloc(strlen(comma)+(2*commas));
1193 p = newp;
1194 arg = comma;
1195 comma = split(arg);
1197 while (arg && *arg)
1199 u16 len = strlen(arg);
1200 unhide_metas(arg);
1201 PUTSHORT(len, p);
1202 memcpy(p, arg, len);
1203 p += len;
1205 arg = comma;
1206 comma = split(arg);
1209 new->val = newp;
1210 new->len = p - newp;
1212 else if (comma && (opt_len & OT_RFC1035_NAME))
1214 unsigned char *p = NULL, *newp, *end;
1215 int len = 0;
1216 arg = comma;
1217 comma = split(arg);
1219 while (arg && *arg)
1221 char *dom = canonicalise_opt(arg);
1222 if (!dom)
1223 ret_err(_("bad domain in dhcp-option"));
1225 newp = opt_malloc(len + strlen(dom) + 2);
1227 if (p)
1229 memcpy(newp, p, len);
1230 free(p);
1233 p = newp;
1234 end = do_rfc1035_name(p + len, dom);
1235 *end++ = 0;
1236 len = end - p;
1237 free(dom);
1239 arg = comma;
1240 comma = split(arg);
1243 new->val = p;
1244 new->len = len;
1246 #endif
1247 else
1249 new->len = strlen(comma);
1250 /* keep terminating zero on string */
1251 new->val = (unsigned char *)opt_string_alloc(comma);
1252 new->flags |= DHOPT_STRING;
1257 if (!is6 &&
1258 ((new->len > 255) ||
1259 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1260 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
1261 ret_err(_("dhcp-option too long"));
1263 if (flags == DHOPT_MATCH)
1265 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1266 !new->netid ||
1267 new->netid->next)
1268 ret_err(_("illegal dhcp-match"));
1270 if (is6)
1272 new->next = daemon->dhcp_match6;
1273 daemon->dhcp_match6 = new;
1275 else
1277 new->next = daemon->dhcp_match;
1278 daemon->dhcp_match = new;
1281 else if (is6)
1283 new->next = daemon->dhcp_opts6;
1284 daemon->dhcp_opts6 = new;
1286 else
1288 new->next = daemon->dhcp_opts;
1289 daemon->dhcp_opts = new;
1292 return 1;
1295 #endif
1297 void set_option_bool(unsigned int opt)
1299 if (opt < 32)
1300 daemon->options |= 1u << opt;
1301 else
1302 daemon->options2 |= 1u << (opt - 32);
1305 void reset_option_bool(unsigned int opt)
1307 if (opt < 32)
1308 daemon->options &= ~(1u << opt);
1309 else
1310 daemon->options2 &= ~(1u << (opt - 32));
1313 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
1315 int i;
1316 char *comma;
1318 if (option == '?')
1319 ret_err(gen_err);
1321 for (i=0; usage[i].opt != 0; i++)
1322 if (usage[i].opt == option)
1324 int rept = usage[i].rept;
1326 if (command_line)
1328 /* command line */
1329 if (rept == ARG_USED_CL)
1330 ret_err(_("illegal repeated flag"));
1331 if (rept == ARG_ONE)
1332 usage[i].rept = ARG_USED_CL;
1334 else
1336 /* allow file to override command line */
1337 if (rept == ARG_USED_FILE)
1338 ret_err(_("illegal repeated keyword"));
1339 if (rept == ARG_USED_CL || rept == ARG_ONE)
1340 usage[i].rept = ARG_USED_FILE;
1343 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1345 set_option_bool(rept);
1346 return 1;
1349 break;
1352 switch (option)
1354 case 'C': /* --conf-file */
1356 char *file = opt_string_alloc(arg);
1357 if (file)
1359 one_file(file, 0);
1360 free(file);
1362 break;
1365 case '7': /* --conf-dir */
1367 DIR *dir_stream;
1368 struct dirent *ent;
1369 char *directory, *path;
1370 struct list {
1371 char *suffix;
1372 struct list *next;
1373 } *ignore_suffix = NULL, *li;
1375 comma = split(arg);
1376 if (!(directory = opt_string_alloc(arg)))
1377 break;
1379 for (arg = comma; arg; arg = comma)
1381 comma = split(arg);
1382 li = opt_malloc(sizeof(struct list));
1383 li->next = ignore_suffix;
1384 ignore_suffix = li;
1385 /* Have to copy: buffer is overwritten */
1386 li->suffix = opt_string_alloc(arg);
1389 if (!(dir_stream = opendir(directory)))
1390 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1392 while ((ent = readdir(dir_stream)))
1394 size_t len = strlen(ent->d_name);
1395 struct stat buf;
1397 /* ignore emacs backups and dotfiles */
1398 if (len == 0 ||
1399 ent->d_name[len - 1] == '~' ||
1400 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1401 ent->d_name[0] == '.')
1402 continue;
1404 for (li = ignore_suffix; li; li = li->next)
1406 /* check for proscribed suffices */
1407 size_t ls = strlen(li->suffix);
1408 if (len > ls &&
1409 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1410 break;
1412 if (li)
1413 continue;
1415 path = opt_malloc(strlen(directory) + len + 2);
1416 strcpy(path, directory);
1417 strcat(path, "/");
1418 strcat(path, ent->d_name);
1420 /* files must be readable */
1421 if (stat(path, &buf) == -1)
1422 die(_("cannot access %s: %s"), path, EC_FILE);
1424 /* only reg files allowed. */
1425 if (S_ISREG(buf.st_mode))
1426 one_file(path, 0);
1428 free(path);
1431 closedir(dir_stream);
1432 free(directory);
1433 for(; ignore_suffix; ignore_suffix = li)
1435 li = ignore_suffix->next;
1436 free(ignore_suffix->suffix);
1437 free(ignore_suffix);
1440 break;
1443 case '1': /* --enable-dbus */
1444 set_option_bool(OPT_DBUS);
1445 if (arg)
1446 daemon->dbus_name = opt_string_alloc(arg);
1447 else
1448 daemon->dbus_name = DNSMASQ_SERVICE;
1449 break;
1451 case '8': /* --log-facility */
1452 /* may be a filename */
1453 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1454 daemon->log_file = opt_string_alloc(arg);
1455 else
1457 #ifdef __ANDROID__
1458 ret_err(_("setting log facility is not possible under Android"));
1459 #else
1460 for (i = 0; facilitynames[i].c_name; i++)
1461 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1462 break;
1464 if (facilitynames[i].c_name)
1465 daemon->log_fac = facilitynames[i].c_val;
1466 else
1467 ret_err(_("bad log facility"));
1468 #endif
1470 break;
1472 case 'x': /* --pid-file */
1473 daemon->runfile = opt_string_alloc(arg);
1474 break;
1476 case 'r': /* --resolv-file */
1478 char *name = opt_string_alloc(arg);
1479 struct resolvc *new, *list = daemon->resolv_files;
1481 if (list && list->is_default)
1483 /* replace default resolv file - possibly with nothing */
1484 if (name)
1486 list->is_default = 0;
1487 list->name = name;
1489 else
1490 list = NULL;
1492 else if (name)
1494 new = opt_malloc(sizeof(struct resolvc));
1495 new->next = list;
1496 new->name = name;
1497 new->is_default = 0;
1498 new->mtime = 0;
1499 new->logged = 0;
1500 list = new;
1502 daemon->resolv_files = list;
1503 break;
1506 case 'm': /* --mx-host */
1508 int pref = 1;
1509 struct mx_srv_record *new;
1510 char *name, *target = NULL;
1512 if ((comma = split(arg)))
1514 char *prefstr;
1515 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1516 ret_err(_("bad MX preference"));
1519 if (!(name = canonicalise_opt(arg)) ||
1520 (comma && !(target = canonicalise_opt(comma))))
1521 ret_err(_("bad MX name"));
1523 new = opt_malloc(sizeof(struct mx_srv_record));
1524 new->next = daemon->mxnames;
1525 daemon->mxnames = new;
1526 new->issrv = 0;
1527 new->name = name;
1528 new->target = target; /* may be NULL */
1529 new->weight = pref;
1530 break;
1533 case 't': /* --mx-target */
1534 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1535 ret_err(_("bad MX target"));
1536 break;
1538 #ifdef HAVE_DHCP
1539 case 'l': /* --dhcp-leasefile */
1540 daemon->lease_file = opt_string_alloc(arg);
1541 break;
1543 /* Sorry about the gross pre-processor abuse */
1544 case '6': /* --dhcp-script */
1545 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1546 # if defined(NO_FORK)
1547 ret_err(_("cannot run scripts under uClinux"));
1548 # elif !defined(HAVE_SCRIPT)
1549 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
1550 # else
1551 if (option == LOPT_LUASCRIPT)
1552 # if !defined(HAVE_LUASCRIPT)
1553 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
1554 # else
1555 daemon->luascript = opt_string_alloc(arg);
1556 # endif
1557 else
1558 daemon->lease_change_command = opt_string_alloc(arg);
1559 # endif
1560 break;
1561 #endif /* HAVE_DHCP */
1563 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1564 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1565 case 'H': /* --addn-hosts */
1567 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1568 static int hosts_index = 1;
1569 new->fname = opt_string_alloc(arg);
1570 new->index = hosts_index++;
1571 new->flags = 0;
1572 if (option == 'H')
1574 new->next = daemon->addn_hosts;
1575 daemon->addn_hosts = new;
1577 else if (option == LOPT_DHCP_HOST)
1579 new->next = daemon->dhcp_hosts_file;
1580 daemon->dhcp_hosts_file = new;
1582 else if (option == LOPT_DHCP_OPTS)
1584 new->next = daemon->dhcp_opts_file;
1585 daemon->dhcp_opts_file = new;
1587 break;
1590 case LOPT_AUTHSERV: /* --auth-server */
1591 if (!(comma = split(arg)))
1592 ret_err(gen_err);
1594 daemon->authserver = opt_string_alloc(arg);
1595 arg = comma;
1596 do {
1597 struct iname *new = opt_malloc(sizeof(struct iname));
1598 comma = split(arg);
1599 new->name = NULL;
1600 unhide_metas(arg);
1601 if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
1602 new->addr.sa.sa_family = AF_INET;
1603 #ifdef HAVE_IPV6
1604 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1605 new->addr.sa.sa_family = AF_INET6;
1606 #endif
1607 else
1608 new->name = opt_string_alloc(arg);
1610 new->next = daemon->authinterface;
1611 daemon->authinterface = new;
1613 arg = comma;
1614 } while (arg);
1616 break;
1618 case LOPT_AUTHSFS: /* --auth-sec-servers */
1620 struct name_list *new;
1622 do {
1623 comma = split(arg);
1624 new = opt_malloc(sizeof(struct name_list));
1625 new->name = opt_string_alloc(arg);
1626 new->next = daemon->secondary_forward_server;
1627 daemon->secondary_forward_server = new;
1628 arg = comma;
1629 } while (arg);
1630 break;
1633 case LOPT_AUTHZONE: /* --auth-zone */
1635 struct auth_zone *new;
1637 comma = split(arg);
1639 new = opt_malloc(sizeof(struct auth_zone));
1640 new->domain = opt_string_alloc(arg);
1641 new->subnet = NULL;
1642 new->next = daemon->auth_zones;
1643 daemon->auth_zones = new;
1645 while ((arg = comma))
1647 int prefixlen = 0;
1648 char *prefix;
1649 struct subnet *subnet = opt_malloc(sizeof(struct subnet));
1651 subnet->next = new->subnet;
1652 new->subnet = subnet;
1654 comma = split(arg);
1655 prefix = split_chr(arg, '/');
1657 if (prefix && !atoi_check(prefix, &prefixlen))
1658 ret_err(gen_err);
1660 if (inet_pton(AF_INET, arg, &subnet->addr4))
1662 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
1663 subnet->is6 = 0;
1665 #ifdef HAVE_IPV6
1666 else if (inet_pton(AF_INET6, arg, &subnet->addr6))
1668 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
1669 subnet->is6 = 1;
1671 #endif
1672 else
1673 ret_err(gen_err);
1675 break;
1678 case LOPT_AUTHSOA: /* --auth-soa */
1679 comma = split(arg);
1680 daemon->soa_sn = (u32)atoi(arg);
1681 if (comma)
1683 char *cp;
1684 arg = comma;
1685 comma = split(arg);
1686 daemon->hostmaster = opt_string_alloc(arg);
1687 for (cp = daemon->hostmaster; *cp; cp++)
1688 if (*cp == '@')
1689 *cp = '.';
1691 if (comma)
1693 arg = comma;
1694 comma = split(arg);
1695 daemon->soa_refresh = (u32)atoi(arg);
1696 if (comma)
1698 arg = comma;
1699 comma = split(arg);
1700 daemon->soa_retry = (u32)atoi(arg);
1701 if (comma)
1703 arg = comma;
1704 comma = split(arg);
1705 daemon->soa_expiry = (u32)atoi(arg);
1711 break;
1713 case 's': /* --domain */
1714 case LOPT_SYNTH: /* --synth-domain */
1715 if (strcmp (arg, "#") == 0)
1716 set_option_bool(OPT_RESOLV_DOMAIN);
1717 else
1719 char *d;
1720 comma = split(arg);
1721 if (!(d = canonicalise_opt(arg)))
1722 ret_err(gen_err);
1723 else
1725 if (comma)
1727 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
1728 char *netpart;
1730 new->prefix = NULL;
1732 unhide_metas(comma);
1733 if ((netpart = split_chr(comma, '/')))
1735 int msize;
1737 arg = split(netpart);
1738 if (!atoi_check(netpart, &msize))
1739 ret_err(gen_err);
1740 else if (inet_pton(AF_INET, comma, &new->start))
1742 int mask = (1 << (32 - msize)) - 1;
1743 new->is6 = 0;
1744 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1745 new->end.s_addr = new->start.s_addr | htonl(mask);
1746 if (arg)
1748 if (option != 's')
1750 if (!(new->prefix = canonicalise_opt(arg)) ||
1751 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1752 ret_err(_("bad prefix"));
1754 else if (strcmp(arg, "local") != 0 ||
1755 (msize != 8 && msize != 16 && msize != 24))
1756 ret_err(gen_err);
1757 else
1759 /* generate the equivalent of
1760 local=/<domain>/
1761 local=/xxx.yyy.zzz.in-addr.arpa/ */
1762 struct server *serv = opt_malloc(sizeof(struct server));
1763 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1764 char *p;
1766 memset(serv, 0, sizeof(struct server));
1767 serv->domain = d;
1768 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1769 serv->next = daemon->servers;
1770 daemon->servers = serv;
1772 serv = opt_malloc(sizeof(struct server));
1773 memset(serv, 0, sizeof(struct server));
1774 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1776 if (msize == 24)
1777 p += sprintf(p, "%d.", a & 0xff);
1778 a = a >> 8;
1779 if (msize != 8)
1780 p += sprintf(p, "%d.", a & 0xff);
1781 a = a >> 8;
1782 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
1784 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1785 serv->next = daemon->servers;
1786 daemon->servers = serv;
1790 #ifdef HAVE_IPV6
1791 else if (inet_pton(AF_INET6, comma, &new->start6))
1793 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1794 u64 addrpart = addr6part(&new->start6);
1795 new->is6 = 1;
1797 /* prefix==64 overflows the mask calculation above */
1798 if (msize == 64)
1799 mask = (u64)-1LL;
1801 new->end6 = new->start6;
1802 setaddr6part(&new->start6, addrpart & ~mask);
1803 setaddr6part(&new->end6, addrpart | mask);
1805 if (msize < 64)
1806 ret_err(gen_err);
1807 else if (arg)
1809 if (option != 's')
1811 if (!(new->prefix = canonicalise_opt(arg)) ||
1812 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
1813 ret_err(_("bad prefix"));
1815 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
1816 ret_err(gen_err);
1817 else
1819 /* generate the equivalent of
1820 local=/<domain>/
1821 local=/xxx.yyy.zzz.ip6.arpa/ */
1822 struct server *serv = opt_malloc(sizeof(struct server));
1823 char *p;
1825 memset(serv, 0, sizeof(struct server));
1826 serv->domain = d;
1827 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1828 serv->next = daemon->servers;
1829 daemon->servers = serv;
1831 serv = opt_malloc(sizeof(struct server));
1832 memset(serv, 0, sizeof(struct server));
1833 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1835 for (i = msize-1; i >= 0; i -= 4)
1837 int dig = ((unsigned char *)&new->start6)[i>>3];
1838 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1840 p += sprintf(p, "ip6.arpa");
1842 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1843 serv->next = daemon->servers;
1844 daemon->servers = serv;
1848 #endif
1849 else
1850 ret_err(gen_err);
1852 else
1854 arg = split(comma);
1855 if (inet_pton(AF_INET, comma, &new->start))
1857 new->is6 = 0;
1858 if (!arg)
1859 new->end.s_addr = new->start.s_addr;
1860 else if (!inet_pton(AF_INET, arg, &new->end))
1861 ret_err(gen_err);
1863 #ifdef HAVE_IPV6
1864 else if (inet_pton(AF_INET6, comma, &new->start6))
1866 new->is6 = 1;
1867 if (!arg)
1868 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1869 else if (!inet_pton(AF_INET6, arg, &new->end6))
1870 ret_err(gen_err);
1872 #endif
1873 else
1874 ret_err(gen_err);
1877 new->domain = d;
1878 if (option == 's')
1880 new->next = daemon->cond_domain;
1881 daemon->cond_domain = new;
1883 else
1885 new->next = daemon->synth_domains;
1886 daemon->synth_domains = new;
1889 else if (option == 's')
1890 daemon->domain_suffix = d;
1891 else
1892 ret_err(gen_err);
1895 break;
1897 case 'u': /* --user */
1898 daemon->username = opt_string_alloc(arg);
1899 break;
1901 case 'g': /* --group */
1902 daemon->groupname = opt_string_alloc(arg);
1903 daemon->group_set = 1;
1904 break;
1906 #ifdef HAVE_DHCP
1907 case LOPT_SCRIPTUSR: /* --scriptuser */
1908 daemon->scriptuser = opt_string_alloc(arg);
1909 break;
1910 #endif
1912 case 'i': /* --interface */
1913 do {
1914 struct iname *new = opt_malloc(sizeof(struct iname));
1915 comma = split(arg);
1916 new->next = daemon->if_names;
1917 daemon->if_names = new;
1918 /* new->name may be NULL if someone does
1919 "interface=" to disable all interfaces except loop. */
1920 new->name = opt_string_alloc(arg);
1921 new->used = 0;
1922 arg = comma;
1923 } while (arg);
1924 break;
1926 case LOPT_TFTP: /* --enable-tftp */
1927 set_option_bool(OPT_TFTP);
1928 if (!arg)
1929 break;
1930 /* fall through */
1932 case 'I': /* --except-interface */
1933 case '2': /* --no-dhcp-interface */
1934 do {
1935 struct iname *new = opt_malloc(sizeof(struct iname));
1936 comma = split(arg);
1937 new->name = opt_string_alloc(arg);
1938 if (option == 'I')
1940 new->next = daemon->if_except;
1941 daemon->if_except = new;
1943 else if (option == LOPT_TFTP)
1945 new->next = daemon->tftp_interfaces;
1946 daemon->tftp_interfaces = new;
1948 else
1950 new->next = daemon->dhcp_except;
1951 daemon->dhcp_except = new;
1953 arg = comma;
1954 } while (arg);
1955 break;
1957 case 'B': /* --bogus-nxdomain */
1959 struct in_addr addr;
1960 unhide_metas(arg);
1961 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
1963 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1964 baddr->next = daemon->bogus_addr;
1965 daemon->bogus_addr = baddr;
1966 baddr->addr = addr;
1968 else
1969 ret_err(gen_err); /* error */
1970 break;
1973 case 'a': /* --listen-address */
1974 case LOPT_AUTHPEER: /* --auth-peer */
1975 do {
1976 struct iname *new = opt_malloc(sizeof(struct iname));
1977 comma = split(arg);
1978 unhide_metas(arg);
1979 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
1981 new->addr.sa.sa_family = AF_INET;
1982 new->addr.in.sin_port = 0;
1983 #ifdef HAVE_SOCKADDR_SA_LEN
1984 new->addr.in.sin_len = sizeof(new->addr.in);
1985 #endif
1987 #ifdef HAVE_IPV6
1988 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1990 new->addr.sa.sa_family = AF_INET6;
1991 new->addr.in6.sin6_flowinfo = 0;
1992 new->addr.in6.sin6_scope_id = 0;
1993 new->addr.in6.sin6_port = 0;
1994 #ifdef HAVE_SOCKADDR_SA_LEN
1995 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1996 #endif
1998 #endif
1999 else
2000 ret_err(gen_err);
2002 new->used = 0;
2003 if (option == 'a')
2005 new->next = daemon->if_addrs;
2006 daemon->if_addrs = new;
2008 else
2010 new->next = daemon->auth_peers;
2011 daemon->auth_peers = new;
2013 arg = comma;
2014 } while (arg);
2015 break;
2017 case 'S': /* --server */
2018 case LOPT_LOCAL: /* --local */
2019 case 'A': /* --address */
2020 case LOPT_NO_REBIND: /* --rebind-domain-ok */
2022 struct server *serv, *newlist = NULL;
2024 unhide_metas(arg);
2026 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
2028 int rebind = !(*arg == '/');
2029 char *end = NULL;
2030 if (!rebind)
2031 arg++;
2032 while (rebind || (end = split_chr(arg, '/')))
2034 char *domain = NULL;
2035 /* elide leading dots - they are implied in the search algorithm */
2036 while (*arg == '.') arg++;
2037 /* # matches everything and becomes a zero length domain string */
2038 if (strcmp(arg, "#") == 0)
2039 domain = "";
2040 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
2041 option = '?';
2042 serv = opt_malloc(sizeof(struct server));
2043 memset(serv, 0, sizeof(struct server));
2044 serv->next = newlist;
2045 newlist = serv;
2046 serv->domain = domain;
2047 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
2048 arg = end;
2049 if (rebind)
2050 break;
2052 if (!newlist)
2053 ret_err(gen_err);
2055 else
2057 newlist = opt_malloc(sizeof(struct server));
2058 memset(newlist, 0, sizeof(struct server));
2061 if (option == 'A')
2063 newlist->flags |= SERV_LITERAL_ADDRESS;
2064 if (!(newlist->flags & SERV_TYPE))
2065 ret_err(gen_err);
2067 else if (option == LOPT_NO_REBIND)
2068 newlist->flags |= SERV_NO_REBIND;
2070 if (!arg || !*arg)
2072 if (!(newlist->flags & SERV_NO_REBIND))
2073 newlist->flags |= SERV_NO_ADDR; /* no server */
2074 if (newlist->flags & SERV_LITERAL_ADDRESS)
2075 ret_err(gen_err);
2078 else if (strcmp(arg, "#") == 0)
2080 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
2081 if (newlist->flags & SERV_LITERAL_ADDRESS)
2082 ret_err(gen_err);
2084 else
2086 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2087 if (err)
2088 ret_err(err);
2091 serv = newlist;
2092 while (serv->next)
2094 serv->next->flags = serv->flags;
2095 serv->next->addr = serv->addr;
2096 serv->next->source_addr = serv->source_addr;
2097 strcpy(serv->next->interface, serv->interface);
2098 serv = serv->next;
2100 serv->next = daemon->servers;
2101 daemon->servers = newlist;
2102 break;
2105 case LOPT_IPSET: /* --ipset */
2106 #ifndef HAVE_IPSET
2107 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2108 break;
2109 #else
2111 struct ipsets ipsets_head;
2112 struct ipsets *ipsets = &ipsets_head;
2113 int size;
2114 char *end;
2115 char **sets, **sets_pos;
2116 memset(ipsets, 0, sizeof(struct ipsets));
2117 unhide_metas(arg);
2118 if (arg && *arg == '/')
2120 arg++;
2121 while ((end = split_chr(arg, '/')))
2123 char *domain = NULL;
2124 /* elide leading dots - they are implied in the search algorithm */
2125 while (*arg == '.')
2126 arg++;
2127 /* # matches everything and becomes a zero length domain string */
2128 if (strcmp(arg, "#") == 0 || !*arg)
2129 domain = "";
2130 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2131 option = '?';
2132 ipsets->next = opt_malloc(sizeof(struct ipsets));
2133 ipsets = ipsets->next;
2134 memset(ipsets, 0, sizeof(struct ipsets));
2135 ipsets->domain = domain;
2136 arg = end;
2139 else
2141 ipsets->next = opt_malloc(sizeof(struct ipsets));
2142 ipsets = ipsets->next;
2143 memset(ipsets, 0, sizeof(struct ipsets));
2144 ipsets->domain = "";
2146 if (!arg || !*arg)
2148 option = '?';
2149 break;
2151 size = 2;
2152 for (end = arg; *end; ++end)
2153 if (*end == ',')
2154 ++size;
2156 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2158 do {
2159 end = split(arg);
2160 *sets_pos++ = opt_string_alloc(arg);
2161 arg = end;
2162 } while (end);
2163 *sets_pos = 0;
2164 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2165 ipsets->next->sets = sets;
2166 ipsets->next = daemon->ipsets;
2167 daemon->ipsets = ipsets_head.next;
2169 break;
2171 #endif
2173 case 'c': /* --cache-size */
2175 int size;
2177 if (!atoi_check(arg, &size))
2178 ret_err(gen_err);
2179 else
2181 /* zero is OK, and means no caching. */
2183 if (size < 0)
2184 size = 0;
2185 else if (size > 10000)
2186 size = 10000;
2188 daemon->cachesize = size;
2190 break;
2193 case 'p': /* --port */
2194 if (!atoi_check16(arg, &daemon->port))
2195 ret_err(gen_err);
2196 break;
2198 case LOPT_MINPORT: /* --min-port */
2199 if (!atoi_check16(arg, &daemon->min_port))
2200 ret_err(gen_err);
2201 break;
2203 case '0': /* --dns-forward-max */
2204 if (!atoi_check(arg, &daemon->ftabsize))
2205 ret_err(gen_err);
2206 break;
2208 case LOPT_MAX_LOGS: /* --log-async */
2209 daemon->max_logs = LOG_MAX; /* default */
2210 if (arg && !atoi_check(arg, &daemon->max_logs))
2211 ret_err(gen_err);
2212 else if (daemon->max_logs > 100)
2213 daemon->max_logs = 100;
2214 break;
2216 case 'P': /* --edns-packet-max */
2218 int i;
2219 if (!atoi_check(arg, &i))
2220 ret_err(gen_err);
2221 daemon->edns_pktsz = (unsigned short)i;
2222 break;
2225 case 'Q': /* --query-port */
2226 if (!atoi_check16(arg, &daemon->query_port))
2227 ret_err(gen_err);
2228 /* if explicitly set to zero, use single OS ephemeral port
2229 and disable random ports */
2230 if (daemon->query_port == 0)
2231 daemon->osport = 1;
2232 break;
2234 case 'T': /* --local-ttl */
2235 case LOPT_NEGTTL: /* --neg-ttl */
2236 case LOPT_MAXTTL: /* --max-ttl */
2237 case LOPT_MAXCTTL: /* --max-cache-ttl */
2238 case LOPT_AUTHTTL: /* --auth-ttl */
2240 int ttl;
2241 if (!atoi_check(arg, &ttl))
2242 ret_err(gen_err);
2243 else if (option == LOPT_NEGTTL)
2244 daemon->neg_ttl = (unsigned long)ttl;
2245 else if (option == LOPT_MAXTTL)
2246 daemon->max_ttl = (unsigned long)ttl;
2247 else if (option == LOPT_MAXCTTL)
2248 daemon->max_cache_ttl = (unsigned long)ttl;
2249 else if (option == LOPT_AUTHTTL)
2250 daemon->auth_ttl = (unsigned long)ttl;
2251 else
2252 daemon->local_ttl = (unsigned long)ttl;
2253 break;
2256 #ifdef HAVE_DHCP
2257 case 'X': /* --dhcp-lease-max */
2258 if (!atoi_check(arg, &daemon->dhcp_max))
2259 ret_err(gen_err);
2260 break;
2261 #endif
2263 #ifdef HAVE_TFTP
2264 case LOPT_TFTP_MAX: /* --tftp-max */
2265 if (!atoi_check(arg, &daemon->tftp_max))
2266 ret_err(gen_err);
2267 break;
2269 case LOPT_PREFIX: /* --tftp-prefix */
2270 comma = split(arg);
2271 if (comma)
2273 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2274 new->interface = opt_string_alloc(comma);
2275 new->prefix = opt_string_alloc(arg);
2276 new->next = daemon->if_prefix;
2277 daemon->if_prefix = new;
2279 else
2280 daemon->tftp_prefix = opt_string_alloc(arg);
2281 break;
2283 case LOPT_TFTPPORTS: /* --tftp-port-range */
2284 if (!(comma = split(arg)) ||
2285 !atoi_check16(arg, &daemon->start_tftp_port) ||
2286 !atoi_check16(comma, &daemon->end_tftp_port))
2287 ret_err(_("bad port range"));
2289 if (daemon->start_tftp_port > daemon->end_tftp_port)
2291 int tmp = daemon->start_tftp_port;
2292 daemon->start_tftp_port = daemon->end_tftp_port;
2293 daemon->end_tftp_port = tmp;
2296 break;
2297 #endif
2299 case LOPT_BRIDGE: /* --bridge-interface */
2301 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2302 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2303 ret_err(_("bad bridge-interface"));
2305 strcpy(new->iface, arg);
2306 new->alias = NULL;
2307 new->next = daemon->bridges;
2308 daemon->bridges = new;
2310 do {
2311 arg = comma;
2312 comma = split(arg);
2313 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2315 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2316 b->next = new->alias;
2317 new->alias = b;
2318 strcpy(b->iface, arg);
2320 } while (comma);
2322 break;
2325 #ifdef HAVE_DHCP
2326 case 'F': /* --dhcp-range */
2328 int k, leasepos = 2;
2329 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2330 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2332 memset (new, 0, sizeof(*new));
2333 new->lease_time = DEFLEASE;
2335 if (!arg)
2337 option = '?';
2338 break;
2341 while(1)
2343 for (cp = arg; *cp; cp++)
2344 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2345 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2346 (*cp >='0' && *cp <= '9')))
2347 break;
2349 if (*cp != ',' && (comma = split(arg)))
2351 if (is_tag_prefix(arg))
2353 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2354 tt->net = opt_string_alloc(arg+4);
2355 tt->next = new->filter;
2356 /* ignore empty tag */
2357 if (tt->net)
2358 new->filter = tt;
2360 else
2362 if (new->netid.net)
2363 ret_err(_("only one tag allowed"));
2364 else if (strstr(arg, "set:") == arg)
2365 new->netid.net = opt_string_alloc(arg+4);
2366 else
2367 new->netid.net = opt_string_alloc(arg);
2369 arg = comma;
2371 else
2373 a[0] = arg;
2374 break;
2378 for (k = 1; k < 8; k++)
2379 if (!(a[k] = split(a[k-1])))
2380 break;
2382 if (k < 2)
2383 ret_err(_("bad dhcp-range"));
2385 if (inet_pton(AF_INET, a[0], &new->start))
2387 new->next = daemon->dhcp;
2388 daemon->dhcp = new;
2389 new->end = new->start;
2390 if (strcmp(a[1], "static") == 0)
2391 new->flags |= CONTEXT_STATIC;
2392 else if (strcmp(a[1], "proxy") == 0)
2393 new->flags |= CONTEXT_PROXY;
2394 else if (!inet_pton(AF_INET, a[1], &new->end))
2395 ret_err(_("bad dhcp-range"));
2397 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2399 struct in_addr tmp = new->start;
2400 new->start = new->end;
2401 new->end = tmp;
2404 if (k >= 3 && strchr(a[2], '.') &&
2405 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
2407 new->flags |= CONTEXT_NETMASK;
2408 leasepos = 3;
2409 if (!is_same_net(new->start, new->end, new->netmask))
2410 ret_err(_("inconsistent DHCP range"));
2413 if (k >= 4 && strchr(a[3], '.') &&
2414 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
2416 new->flags |= CONTEXT_BRDCAST;
2417 leasepos = 4;
2420 #ifdef HAVE_DHCP6
2421 else if (inet_pton(AF_INET6, a[0], &new->start6))
2423 new->prefix = 64; /* default */
2424 new->end6 = new->start6;
2425 new->next = daemon->dhcp6;
2426 daemon->dhcp6 = new;
2428 for (leasepos = 1; leasepos < k; leasepos++)
2430 if (strcmp(a[leasepos], "static") == 0)
2431 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2432 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2433 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
2434 else if (strcmp(a[leasepos], "ra-names") == 0)
2435 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
2436 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2437 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
2438 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2439 new->flags |= CONTEXT_DHCP;
2440 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2442 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2443 new->flags |= CONTEXT_TEMPLATE;
2445 else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
2447 new->template_interface = opt_string_alloc(a[leasepos] + 19);
2448 new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
2450 else
2451 break;
2454 /* bare integer < 128 is prefix value */
2455 if (leasepos < k)
2457 int pref;
2458 for (cp = a[leasepos]; *cp; cp++)
2459 if (!(*cp >= '0' && *cp <= '9'))
2460 break;
2461 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
2463 new->prefix = pref;
2464 leasepos++;
2468 if (new->prefix != 64)
2470 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2471 ret_err(_("prefix length must be exactly 64 for RA subnets"));
2472 else if (new->flags & CONTEXT_TEMPLATE)
2473 ret_err(_("prefix length must be exactly 64 for subnet constructors"));
2476 if (new->prefix < 64)
2477 ret_err(_("prefix length must be at least 64"));
2479 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2480 ret_err(_("inconsistent DHCPv6 range"));
2482 /* dhcp-range=:: enables DHCP stateless on any interface */
2483 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
2484 new->prefix = 0;
2486 if (new->flags & CONTEXT_TEMPLATE)
2488 struct in6_addr zero;
2489 memset(&zero, 0, sizeof(zero));
2490 if (!is_same_net6(&zero, &new->start6, new->prefix))
2491 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2494 if (addr6part(&new->start6) > addr6part(&new->end6))
2496 struct in6_addr tmp = new->start6;
2497 new->start6 = new->end6;
2498 new->end6 = tmp;
2501 #endif
2502 else
2503 ret_err(_("bad dhcp-range"));
2505 if (leasepos < k)
2507 if (strcmp(a[leasepos], "infinite") == 0)
2508 new->lease_time = 0xffffffff;
2509 else if (strcmp(a[leasepos], "deprecated") == 0)
2510 new->flags |= CONTEXT_DEPRECATE;
2511 else
2513 int fac = 1;
2514 if (strlen(a[leasepos]) > 0)
2516 switch (a[leasepos][strlen(a[leasepos]) - 1])
2518 case 'w':
2519 case 'W':
2520 fac *= 7;
2521 /* fall through */
2522 case 'd':
2523 case 'D':
2524 fac *= 24;
2525 /* fall though */
2526 case 'h':
2527 case 'H':
2528 fac *= 60;
2529 /* fall through */
2530 case 'm':
2531 case 'M':
2532 fac *= 60;
2533 /* fall through */
2534 case 's':
2535 case 'S':
2536 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2539 for (cp = a[leasepos]; *cp; cp++)
2540 if (!(*cp >= '0' && *cp <= '9'))
2541 break;
2543 if (*cp || (leasepos+1 < k))
2544 ret_err(_("bad dhcp-range"));
2546 new->lease_time = atoi(a[leasepos]) * fac;
2547 /* Leases of a minute or less confuse
2548 some clients, notably Apple's */
2549 if (new->lease_time < 120)
2550 new->lease_time = 120;
2554 break;
2557 case LOPT_BANK:
2558 case 'G': /* --dhcp-host */
2560 int j, k = 0;
2561 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2562 struct dhcp_config *new;
2563 struct in_addr in;
2565 new = opt_malloc(sizeof(struct dhcp_config));
2567 new->next = daemon->dhcp_conf;
2568 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2569 new->hwaddr = NULL;
2570 new->netid = NULL;
2572 if ((a[0] = arg))
2573 for (k = 1; k < 7; k++)
2574 if (!(a[k] = split(a[k-1])))
2575 break;
2577 for (j = 0; j < k; j++)
2578 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2580 char *arg = a[j];
2582 if ((arg[0] == 'i' || arg[0] == 'I') &&
2583 (arg[1] == 'd' || arg[1] == 'D') &&
2584 arg[2] == ':')
2586 if (arg[3] == '*')
2587 new->flags |= CONFIG_NOCLID;
2588 else
2590 int len;
2591 arg += 3; /* dump id: */
2592 if (strchr(arg, ':'))
2593 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2594 else
2596 unhide_metas(arg);
2597 len = (int) strlen(arg);
2600 if (len == -1)
2602 ret_err(_("bad hex constant"));
2603 else if ((new->clid = opt_malloc(len)))
2605 new->flags |= CONFIG_CLID;
2606 new->clid_len = len;
2607 memcpy(new->clid, arg, len);
2611 /* dhcp-host has strange backwards-compat needs. */
2612 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2614 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2615 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2616 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2617 newlist->next = new->netid;
2618 new->netid = newlist;
2619 newlist->list = newtag;
2620 strcpy(newtag->net, arg+4);
2621 unhide_metas(newtag->net);
2623 else if (strstr(arg, "tag:") == arg)
2624 ret_err(_("cannot match tags in --dhcp-host"));
2625 #ifdef HAVE_DHCP6
2626 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2628 arg[strlen(arg)-1] = 0;
2629 arg++;
2631 if (!inet_pton(AF_INET6, arg, &new->addr6))
2632 ret_err(_("bad IPv6 address"));
2634 for (i= 0; i < 8; i++)
2635 if (new->addr6.s6_addr[i] != 0)
2636 break;
2638 /* set WILDCARD if network part all zeros */
2639 if (i == 8)
2640 new->flags |= CONFIG_WILDCARD;
2642 new->flags |= CONFIG_ADDR6;
2644 #endif
2645 else
2647 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2648 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2649 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2650 ret_err(_("bad hex constant"));
2651 else
2654 newhw->next = new->hwaddr;
2655 new->hwaddr = newhw;
2659 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
2661 struct dhcp_config *configs;
2663 new->addr = in;
2664 new->flags |= CONFIG_ADDR;
2666 /* If the same IP appears in more than one host config, then DISCOVER
2667 for one of the hosts will get the address, but REQUEST will be NAKed,
2668 since the address is reserved by the other one -> protocol loop. */
2669 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2670 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2672 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2673 return 0;
2676 else
2678 char *cp, *lastp = NULL, last = 0;
2679 int fac = 1;
2681 if (strlen(a[j]) > 1)
2683 lastp = a[j] + strlen(a[j]) - 1;
2684 last = *lastp;
2685 switch (last)
2687 case 'w':
2688 case 'W':
2689 fac *= 7;
2690 /* fall through */
2691 case 'd':
2692 case 'D':
2693 fac *= 24;
2694 /* fall through */
2695 case 'h':
2696 case 'H':
2697 fac *= 60;
2698 /* fall through */
2699 case 'm':
2700 case 'M':
2701 fac *= 60;
2702 /* fall through */
2703 case 's':
2704 case 'S':
2705 *lastp = 0;
2709 for (cp = a[j]; *cp; cp++)
2710 if (!isdigit((unsigned char)*cp) && *cp != ' ')
2711 break;
2713 if (*cp)
2715 if (lastp)
2716 *lastp = last;
2717 if (strcmp(a[j], "infinite") == 0)
2719 new->lease_time = 0xffffffff;
2720 new->flags |= CONFIG_TIME;
2722 else if (strcmp(a[j], "ignore") == 0)
2723 new->flags |= CONFIG_DISABLE;
2724 else
2726 if (!(new->hostname = canonicalise_opt(a[j])) ||
2727 !legal_hostname(new->hostname))
2728 ret_err(_("bad DHCP host name"));
2730 new->flags |= CONFIG_NAME;
2731 new->domain = strip_hostname(new->hostname);
2734 else
2736 new->lease_time = atoi(a[j]) * fac;
2737 /* Leases of a minute or less confuse
2738 some clients, notably Apple's */
2739 if (new->lease_time < 120)
2740 new->lease_time = 120;
2741 new->flags |= CONFIG_TIME;
2745 daemon->dhcp_conf = new;
2746 break;
2749 case LOPT_TAG_IF: /* --tag-if */
2751 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2753 new->tag = NULL;
2754 new->set = NULL;
2755 new->next = NULL;
2757 /* preserve order */
2758 if (!daemon->tag_if)
2759 daemon->tag_if = new;
2760 else
2762 struct tag_if *tmp;
2763 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2764 tmp->next = new;
2767 while (arg)
2769 size_t len;
2771 comma = split(arg);
2772 len = strlen(arg);
2774 if (len < 5)
2776 new->set = NULL;
2777 break;
2779 else
2781 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2782 newtag->net = opt_malloc(len - 3);
2783 strcpy(newtag->net, arg+4);
2784 unhide_metas(newtag->net);
2786 if (strstr(arg, "set:") == arg)
2788 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2789 newlist->next = new->set;
2790 new->set = newlist;
2791 newlist->list = newtag;
2793 else if (strstr(arg, "tag:") == arg)
2795 newtag->next = new->tag;
2796 new->tag = newtag;
2798 else
2800 new->set = NULL;
2801 free(newtag);
2802 break;
2806 arg = comma;
2809 if (!new->set)
2810 ret_err(_("bad tag-if"));
2812 break;
2816 case 'O': /* --dhcp-option */
2817 case LOPT_FORCE: /* --dhcp-option-force */
2818 case LOPT_OPTS:
2819 case LOPT_MATCH: /* --dhcp-match */
2820 return parse_dhcp_opt(errstr, arg,
2821 option == LOPT_FORCE ? DHOPT_FORCE :
2822 (option == LOPT_MATCH ? DHOPT_MATCH :
2823 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2825 case 'M': /* --dhcp-boot */
2827 struct dhcp_netid *id = NULL;
2828 while (is_tag_prefix(arg))
2830 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2831 newid->next = id;
2832 id = newid;
2833 comma = split(arg);
2834 newid->net = opt_string_alloc(arg+4);
2835 arg = comma;
2838 if (!arg)
2839 ret_err(gen_err);
2840 else
2842 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2843 struct in_addr dhcp_next_server;
2844 struct dhcp_boot *new;
2845 comma = split(arg);
2846 dhcp_file = opt_string_alloc(arg);
2847 dhcp_next_server.s_addr = 0;
2848 if (comma)
2850 arg = comma;
2851 comma = split(arg);
2852 dhcp_sname = opt_string_alloc(arg);
2853 if (comma)
2855 unhide_metas(comma);
2856 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2859 * The user may have specified the tftp hostname here.
2860 * save it so that it can be resolved/looked up during
2861 * actual dhcp_reply().
2864 tftp_sname = opt_string_alloc(comma);
2865 dhcp_next_server.s_addr = 0;
2870 new = opt_malloc(sizeof(struct dhcp_boot));
2871 new->file = dhcp_file;
2872 new->sname = dhcp_sname;
2873 new->tftp_sname = tftp_sname;
2874 new->next_server = dhcp_next_server;
2875 new->netid = id;
2876 new->next = daemon->boot_config;
2877 daemon->boot_config = new;
2880 break;
2883 case LOPT_PXE_PROMT: /* --pxe-prompt */
2885 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2886 int timeout;
2888 new->netid = NULL;
2889 new->opt = 10; /* PXE_MENU_PROMPT */
2891 while (is_tag_prefix(arg))
2893 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2894 comma = split(arg);
2895 nn->next = new->netid;
2896 new->netid = nn;
2897 nn->net = opt_string_alloc(arg+4);
2898 arg = comma;
2901 if (!arg)
2902 ret_err(gen_err);
2903 else
2905 comma = split(arg);
2906 unhide_metas(arg);
2907 new->len = strlen(arg) + 1;
2908 new->val = opt_malloc(new->len);
2909 memcpy(new->val + 1, arg, new->len - 1);
2911 new->u.vendor_class = (unsigned char *)"PXEClient";
2912 new->flags = DHOPT_VENDOR;
2914 if (comma && atoi_check(comma, &timeout))
2915 *(new->val) = timeout;
2916 else
2917 *(new->val) = 255;
2919 new->next = daemon->dhcp_opts;
2920 daemon->dhcp_opts = new;
2921 daemon->enable_pxe = 1;
2924 break;
2927 case LOPT_PXE_SERV: /* --pxe-service */
2929 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2930 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2931 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2932 static int boottype = 32768;
2934 new->netid = NULL;
2935 new->sname = NULL;
2936 new->server.s_addr = 0;
2938 while (is_tag_prefix(arg))
2940 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2941 comma = split(arg);
2942 nn->next = new->netid;
2943 new->netid = nn;
2944 nn->net = opt_string_alloc(arg+4);
2945 arg = comma;
2948 if (arg && (comma = split(arg)))
2950 for (i = 0; CSA[i]; i++)
2951 if (strcasecmp(CSA[i], arg) == 0)
2952 break;
2954 if (CSA[i] || atoi_check(arg, &i))
2956 arg = comma;
2957 comma = split(arg);
2959 new->CSA = i;
2960 new->menu = opt_string_alloc(arg);
2962 if (!comma)
2964 new->type = 0; /* local boot */
2965 new->basename = NULL;
2967 else
2969 arg = comma;
2970 comma = split(arg);
2971 if (atoi_check(arg, &i))
2973 new->type = i;
2974 new->basename = NULL;
2976 else
2978 new->type = boottype++;
2979 new->basename = opt_string_alloc(arg);
2982 if (comma)
2984 if (!inet_pton(AF_INET, comma, &new->server))
2986 new->server.s_addr = 0;
2987 new->sname = opt_string_alloc(comma);
2993 /* Order matters */
2994 new->next = NULL;
2995 if (!daemon->pxe_services)
2996 daemon->pxe_services = new;
2997 else
2999 struct pxe_service *s;
3000 for (s = daemon->pxe_services; s->next; s = s->next);
3001 s->next = new;
3004 daemon->enable_pxe = 1;
3005 break;
3010 ret_err(gen_err);
3013 case '4': /* --dhcp-mac */
3015 if (!(comma = split(arg)))
3016 ret_err(gen_err);
3017 else
3019 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
3020 new->netid.net = opt_string_alloc(set_prefix(arg));
3021 unhide_metas(comma);
3022 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
3023 if (new->hwaddr_len == -1)
3024 ret_err(gen_err);
3025 else
3027 new->next = daemon->dhcp_macs;
3028 daemon->dhcp_macs = new;
3032 break;
3034 #ifdef OPTION6_PREFIX_CLASS
3035 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3037 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3039 if (!(comma = split(arg)) ||
3040 !atoi_check16(comma, &new->class))
3041 ret_err(gen_err);
3043 new->tag.net = opt_string_alloc(set_prefix(arg));
3044 new->next = daemon->prefix_classes;
3045 daemon->prefix_classes = new;
3047 break;
3049 #endif
3052 case 'U': /* --dhcp-vendorclass */
3053 case 'j': /* --dhcp-userclass */
3054 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3055 case LOPT_REMOTE: /* --dhcp-remoteid */
3056 case LOPT_SUBSCR: /* --dhcp-subscrid */
3058 unsigned char *p;
3059 int dig = 0;
3060 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3062 if (!(comma = split(arg)))
3063 ret_err(gen_err);
3065 new->netid.net = opt_string_alloc(set_prefix(arg));
3066 /* check for hex string - must digits may include : must not have nothing else,
3067 only allowed for agent-options. */
3069 arg = comma;
3070 if ((comma = split(arg)))
3072 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3073 ret_err(gen_err);
3074 else
3075 new->enterprise = atoi(arg+11);
3077 else
3078 comma = arg;
3080 for (p = (unsigned char *)comma; *p; p++)
3081 if (isxdigit(*p))
3082 dig = 1;
3083 else if (*p != ':')
3084 break;
3085 unhide_metas(comma);
3086 if (option == 'U' || option == 'j' || *p || !dig)
3088 new->len = strlen(comma);
3089 new->data = opt_malloc(new->len);
3090 memcpy(new->data, comma, new->len);
3092 else
3094 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3095 new->data = opt_malloc(new->len);
3096 memcpy(new->data, comma, new->len);
3099 switch (option)
3101 case 'j':
3102 new->match_type = MATCH_USER;
3103 break;
3104 case 'U':
3105 new->match_type = MATCH_VENDOR;
3106 break;
3107 case LOPT_CIRCUIT:
3108 new->match_type = MATCH_CIRCUIT;
3109 break;
3110 case LOPT_REMOTE:
3111 new->match_type = MATCH_REMOTE;
3112 break;
3113 case LOPT_SUBSCR:
3114 new->match_type = MATCH_SUBSCRIBER;
3115 break;
3117 new->next = daemon->dhcp_vendors;
3118 daemon->dhcp_vendors = new;
3120 break;
3123 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3124 if (!arg)
3126 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3127 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3129 else
3131 comma = split(arg);
3132 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3133 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
3134 ret_err(_("invalid port number"));
3135 if (!comma)
3136 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3138 break;
3140 case 'J': /* --dhcp-ignore */
3141 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3142 case LOPT_BROADCAST: /* --dhcp-broadcast */
3143 case '3': /* --bootp-dynamic */
3144 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
3146 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
3147 struct dhcp_netid *list = NULL;
3148 if (option == 'J')
3150 new->next = daemon->dhcp_ignore;
3151 daemon->dhcp_ignore = new;
3153 else if (option == LOPT_BROADCAST)
3155 new->next = daemon->force_broadcast;
3156 daemon->force_broadcast = new;
3158 else if (option == '3')
3160 new->next = daemon->bootp_dynamic;
3161 daemon->bootp_dynamic = new;
3163 else if (option == LOPT_GEN_NAMES)
3165 new->next = daemon->dhcp_gen_names;
3166 daemon->dhcp_gen_names = new;
3168 else
3170 new->next = daemon->dhcp_ignore_names;
3171 daemon->dhcp_ignore_names = new;
3174 while (arg) {
3175 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3176 comma = split(arg);
3177 member->next = list;
3178 list = member;
3179 if (is_tag_prefix(arg))
3180 member->net = opt_string_alloc(arg+4);
3181 else
3182 member->net = opt_string_alloc(arg);
3183 arg = comma;
3186 new->list = list;
3187 break;
3190 case LOPT_PROXY: /* --dhcp-proxy */
3191 daemon->override = 1;
3192 while (arg) {
3193 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3194 comma = split(arg);
3195 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
3196 ret_err(_("bad dhcp-proxy address"));
3197 new->next = daemon->override_relays;
3198 daemon->override_relays = new;
3199 arg = comma;
3201 break;
3203 case LOPT_RELAY: /* --dhcp-relay */
3205 struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
3206 comma = split(arg);
3207 new->interface = opt_string_alloc(split(comma));
3208 new->iface_index = 0;
3209 if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
3211 new->next = daemon->relay4;
3212 daemon->relay4 = new;
3214 #ifdef HAVE_DHCP6
3215 else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
3217 new->next = daemon->relay6;
3218 daemon->relay6 = new;
3220 #endif
3221 else
3222 ret_err(_("Bad dhcp-relay"));
3224 break;
3227 #endif
3229 #ifdef HAVE_DHCP6
3230 case LOPT_DUID: /* --dhcp-duid */
3231 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
3232 ret_err(_("bad DUID"));
3233 else
3235 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3236 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3237 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3239 break;
3240 #endif
3242 case 'V': /* --alias */
3244 char *dash, *a[3] = { NULL, NULL, NULL };
3245 int k = 0;
3246 struct doctor *new = opt_malloc(sizeof(struct doctor));
3247 new->next = daemon->doctors;
3248 daemon->doctors = new;
3249 new->mask.s_addr = 0xffffffff;
3250 new->end.s_addr = 0;
3252 if ((a[0] = arg))
3253 for (k = 1; k < 3; k++)
3255 if (!(a[k] = split(a[k-1])))
3256 break;
3257 unhide_metas(a[k]);
3260 dash = split_chr(a[0], '-');
3262 if ((k < 2) ||
3263 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3264 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
3265 option = '?';
3267 if (k == 3)
3268 inet_pton(AF_INET, a[2], &new->mask);
3270 if (dash &&
3271 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
3272 !is_same_net(new->in, new->end, new->mask) ||
3273 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3274 ret_err(_("invalid alias range"));
3276 break;
3279 case LOPT_INTNAME: /* --interface-name */
3281 struct interface_name *new, **up;
3282 char *domain = NULL;
3284 comma = split(arg);
3286 if (!comma || !(domain = canonicalise_opt(arg)))
3287 ret_err(_("bad interface name"));
3289 new = opt_malloc(sizeof(struct interface_name));
3290 new->next = NULL;
3291 new->addr4 = NULL;
3292 #ifdef HAVE_IPV6
3293 new->addr6 = NULL;
3294 #endif
3295 /* Add to the end of the list, so that first name
3296 of an interface is used for PTR lookups. */
3297 for (up = &daemon->int_names; *up; up = &((*up)->next));
3298 *up = new;
3299 new->name = domain;
3300 new->intr = opt_string_alloc(comma);
3301 break;
3304 case LOPT_CNAME: /* --cname */
3306 struct cname *new;
3307 char *alias;
3308 char *target;
3310 if (!(comma = split(arg)))
3311 ret_err(gen_err);
3313 alias = canonicalise_opt(arg);
3314 target = canonicalise_opt(comma);
3316 if (!alias || !target)
3317 ret_err(_("bad CNAME"));
3318 else
3320 for (new = daemon->cnames; new; new = new->next)
3321 if (hostname_isequal(new->alias, arg))
3322 ret_err(_("duplicate CNAME"));
3323 new = opt_malloc(sizeof(struct cname));
3324 new->next = daemon->cnames;
3325 daemon->cnames = new;
3326 new->alias = alias;
3327 new->target = target;
3330 break;
3333 case LOPT_PTR: /* --ptr-record */
3335 struct ptr_record *new;
3336 char *dom, *target = NULL;
3338 comma = split(arg);
3340 if (!(dom = canonicalise_opt(arg)) ||
3341 (comma && !(target = canonicalise_opt(comma))))
3342 ret_err(_("bad PTR record"));
3343 else
3345 new = opt_malloc(sizeof(struct ptr_record));
3346 new->next = daemon->ptr;
3347 daemon->ptr = new;
3348 new->name = dom;
3349 new->ptr = target;
3351 break;
3354 case LOPT_NAPTR: /* --naptr-record */
3356 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3357 int k = 0;
3358 struct naptr *new;
3359 int order, pref;
3360 char *name, *replace = NULL;
3362 if ((a[0] = arg))
3363 for (k = 1; k < 7; k++)
3364 if (!(a[k] = split(a[k-1])))
3365 break;
3368 if (k < 6 ||
3369 !(name = canonicalise_opt(a[0])) ||
3370 !atoi_check16(a[1], &order) ||
3371 !atoi_check16(a[2], &pref) ||
3372 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3373 ret_err(_("bad NAPTR record"));
3374 else
3376 new = opt_malloc(sizeof(struct naptr));
3377 new->next = daemon->naptr;
3378 daemon->naptr = new;
3379 new->name = name;
3380 new->flags = opt_string_alloc(a[3]);
3381 new->services = opt_string_alloc(a[4]);
3382 new->regexp = opt_string_alloc(a[5]);
3383 new->replace = replace;
3384 new->order = order;
3385 new->pref = pref;
3387 break;
3390 case LOPT_RR: /* dns-rr */
3392 struct txt_record *new;
3393 size_t len;
3394 char *data;
3395 int val;
3397 comma = split(arg);
3398 data = split(comma);
3400 new = opt_malloc(sizeof(struct txt_record));
3401 new->next = daemon->rr;
3402 daemon->rr = new;
3404 if (!atoi_check(comma, &val) ||
3405 !(new->name = canonicalise_opt(arg)) ||
3406 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
3407 ret_err(_("bad RR record"));
3409 new->class = val;
3410 new->len = 0;
3412 if (data)
3414 new->txt=opt_malloc(len);
3415 new->len = len;
3416 memcpy(new->txt, data, len);
3419 break;
3422 case 'Y': /* --txt-record */
3424 struct txt_record *new;
3425 unsigned char *p, *cnt;
3426 size_t len;
3428 comma = split(arg);
3430 new = opt_malloc(sizeof(struct txt_record));
3431 new->next = daemon->txt;
3432 daemon->txt = new;
3433 new->class = C_IN;
3435 if (!(new->name = canonicalise_opt(arg)))
3436 ret_err(_("bad TXT record"));
3438 len = comma ? strlen(comma) : 0;
3439 len += (len/255) + 1; /* room for extra counts */
3440 new->txt = p = opt_malloc(len);
3442 cnt = p++;
3443 *cnt = 0;
3445 while (comma && *comma)
3447 unsigned char c = (unsigned char)*comma++;
3449 if (c == ',' || *cnt == 255)
3451 if (c != ',')
3452 comma--;
3453 cnt = p++;
3454 *cnt = 0;
3456 else
3458 *p++ = unhide_meta(c);
3459 (*cnt)++;
3463 new->len = p - new->txt;
3465 break;
3468 case 'W': /* --srv-host */
3470 int port = 1, priority = 0, weight = 0;
3471 char *name, *target = NULL;
3472 struct mx_srv_record *new;
3474 comma = split(arg);
3476 if (!(name = canonicalise_opt(arg)))
3477 ret_err(_("bad SRV record"));
3479 if (comma)
3481 arg = comma;
3482 comma = split(arg);
3483 if (!(target = canonicalise_opt(arg)))
3484 ret_err(_("bad SRV target"));
3486 if (comma)
3488 arg = comma;
3489 comma = split(arg);
3490 if (!atoi_check16(arg, &port))
3491 ret_err(_("invalid port number"));
3493 if (comma)
3495 arg = comma;
3496 comma = split(arg);
3497 if (!atoi_check16(arg, &priority))
3498 ret_err(_("invalid priority"));
3500 if (comma)
3502 arg = comma;
3503 comma = split(arg);
3504 if (!atoi_check16(arg, &weight))
3505 ret_err(_("invalid weight"));
3511 new = opt_malloc(sizeof(struct mx_srv_record));
3512 new->next = daemon->mxnames;
3513 daemon->mxnames = new;
3514 new->issrv = 1;
3515 new->name = name;
3516 new->target = target;
3517 new->srvport = port;
3518 new->priority = priority;
3519 new->weight = weight;
3520 break;
3523 case LOPT_HOST_REC: /* --host-record */
3525 struct host_record *new = opt_malloc(sizeof(struct host_record));
3526 memset(new, 0, sizeof(struct host_record));
3528 if (!arg || !(comma = split(arg)))
3529 ret_err(_("Bad host-record"));
3531 while (arg)
3533 struct all_addr addr;
3534 if (inet_pton(AF_INET, arg, &addr))
3535 new->addr = addr.addr.addr4;
3536 #ifdef HAVE_IPV6
3537 else if (inet_pton(AF_INET6, arg, &addr))
3538 new->addr6 = addr.addr.addr6;
3539 #endif
3540 else
3542 int nomem;
3543 char *canon = canonicalise(arg, &nomem);
3544 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3545 if (!canon)
3546 ret_err(_("Bad name in host-record"));
3548 nl->name = canon;
3549 /* keep order, so that PTR record goes to first name */
3550 nl->next = NULL;
3551 if (!new->names)
3552 new->names = nl;
3553 else
3555 struct name_list *tmp;
3556 for (tmp = new->names; tmp->next; tmp = tmp->next);
3557 tmp->next = nl;
3561 arg = comma;
3562 comma = split(arg);
3565 /* Keep list order */
3566 if (!daemon->host_records_tail)
3567 daemon->host_records = new;
3568 else
3569 daemon->host_records_tail->next = new;
3570 new->next = NULL;
3571 daemon->host_records_tail = new;
3572 break;
3575 default:
3576 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3580 return 1;
3583 static void read_file(char *file, FILE *f, int hard_opt)
3585 volatile int lineno = 0;
3586 char *buff = daemon->namebuff;
3588 while (fgets(buff, MAXDNAME, f))
3590 int white, i, option = hard_opt;
3591 char *errmess, *p, *arg = NULL, *start;
3592 size_t len;
3594 /* Memory allocation failure longjmps here if mem_recover == 1 */
3595 if (option != 0)
3597 if (setjmp(mem_jmp))
3598 continue;
3599 mem_recover = 1;
3602 lineno++;
3603 errmess = NULL;
3605 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3606 metacharacters get hidden also strip comments */
3607 for (white = 1, p = buff; *p; p++)
3609 if (*p == '"')
3611 memmove(p, p+1, strlen(p+1)+1);
3613 for(; *p && *p != '"'; p++)
3615 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3617 if (p[1] == 't')
3618 p[1] = '\t';
3619 else if (p[1] == 'n')
3620 p[1] = '\n';
3621 else if (p[1] == 'b')
3622 p[1] = '\b';
3623 else if (p[1] == 'r')
3624 p[1] = '\r';
3625 else if (p[1] == 'e') /* escape */
3626 p[1] = '\033';
3627 memmove(p, p+1, strlen(p+1)+1);
3629 *p = hide_meta(*p);
3632 if (*p == 0)
3634 errmess = _("missing \"");
3635 goto oops;
3638 memmove(p, p+1, strlen(p+1)+1);
3641 if (isspace(*p))
3643 *p = ' ';
3644 white = 1;
3646 else
3648 if (white && *p == '#')
3650 *p = 0;
3651 break;
3653 white = 0;
3658 /* strip leading spaces */
3659 for (start = buff; *start && *start == ' '; start++);
3661 /* strip trailing spaces */
3662 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3664 if (len == 0)
3665 continue;
3666 else
3667 start[len] = 0;
3669 if (option != 0)
3670 arg = start;
3671 else if ((p=strchr(start, '=')))
3673 /* allow spaces around "=" */
3674 for (arg = p+1; *arg == ' '; arg++);
3675 for (; p >= start && (*p == ' ' || *p == '='); p--)
3676 *p = 0;
3678 else
3679 arg = NULL;
3681 if (option == 0)
3683 for (option = 0, i = 0; opts[i].name; i++)
3684 if (strcmp(opts[i].name, start) == 0)
3686 option = opts[i].val;
3687 break;
3690 if (!option)
3691 errmess = _("bad option");
3692 else if (opts[i].has_arg == 0 && arg)
3693 errmess = _("extraneous parameter");
3694 else if (opts[i].has_arg == 1 && !arg)
3695 errmess = _("missing parameter");
3698 oops:
3699 if (errmess)
3700 strcpy(daemon->namebuff, errmess);
3702 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
3704 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
3705 if (hard_opt != 0)
3706 my_syslog(LOG_ERR, "%s", daemon->namebuff);
3707 else
3708 die("%s", daemon->namebuff, EC_BADCONF);
3712 mem_recover = 0;
3713 fclose(f);
3716 static int one_file(char *file, int hard_opt)
3718 FILE *f;
3719 int nofile_ok = 0;
3720 static int read_stdin = 0;
3721 static struct fileread {
3722 dev_t dev;
3723 ino_t ino;
3724 struct fileread *next;
3725 } *filesread = NULL;
3727 if (hard_opt == '7')
3729 /* default conf-file reading */
3730 hard_opt = 0;
3731 nofile_ok = 1;
3734 if (hard_opt == 0 && strcmp(file, "-") == 0)
3736 if (read_stdin == 1)
3737 return 1;
3738 read_stdin = 1;
3739 file = "stdin";
3740 f = stdin;
3742 else
3744 /* ignore repeated files. */
3745 struct stat statbuf;
3747 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3749 struct fileread *r;
3751 for (r = filesread; r; r = r->next)
3752 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3753 return 1;
3755 r = safe_malloc(sizeof(struct fileread));
3756 r->next = filesread;
3757 filesread = r;
3758 r->dev = statbuf.st_dev;
3759 r->ino = statbuf.st_ino;
3762 if (!(f = fopen(file, "r")))
3764 if (errno == ENOENT && nofile_ok)
3765 return 1; /* No conffile, all done. */
3766 else
3768 char *str = _("cannot read %s: %s");
3769 if (hard_opt != 0)
3771 my_syslog(LOG_ERR, str, file, strerror(errno));
3772 return 0;
3774 else
3775 die(str, file, EC_FILE);
3780 read_file(file, f, hard_opt);
3781 return 1;
3784 /* expand any name which is a directory */
3785 struct hostsfile *expand_filelist(struct hostsfile *list)
3787 int i;
3788 struct hostsfile *ah;
3790 for (i = 0, ah = list; ah; ah = ah->next)
3792 if (i <= ah->index)
3793 i = ah->index + 1;
3795 if (ah->flags & AH_DIR)
3796 ah->flags |= AH_INACTIVE;
3797 else
3798 ah->flags &= ~AH_INACTIVE;
3801 for (ah = list; ah; ah = ah->next)
3802 if (!(ah->flags & AH_INACTIVE))
3804 struct stat buf;
3805 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3807 DIR *dir_stream;
3808 struct dirent *ent;
3810 /* don't read this as a file */
3811 ah->flags |= AH_INACTIVE;
3813 if (!(dir_stream = opendir(ah->fname)))
3814 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3815 ah->fname, strerror(errno));
3816 else
3818 while ((ent = readdir(dir_stream)))
3820 size_t lendir = strlen(ah->fname);
3821 size_t lenfile = strlen(ent->d_name);
3822 struct hostsfile *ah1;
3823 char *path;
3825 /* ignore emacs backups and dotfiles */
3826 if (lenfile == 0 ||
3827 ent->d_name[lenfile - 1] == '~' ||
3828 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3829 ent->d_name[0] == '.')
3830 continue;
3832 /* see if we have an existing record.
3833 dir is ah->fname
3834 file is ent->d_name
3835 path to match is ah1->fname */
3837 for (ah1 = list; ah1; ah1 = ah1->next)
3839 if (lendir < strlen(ah1->fname) &&
3840 strstr(ah1->fname, ah->fname) == ah1->fname &&
3841 ah1->fname[lendir] == '/' &&
3842 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3844 ah1->flags &= ~AH_INACTIVE;
3845 break;
3849 /* make new record */
3850 if (!ah1)
3852 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3853 continue;
3855 if (!(path = whine_malloc(lendir + lenfile + 2)))
3857 free(ah1);
3858 continue;
3861 strcpy(path, ah->fname);
3862 strcat(path, "/");
3863 strcat(path, ent->d_name);
3864 ah1->fname = path;
3865 ah1->index = i++;
3866 ah1->flags = AH_DIR;
3867 ah1->next = list;
3868 list = ah1;
3871 /* inactivate record if not regular file */
3872 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3873 ah1->flags |= AH_INACTIVE;
3876 closedir(dir_stream);
3881 return list;
3885 #ifdef HAVE_DHCP
3886 void reread_dhcp(void)
3888 struct hostsfile *hf;
3890 if (daemon->dhcp_hosts_file)
3892 struct dhcp_config *configs, *cp, **up;
3894 /* remove existing... */
3895 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3897 cp = configs->next;
3899 if (configs->flags & CONFIG_BANK)
3901 struct hwaddr_config *mac, *tmp;
3902 struct dhcp_netid_list *list, *tmplist;
3904 for (mac = configs->hwaddr; mac; mac = tmp)
3906 tmp = mac->next;
3907 free(mac);
3910 if (configs->flags & CONFIG_CLID)
3911 free(configs->clid);
3913 for (list = configs->netid; list; list = tmplist)
3915 free(list->list);
3916 tmplist = list->next;
3917 free(list);
3920 if (configs->flags & CONFIG_NAME)
3921 free(configs->hostname);
3923 *up = configs->next;
3924 free(configs);
3926 else
3927 up = &configs->next;
3930 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3931 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3932 if (!(hf->flags & AH_INACTIVE))
3934 if (one_file(hf->fname, LOPT_BANK))
3935 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3939 if (daemon->dhcp_opts_file)
3941 struct dhcp_opt *opts, *cp, **up;
3942 struct dhcp_netid *id, *next;
3944 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3946 cp = opts->next;
3948 if (opts->flags & DHOPT_BANK)
3950 if ((opts->flags & DHOPT_VENDOR))
3951 free(opts->u.vendor_class);
3952 free(opts->val);
3953 for (id = opts->netid; id; id = next)
3955 next = id->next;
3956 free(id->net);
3957 free(id);
3959 *up = opts->next;
3960 free(opts);
3962 else
3963 up = &opts->next;
3966 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3967 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3968 if (!(hf->flags & AH_INACTIVE))
3970 if (one_file(hf->fname, LOPT_OPTS))
3971 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3975 #endif
3977 void read_opts(int argc, char **argv, char *compile_opts)
3979 char *buff = opt_malloc(MAXDNAME);
3980 int option, conffile_opt = '7', testmode = 0;
3981 char *arg, *conffile = CONFFILE;
3983 opterr = 0;
3985 daemon = opt_malloc(sizeof(struct daemon));
3986 memset(daemon, 0, sizeof(struct daemon));
3987 daemon->namebuff = buff;
3989 /* Set defaults - everything else is zero or NULL */
3990 daemon->cachesize = CACHESIZ;
3991 daemon->ftabsize = FTABSIZ;
3992 daemon->port = NAMESERVER_PORT;
3993 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3994 daemon->dhcp_server_port = DHCP_SERVER_PORT;
3995 daemon->default_resolv.is_default = 1;
3996 daemon->default_resolv.name = RESOLVFILE;
3997 daemon->resolv_files = &daemon->default_resolv;
3998 daemon->username = CHUSER;
3999 daemon->runfile = RUNFILE;
4000 daemon->dhcp_max = MAXLEASES;
4001 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
4002 daemon->edns_pktsz = EDNS_PKTSZ;
4003 daemon->log_fac = -1;
4004 daemon->auth_ttl = AUTH_TTL;
4005 daemon->soa_refresh = SOA_REFRESH;
4006 daemon->soa_retry = SOA_RETRY;
4007 daemon->soa_expiry = SOA_EXPIRY;
4008 add_txt("version.bind", "dnsmasq-" VERSION );
4009 add_txt("authors.bind", "Simon Kelley");
4010 add_txt("copyright.bind", COPYRIGHT);
4012 while (1)
4014 #ifdef HAVE_GETOPT_LONG
4015 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
4016 #else
4017 option = getopt(argc, argv, OPTSTRING);
4018 #endif
4020 if (option == -1)
4022 for (; optind < argc; optind++)
4024 unsigned char *c = (unsigned char *)argv[optind];
4025 for (; *c != 0; c++)
4026 if (!isspace(*c))
4027 die(_("junk found in command line"), NULL, EC_BADCONF);
4029 break;
4032 /* Copy optarg so that argv doesn't get changed */
4033 if (optarg)
4035 strncpy(buff, optarg, MAXDNAME);
4036 buff[MAXDNAME-1] = 0;
4037 arg = buff;
4039 else
4040 arg = NULL;
4042 /* command-line only stuff */
4043 if (option == LOPT_TEST)
4044 testmode = 1;
4045 else if (option == 'w')
4047 #ifdef HAVE_DHCP
4048 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
4049 display_opts();
4050 #ifdef HAVE_DHCP6
4051 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4052 display_opts6();
4053 #endif
4054 else
4055 #endif
4056 do_usage();
4058 exit(0);
4060 else if (option == 'v')
4062 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
4063 printf(_("Compile time options: %s\n\n"), compile_opts);
4064 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4065 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
4066 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
4067 exit(0);
4069 else if (option == 'C')
4071 conffile_opt = 0; /* file must exist */
4072 conffile = opt_string_alloc(arg);
4074 else
4076 #ifdef HAVE_GETOPT_LONG
4077 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
4078 #else
4079 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
4080 #endif
4081 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
4085 if (conffile)
4086 one_file(conffile, conffile_opt);
4088 /* port might not be known when the address is parsed - fill in here */
4089 if (daemon->servers)
4091 struct server *tmp;
4092 for (tmp = daemon->servers; tmp; tmp = tmp->next)
4093 if (!(tmp->flags & SERV_HAS_SOURCE))
4095 if (tmp->source_addr.sa.sa_family == AF_INET)
4096 tmp->source_addr.in.sin_port = htons(daemon->query_port);
4097 #ifdef HAVE_IPV6
4098 else if (tmp->source_addr.sa.sa_family == AF_INET6)
4099 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
4100 #endif
4104 if (daemon->if_addrs)
4106 struct iname *tmp;
4107 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
4108 if (tmp->addr.sa.sa_family == AF_INET)
4109 tmp->addr.in.sin_port = htons(daemon->port);
4110 #ifdef HAVE_IPV6
4111 else if (tmp->addr.sa.sa_family == AF_INET6)
4112 tmp->addr.in6.sin6_port = htons(daemon->port);
4113 #endif /* IPv6 */
4116 /* create default, if not specified */
4117 if (daemon->authserver && !daemon->hostmaster)
4119 strcpy(buff, "hostmaster.");
4120 strcat(buff, daemon->authserver);
4121 daemon->hostmaster = opt_string_alloc(buff);
4124 /* only one of these need be specified: the other defaults to the host-name */
4125 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
4127 struct mx_srv_record *mx;
4129 if (gethostname(buff, MAXDNAME) == -1)
4130 die(_("cannot get host-name: %s"), NULL, EC_MISC);
4132 for (mx = daemon->mxnames; mx; mx = mx->next)
4133 if (!mx->issrv && hostname_isequal(mx->name, buff))
4134 break;
4136 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
4138 mx = opt_malloc(sizeof(struct mx_srv_record));
4139 mx->next = daemon->mxnames;
4140 mx->issrv = 0;
4141 mx->target = NULL;
4142 mx->name = opt_string_alloc(buff);
4143 daemon->mxnames = mx;
4146 if (!daemon->mxtarget)
4147 daemon->mxtarget = opt_string_alloc(buff);
4149 for (mx = daemon->mxnames; mx; mx = mx->next)
4150 if (!mx->issrv && !mx->target)
4151 mx->target = daemon->mxtarget;
4154 if (!option_bool(OPT_NO_RESOLV) &&
4155 daemon->resolv_files &&
4156 daemon->resolv_files->next &&
4157 option_bool(OPT_NO_POLL))
4158 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
4160 if (option_bool(OPT_RESOLV_DOMAIN))
4162 char *line;
4163 FILE *f;
4165 if (option_bool(OPT_NO_RESOLV) ||
4166 !daemon->resolv_files ||
4167 (daemon->resolv_files)->next)
4168 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
4170 if (!(f = fopen((daemon->resolv_files)->name, "r")))
4171 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
4173 while ((line = fgets(buff, MAXDNAME, f)))
4175 char *token = strtok(line, " \t\n\r");
4177 if (!token || strcmp(token, "search") != 0)
4178 continue;
4180 if ((token = strtok(NULL, " \t\n\r")) &&
4181 (daemon->domain_suffix = canonicalise_opt(token)))
4182 break;
4185 fclose(f);
4187 if (!daemon->domain_suffix)
4188 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
4191 if (daemon->domain_suffix)
4193 /* add domain for any srv record without one. */
4194 struct mx_srv_record *srv;
4196 for (srv = daemon->mxnames; srv; srv = srv->next)
4197 if (srv->issrv &&
4198 strchr(srv->name, '.') &&
4199 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4201 strcpy(buff, srv->name);
4202 strcat(buff, ".");
4203 strcat(buff, daemon->domain_suffix);
4204 free(srv->name);
4205 srv->name = opt_string_alloc(buff);
4208 else if (option_bool(OPT_DHCP_FQDN))
4209 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
4211 if (testmode)
4213 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4214 exit(0);