Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnsmasq / src / option.c
blob2cfd8b0ec80cace18cd9ad516dec3aa8a28cbdb6
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
136 #ifdef HAVE_QUIET_DHCP //Originally TOMATO option
137 #define LOPT_QUIET_DHCP 322
138 #define LOPT_QUIET_DHCP6 323
139 #define LOPT_QUIET_RA 324
140 #endif
142 #ifdef HAVE_GETOPT_LONG
143 static const struct option opts[] =
144 #else
145 static const struct myoption opts[] =
146 #endif
148 { "version", 0, 0, 'v' },
149 { "no-hosts", 0, 0, 'h' },
150 { "no-poll", 0, 0, 'n' },
151 { "help", 0, 0, 'w' },
152 { "no-daemon", 0, 0, 'd' },
153 { "log-queries", 0, 0, 'q' },
154 { "user", 2, 0, 'u' },
155 { "group", 2, 0, 'g' },
156 { "resolv-file", 2, 0, 'r' },
157 { "mx-host", 1, 0, 'm' },
158 { "mx-target", 1, 0, 't' },
159 { "cache-size", 2, 0, 'c' },
160 { "port", 1, 0, 'p' },
161 { "dhcp-leasefile", 2, 0, 'l' },
162 { "dhcp-lease", 1, 0, 'l' },
163 { "dhcp-host", 1, 0, 'G' },
164 { "dhcp-range", 1, 0, 'F' },
165 { "dhcp-option", 1, 0, 'O' },
166 { "dhcp-boot", 1, 0, 'M' },
167 { "domain", 1, 0, 's' },
168 { "domain-suffix", 1, 0, 's' },
169 { "interface", 1, 0, 'i' },
170 { "listen-address", 1, 0, 'a' },
171 { "bogus-priv", 0, 0, 'b' },
172 { "bogus-nxdomain", 1, 0, 'B' },
173 { "selfmx", 0, 0, 'e' },
174 { "filterwin2k", 0, 0, 'f' },
175 { "pid-file", 2, 0, 'x' },
176 { "strict-order", 0, 0, 'o' },
177 { "server", 1, 0, 'S' },
178 { "local", 1, 0, LOPT_LOCAL },
179 { "address", 1, 0, 'A' },
180 { "conf-file", 2, 0, 'C' },
181 { "no-resolv", 0, 0, 'R' },
182 { "expand-hosts", 0, 0, 'E' },
183 { "localmx", 0, 0, 'L' },
184 { "local-ttl", 1, 0, 'T' },
185 { "no-negcache", 0, 0, 'N' },
186 { "addn-hosts", 1, 0, 'H' },
187 { "query-port", 1, 0, 'Q' },
188 { "except-interface", 1, 0, 'I' },
189 { "no-dhcp-interface", 1, 0, '2' },
190 { "domain-needed", 0, 0, 'D' },
191 { "dhcp-lease-max", 1, 0, 'X' },
192 { "bind-interfaces", 0, 0, 'z' },
193 { "read-ethers", 0, 0, 'Z' },
194 { "alias", 1, 0, 'V' },
195 { "dhcp-vendorclass", 1, 0, 'U' },
196 { "dhcp-userclass", 1, 0, 'j' },
197 { "dhcp-ignore", 1, 0, 'J' },
198 { "edns-packet-max", 1, 0, 'P' },
199 { "keep-in-foreground", 0, 0, 'k' },
200 { "dhcp-authoritative", 0, 0, 'K' },
201 { "srv-host", 1, 0, 'W' },
202 { "localise-queries", 0, 0, 'y' },
203 { "txt-record", 1, 0, 'Y' },
204 { "dns-rr", 1, 0, LOPT_RR },
205 { "enable-dbus", 2, 0, '1' },
206 { "bootp-dynamic", 2, 0, '3' },
207 { "dhcp-mac", 1, 0, '4' },
208 { "no-ping", 0, 0, '5' },
209 { "dhcp-script", 1, 0, '6' },
210 { "conf-dir", 1, 0, '7' },
211 { "log-facility", 1, 0 ,'8' },
212 { "leasefile-ro", 0, 0, '9' },
213 { "dns-forward-max", 1, 0, '0' },
214 { "clear-on-reload", 0, 0, LOPT_RELOAD },
215 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
216 { "enable-tftp", 0, 0, LOPT_TFTP },
217 { "tftp-secure", 0, 0, LOPT_SECURE },
218 { "tftp-unique-root", 0, 0, LOPT_APREF },
219 { "tftp-root", 1, 0, LOPT_PREFIX },
220 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
221 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
222 { "ptr-record", 1, 0, LOPT_PTR },
223 { "naptr-record", 1, 0, LOPT_NAPTR },
224 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
225 { "dhcp-option-force", 1, 0, LOPT_FORCE },
226 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
227 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
228 { "log-async", 2, 0, LOPT_MAX_LOGS },
229 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
230 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
231 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
232 { "interface-name", 1, 0, LOPT_INTNAME },
233 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
234 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
235 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
236 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
237 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
238 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
239 { "all-servers", 0, 0, LOPT_NOLAST },
240 { "dhcp-match", 1, 0, LOPT_MATCH },
241 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
242 { "neg-ttl", 1, 0, LOPT_NEGTTL },
243 { "max-ttl", 1, 0, LOPT_MAXTTL },
244 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
245 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
246 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
247 { "min-port", 1, 0, LOPT_MINPORT },
248 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
249 { "cname", 1, 0, LOPT_CNAME },
250 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
251 { "pxe-service", 1, 0, LOPT_PXE_SERV },
252 { "test", 0, 0, LOPT_TEST },
253 { "tag-if", 1, 0, LOPT_TAG_IF },
254 { "dhcp-proxy", 2, 0, LOPT_PROXY },
255 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
256 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
257 { "add-mac", 0, 0, LOPT_ADD_MAC },
258 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
259 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
260 { "conntrack", 0, 0, LOPT_CONNTRACK },
261 { "dhcp-client-update", 0, 0, LOPT_FQDN },
262 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
263 { "enable-ra", 0, 0, LOPT_RA },
264 { "dhcp-duid", 1, 0, LOPT_DUID },
265 { "host-record", 1, 0, LOPT_HOST_REC },
266 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
267 { "auth-zone", 1, 0, LOPT_AUTHZONE },
268 { "auth-server", 1, 0, LOPT_AUTHSERV },
269 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
270 { "auth-soa", 1, 0, LOPT_AUTHSOA },
271 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
272 { "auth-peer", 1, 0, LOPT_AUTHPEER },
273 { "ipset", 1, 0, LOPT_IPSET },
274 { "synth-domain", 1, 0, LOPT_SYNTH },
275 #ifdef OPTION6_PREFIX_CLASS
276 { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
277 #endif
278 #ifdef HAVE_QUIET_DHCP //Originally TOMATO option
279 { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
280 { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
281 { "quiet-ra", 0, 0, LOPT_QUIET_RA },
282 #endif
283 { NULL, 0, 0, 0 }
287 #define ARG_DUP OPT_LAST
288 #define ARG_ONE OPT_LAST + 1
289 #define ARG_USED_CL OPT_LAST + 2
290 #define ARG_USED_FILE OPT_LAST + 3
292 static struct {
293 int opt;
294 unsigned int rept;
295 char * const flagdesc;
296 char * const desc;
297 char * const arg;
298 } usage[] = {
299 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
300 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
301 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
302 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
303 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
304 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
305 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
306 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
307 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
308 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
309 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
310 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
311 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
312 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
313 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
314 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
315 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
316 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
317 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
318 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
319 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
320 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
321 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
322 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
323 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
324 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
325 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
326 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
327 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
328 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
329 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
330 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
331 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
332 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
333 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
334 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
335 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
336 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
337 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
338 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
339 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
340 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
341 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
342 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
343 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
344 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
345 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
346 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
347 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
348 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
349 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
350 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
351 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
352 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
353 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
354 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
355 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
356 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
357 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
358 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
359 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
360 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
361 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
362 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
363 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
364 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
365 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
366 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
367 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
368 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
369 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
370 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
371 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
372 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
373 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
374 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
375 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
376 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
377 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
378 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
379 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
380 { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
381 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
382 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
383 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
384 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
385 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
386 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
387 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
388 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
389 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
390 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
391 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
392 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
393 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
394 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
395 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
396 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
397 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
398 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
399 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
400 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
401 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
402 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
403 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
404 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
405 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
406 { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
407 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
408 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
409 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
410 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
411 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
412 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
413 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
414 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
415 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
416 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
417 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
418 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
419 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
420 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
421 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
422 { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
423 #ifdef OPTION6_PREFIX_CLASS
424 { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
425 #endif
426 #ifdef HAVE_QUIET_DHCP //originally TOMATO option
427 { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log DHCP packets."), NULL },
428 { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log DHCPv6 packets."), NULL },
429 { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA packets."), NULL },
430 #endif
431 { 0, 0, NULL, NULL, NULL }
434 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
435 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
436 following sequence so that they map to themselves: it is therefore possible to call
437 unhide_metas repeatedly on string without breaking things.
438 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
439 couple of other places.
440 Note that space is included here so that
441 --dhcp-option=3, string
442 has five characters, whilst
443 --dhcp-option=3," string"
444 has six.
447 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
449 static char hide_meta(char c)
451 unsigned int i;
453 for (i = 0; i < (sizeof(meta) - 1); i++)
454 if (c == meta[i])
455 return (char)i;
457 return c;
460 static char unhide_meta(char cr)
462 unsigned int c = cr;
464 if (c < (sizeof(meta) - 1))
465 cr = meta[c];
467 return cr;
470 static void unhide_metas(char *cp)
472 if (cp)
473 for(; *cp; cp++)
474 *cp = unhide_meta(*cp);
477 static void *opt_malloc(size_t size)
479 void *ret;
481 if (mem_recover)
483 ret = whine_malloc(size);
484 if (!ret)
485 longjmp(mem_jmp, 1);
487 else
488 ret = safe_malloc(size);
490 return ret;
493 static char *opt_string_alloc(char *cp)
495 char *ret = NULL;
497 if (cp && strlen(cp) != 0)
499 ret = opt_malloc(strlen(cp)+1);
500 strcpy(ret, cp);
502 /* restore hidden metachars */
503 unhide_metas(ret);
506 return ret;
510 /* find next comma, split string with zero and eliminate spaces.
511 return start of string following comma */
513 static char *split_chr(char *s, char c)
515 char *comma, *p;
517 if (!s || !(comma = strchr(s, c)))
518 return NULL;
520 p = comma;
521 *comma = ' ';
523 for (; *comma == ' '; comma++);
525 for (; (p >= s) && *p == ' '; p--)
526 *p = 0;
528 return comma;
531 static char *split(char *s)
533 return split_chr(s, ',');
536 static char *canonicalise_opt(char *s)
538 char *ret;
539 int nomem;
541 if (!s)
542 return 0;
544 unhide_metas(s);
545 if (!(ret = canonicalise(s, &nomem)) && nomem)
547 if (mem_recover)
548 longjmp(mem_jmp, 1);
549 else
550 die(_("could not get memory"), NULL, EC_NOMEM);
553 return ret;
556 static int atoi_check(char *a, int *res)
558 char *p;
560 if (!a)
561 return 0;
563 unhide_metas(a);
565 for (p = a; *p; p++)
566 if (*p < '0' || *p > '9')
567 return 0;
569 *res = atoi(a);
570 return 1;
573 static int atoi_check16(char *a, int *res)
575 if (!(atoi_check(a, res)) ||
576 *res < 0 ||
577 *res > 0xffff)
578 return 0;
580 return 1;
583 static void add_txt(char *name, char *txt)
585 size_t len = strlen(txt);
586 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
588 r->name = opt_string_alloc(name);
589 r->next = daemon->txt;
590 daemon->txt = r;
591 r->class = C_CHAOS;
592 r->txt = opt_malloc(len+1);
593 r->len = len+1;
594 *(r->txt) = len;
595 memcpy((r->txt)+1, txt, len);
598 static void do_usage(void)
600 char buff[100];
601 int i, j;
603 struct {
604 char handle;
605 int val;
606 } tab[] = {
607 { '$', CACHESIZ },
608 { '*', EDNS_PKTSZ },
609 { '&', MAXLEASES },
610 { '!', FTABSIZ },
611 { '#', TFTP_MAX_CONNECTIONS },
612 { '\0', 0 }
615 printf(_("Usage: dnsmasq [options]\n\n"));
616 #ifndef HAVE_GETOPT_LONG
617 printf(_("Use short options only on the command line.\n"));
618 #endif
619 printf(_("Valid options are:\n"));
621 for (i = 0; usage[i].opt != 0; i++)
623 char *desc = usage[i].flagdesc;
624 char *eq = "=";
626 if (!desc || *desc == '[')
627 eq = "";
629 if (!desc)
630 desc = "";
632 for ( j = 0; opts[j].name; j++)
633 if (opts[j].val == usage[i].opt)
634 break;
635 if (usage[i].opt < 256)
636 sprintf(buff, "-%c, ", usage[i].opt);
637 else
638 sprintf(buff, " ");
640 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
641 printf("%-40.40s", buff);
643 if (usage[i].arg)
645 strcpy(buff, usage[i].arg);
646 for (j = 0; tab[j].handle; j++)
647 if (tab[j].handle == *(usage[i].arg))
648 sprintf(buff, "%d", tab[j].val);
650 printf(_(usage[i].desc), buff);
651 printf("\n");
655 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
657 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
659 int source_port = 0, serv_port = NAMESERVER_PORT;
660 char *portno, *source;
661 #ifdef HAVE_IPV6
662 int scope_index = 0;
663 char *scope_id;
664 #endif
666 if ((source = split_chr(arg, '@')) && /* is there a source. */
667 (portno = split_chr(source, '#')) &&
668 !atoi_check16(portno, &source_port))
669 return _("bad port");
671 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
672 !atoi_check16(portno, &serv_port))
673 return _("bad port");
675 #ifdef HAVE_IPV6
676 scope_id = split_chr(arg, '%');
677 #endif
679 if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
681 addr->in.sin_port = htons(serv_port);
682 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
683 #ifdef HAVE_SOCKADDR_SA_LEN
684 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
685 #endif
686 source_addr->in.sin_addr.s_addr = INADDR_ANY;
687 source_addr->in.sin_port = htons(daemon->query_port);
689 if (source)
691 if (flags)
692 *flags |= SERV_HAS_SOURCE;
693 source_addr->in.sin_port = htons(source_port);
694 if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
696 #if defined(SO_BINDTODEVICE)
697 source_addr->in.sin_addr.s_addr = INADDR_ANY;
698 strncpy(interface, source, IF_NAMESIZE - 1);
699 #else
700 return _("interface binding not supported");
701 #endif
705 #ifdef HAVE_IPV6
706 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
708 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
709 return _("bad interface name");
711 addr->in6.sin6_port = htons(serv_port);
712 addr->in6.sin6_scope_id = scope_index;
713 source_addr->in6.sin6_addr = in6addr_any;
714 source_addr->in6.sin6_port = htons(daemon->query_port);
715 source_addr->in6.sin6_scope_id = 0;
716 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
717 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
718 #ifdef HAVE_SOCKADDR_SA_LEN
719 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
720 #endif
721 if (source)
723 if (flags)
724 *flags |= SERV_HAS_SOURCE;
725 source_addr->in6.sin6_port = htons(source_port);
726 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
728 #if defined(SO_BINDTODEVICE)
729 source_addr->in6.sin6_addr = in6addr_any;
730 strncpy(interface, source, IF_NAMESIZE - 1);
731 #else
732 return _("interface binding not supported");
733 #endif
737 #endif
738 else
739 return _("bad address");
741 return NULL;
744 #ifdef HAVE_DHCP
746 static int is_tag_prefix(char *arg)
748 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
749 return 1;
751 return 0;
754 static char *set_prefix(char *arg)
756 if (strstr(arg, "set:") == arg)
757 return arg+4;
759 return arg;
762 /* This is too insanely large to keep in-line in the switch */
763 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
765 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
766 char lenchar = 0, *cp;
767 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
768 char *comma = NULL;
769 struct dhcp_netid *np = NULL;
770 u16 opt_len = 0;
771 int is6 = 0;
772 int option_ok = 0;
774 new->len = 0;
775 new->flags = flags;
776 new->netid = NULL;
777 new->val = NULL;
778 new->opt = 0;
780 while (arg)
782 comma = split(arg);
784 for (cp = arg; *cp; cp++)
785 if (*cp < '0' || *cp > '9')
786 break;
788 if (!*cp)
790 new->opt = atoi(arg);
791 opt_len = 0;
792 option_ok = 1;
793 break;
796 if (strstr(arg, "option:") == arg)
798 if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
800 opt_len = lookup_dhcp_len(AF_INET, new->opt);
801 /* option:<optname> must follow tag and vendor string. */
802 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
803 option_ok = 1;
805 break;
807 #ifdef HAVE_DHCP6
808 else if (strstr(arg, "option6:") == arg)
810 for (cp = arg+8; *cp; cp++)
811 if (*cp < '0' || *cp > '9')
812 break;
814 if (!*cp)
816 new->opt = atoi(arg+8);
817 opt_len = 0;
818 option_ok = 1;
820 else
822 if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
824 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
825 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
826 option_ok = 1;
829 /* option6:<opt>|<optname> must follow tag and vendor string. */
830 is6 = 1;
831 break;
833 #endif
834 else if (strstr(arg, "vendor:") == arg)
836 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
837 new->flags |= DHOPT_VENDOR;
839 else if (strstr(arg, "encap:") == arg)
841 new->u.encap = atoi(arg+6);
842 new->flags |= DHOPT_ENCAPSULATE;
844 else if (strstr(arg, "vi-encap:") == arg)
846 new->u.encap = atoi(arg+9);
847 new->flags |= DHOPT_RFC3925;
848 if (flags == DHOPT_MATCH)
850 option_ok = 1;
851 break;
854 else
856 new->netid = opt_malloc(sizeof (struct dhcp_netid));
857 /* allow optional "net:" or "tag:" for consistency */
858 if (is_tag_prefix(arg))
859 new->netid->net = opt_string_alloc(arg+4);
860 else
861 new->netid->net = opt_string_alloc(set_prefix(arg));
862 new->netid->next = np;
863 np = new->netid;
866 arg = comma;
869 #ifdef HAVE_DHCP6
870 if (is6)
872 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
873 ret_err(_("unsupported encapsulation for IPv6 option"));
875 if (opt_len == 0 &&
876 !(new->flags & DHOPT_RFC3925))
877 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
879 else
880 #endif
881 if (opt_len == 0 &&
882 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
883 opt_len = lookup_dhcp_len(AF_INET, new->opt);
885 /* option may be missing with rfc3925 match */
886 if (!option_ok)
887 ret_err(_("bad dhcp-option"));
889 if (comma)
891 /* characterise the value */
892 char c;
893 int found_dig = 0;
894 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
895 addrs = digs = 1;
896 dots = 0;
897 for (cp = comma; (c = *cp); cp++)
898 if (c == ',')
900 addrs++;
901 is_dec = is_hex = 0;
903 else if (c == ':')
905 digs++;
906 is_dec = is_addr = 0;
908 else if (c == '/')
910 is_addr6 = is_dec = is_hex = 0;
911 if (cp == comma) /* leading / means a pathname */
912 is_addr = 0;
914 else if (c == '.')
916 is_addr6 = is_dec = is_hex = 0;
917 dots++;
919 else if (c == '-')
920 is_hex = is_addr = is_addr6 = 0;
921 else if (c == ' ')
922 is_dec = is_hex = 0;
923 else if (!(c >='0' && c <= '9'))
925 is_addr = 0;
926 if (cp[1] == 0 && is_dec &&
927 (c == 'b' || c == 's' || c == 'i'))
929 lenchar = c;
930 *cp = 0;
932 else
933 is_dec = 0;
934 if (!((c >='A' && c <= 'F') ||
935 (c >='a' && c <= 'f') ||
936 (c == '*' && (flags & DHOPT_MATCH))))
938 is_hex = 0;
939 if (c != '[' && c != ']')
940 is_addr6 = 0;
943 else
944 found_dig = 1;
946 if (!found_dig)
947 is_dec = is_addr = 0;
949 /* We know that some options take addresses */
950 if (opt_len & OT_ADDR_LIST)
952 is_string = is_dec = is_hex = 0;
954 if (!is6 && (!is_addr || dots == 0))
955 ret_err(_("bad IP address"));
957 if (is6 && !is_addr6)
958 ret_err(_("bad IPv6 address"));
960 /* or names */
961 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
962 is_addr6 = is_addr = is_dec = is_hex = 0;
964 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
966 int val, fac = 1;
968 switch (comma[strlen(comma) - 1])
970 case 'w':
971 case 'W':
972 fac *= 7;
973 /* fall through */
974 case 'd':
975 case 'D':
976 fac *= 24;
977 /* fall though */
978 case 'h':
979 case 'H':
980 fac *= 60;
981 /* fall through */
982 case 'm':
983 case 'M':
984 fac *= 60;
985 /* fall through */
986 case 's':
987 case 'S':
988 comma[strlen(comma) - 1] = 0;
991 new->len = 4;
992 new->val = opt_malloc(4);
993 val = atoi(comma);
994 *((int *)new->val) = htonl(val * fac);
996 else if (is_hex && digs > 1)
998 new->len = digs;
999 new->val = opt_malloc(new->len);
1000 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
1001 new->flags |= DHOPT_HEX;
1003 else if (is_dec)
1005 int i, val = atoi(comma);
1006 /* assume numeric arg is 1 byte except for
1007 options where it is known otherwise.
1008 For vendor class option, we have to hack. */
1009 if (opt_len != 0)
1010 new->len = opt_len;
1011 else if (val & 0xffff0000)
1012 new->len = 4;
1013 else if (val & 0xff00)
1014 new->len = 2;
1015 else
1016 new->len = 1;
1018 if (lenchar == 'b')
1019 new->len = 1;
1020 else if (lenchar == 's')
1021 new->len = 2;
1022 else if (lenchar == 'i')
1023 new->len = 4;
1025 new->val = opt_malloc(new->len);
1026 for (i=0; i<new->len; i++)
1027 new->val[i] = val>>((new->len - i - 1)*8);
1029 else if (is_addr && !is6)
1031 struct in_addr in;
1032 unsigned char *op;
1033 char *slash;
1034 /* max length of address/subnet descriptor is five bytes,
1035 add one for the option 120 enc byte too */
1036 new->val = op = opt_malloc((5 * addrs) + 1);
1037 new->flags |= DHOPT_ADDR;
1039 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1040 new->opt == OPTION_SIP_SERVER)
1042 *(op++) = 1; /* RFC 3361 "enc byte" */
1043 new->flags &= ~DHOPT_ADDR;
1045 while (addrs--)
1047 cp = comma;
1048 comma = split(cp);
1049 slash = split_chr(cp, '/');
1050 inet_pton(AF_INET, cp, &in);
1051 if (!slash)
1053 memcpy(op, &in, INADDRSZ);
1054 op += INADDRSZ;
1056 else
1058 unsigned char *p = (unsigned char *)&in;
1059 int netsize = atoi(slash);
1060 *op++ = netsize;
1061 if (netsize > 0)
1062 *op++ = *p++;
1063 if (netsize > 8)
1064 *op++ = *p++;
1065 if (netsize > 16)
1066 *op++ = *p++;
1067 if (netsize > 24)
1068 *op++ = *p++;
1069 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1072 new->len = op - new->val;
1074 else if (is_addr6 && is6)
1076 unsigned char *op;
1077 new->val = op = opt_malloc(16 * addrs);
1078 new->flags |= DHOPT_ADDR6;
1079 while (addrs--)
1081 cp = comma;
1082 comma = split(cp);
1084 /* check for [1234::7] */
1085 if (*cp == '[')
1086 cp++;
1087 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1088 cp[strlen(cp)-1] = 0;
1090 if (inet_pton(AF_INET6, cp, op))
1092 op += IN6ADDRSZ;
1093 continue;
1096 ret_err(_("bad IPv6 address"));
1098 new->len = op - new->val;
1100 else if (is_string)
1102 /* text arg */
1103 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
1104 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1106 /* dns search, RFC 3397, or SIP, RFC 3361 */
1107 unsigned char *q, *r, *tail;
1108 unsigned char *p, *m = NULL, *newp;
1109 size_t newlen, len = 0;
1110 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
1112 arg = comma;
1113 comma = split(arg);
1115 while (arg && *arg)
1117 char *in, *dom = NULL;
1118 size_t domlen = 1;
1119 /* Allow "." as an empty domain */
1120 if (strcmp (arg, ".") != 0)
1122 if (!(dom = canonicalise_opt(arg)))
1123 ret_err(_("bad domain in dhcp-option"));
1125 domlen = strlen(dom) + 2;
1128 newp = opt_malloc(len + domlen + header_size);
1129 if (m)
1131 memcpy(newp, m, header_size + len);
1132 free(m);
1134 m = newp;
1135 p = m + header_size;
1136 q = p + len;
1138 /* add string on the end in RFC1035 format */
1139 for (in = dom; in && *in;)
1141 unsigned char *cp = q++;
1142 int j;
1143 for (j = 0; *in && (*in != '.'); in++, j++)
1144 *q++ = *in;
1145 *cp = j;
1146 if (*in)
1147 in++;
1149 *q++ = 0;
1150 free(dom);
1152 /* Now tail-compress using earlier names. */
1153 newlen = q - p;
1154 for (tail = p + len; *tail; tail += (*tail) + 1)
1155 for (r = p; r - p < (int)len; r += (*r) + 1)
1156 if (strcmp((char *)r, (char *)tail) == 0)
1158 PUTSHORT((r - p) | 0xc000, tail);
1159 newlen = tail - p;
1160 goto end;
1162 end:
1163 len = newlen;
1165 arg = comma;
1166 comma = split(arg);
1169 /* RFC 3361, enc byte is zero for names */
1170 if (new->opt == OPTION_SIP_SERVER)
1171 m[0] = 0;
1172 new->len = (int) len + header_size;
1173 new->val = m;
1175 #ifdef HAVE_DHCP6
1176 else if (comma && (opt_len & OT_CSTRING))
1178 /* length fields are two bytes so need 16 bits for each string */
1179 int i, commas = 1;
1180 unsigned char *p, *newp;
1182 for (i = 0; comma[i]; i++)
1183 if (comma[i] == ',')
1184 commas++;
1186 newp = opt_malloc(strlen(comma)+(2*commas));
1187 p = newp;
1188 arg = comma;
1189 comma = split(arg);
1191 while (arg && *arg)
1193 u16 len = strlen(arg);
1194 unhide_metas(arg);
1195 PUTSHORT(len, p);
1196 memcpy(p, arg, len);
1197 p += len;
1199 arg = comma;
1200 comma = split(arg);
1203 new->val = newp;
1204 new->len = p - newp;
1206 else if (comma && (opt_len & OT_RFC1035_NAME))
1208 unsigned char *p = NULL, *newp, *end;
1209 int len = 0;
1210 arg = comma;
1211 comma = split(arg);
1213 while (arg && *arg)
1215 char *dom = canonicalise_opt(arg);
1216 if (!dom)
1217 ret_err(_("bad domain in dhcp-option"));
1219 newp = opt_malloc(len + strlen(dom) + 2);
1221 if (p)
1223 memcpy(newp, p, len);
1224 free(p);
1227 p = newp;
1228 end = do_rfc1035_name(p + len, dom);
1229 *end++ = 0;
1230 len = end - p;
1231 free(dom);
1233 arg = comma;
1234 comma = split(arg);
1237 new->val = p;
1238 new->len = len;
1240 #endif
1241 else
1243 new->len = strlen(comma);
1244 /* keep terminating zero on string */
1245 new->val = (unsigned char *)opt_string_alloc(comma);
1246 new->flags |= DHOPT_STRING;
1251 if (!is6 &&
1252 ((new->len > 255) ||
1253 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1254 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
1255 ret_err(_("dhcp-option too long"));
1257 if (flags == DHOPT_MATCH)
1259 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1260 !new->netid ||
1261 new->netid->next)
1262 ret_err(_("illegal dhcp-match"));
1264 if (is6)
1266 new->next = daemon->dhcp_match6;
1267 daemon->dhcp_match6 = new;
1269 else
1271 new->next = daemon->dhcp_match;
1272 daemon->dhcp_match = new;
1275 else if (is6)
1277 new->next = daemon->dhcp_opts6;
1278 daemon->dhcp_opts6 = new;
1280 else
1282 new->next = daemon->dhcp_opts;
1283 daemon->dhcp_opts = new;
1286 return 1;
1289 #endif
1291 void set_option_bool(unsigned int opt)
1293 if (opt < 32)
1294 daemon->options |= 1u << opt;
1295 else
1296 daemon->options2 |= 1u << (opt - 32);
1299 void reset_option_bool(unsigned int opt)
1301 if (opt < 32)
1302 daemon->options &= ~(1u << opt);
1303 else
1304 daemon->options2 &= ~(1u << (opt - 32));
1307 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
1309 int i;
1310 char *comma;
1312 if (option == '?')
1313 ret_err(gen_err);
1315 for (i=0; usage[i].opt != 0; i++)
1316 if (usage[i].opt == option)
1318 int rept = usage[i].rept;
1320 if (command_line)
1322 /* command line */
1323 if (rept == ARG_USED_CL)
1324 ret_err(_("illegal repeated flag"));
1325 if (rept == ARG_ONE)
1326 usage[i].rept = ARG_USED_CL;
1328 else
1330 /* allow file to override command line */
1331 if (rept == ARG_USED_FILE)
1332 ret_err(_("illegal repeated keyword"));
1333 if (rept == ARG_USED_CL || rept == ARG_ONE)
1334 usage[i].rept = ARG_USED_FILE;
1337 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1339 set_option_bool(rept);
1340 return 1;
1343 break;
1346 switch (option)
1348 case 'C': /* --conf-file */
1350 char *file = opt_string_alloc(arg);
1351 if (file)
1353 one_file(file, 0);
1354 free(file);
1356 break;
1359 case '7': /* --conf-dir */
1361 DIR *dir_stream;
1362 struct dirent *ent;
1363 char *directory, *path;
1364 struct list {
1365 char *suffix;
1366 struct list *next;
1367 } *ignore_suffix = NULL, *li;
1369 comma = split(arg);
1370 if (!(directory = opt_string_alloc(arg)))
1371 break;
1373 for (arg = comma; arg; arg = comma)
1375 comma = split(arg);
1376 li = opt_malloc(sizeof(struct list));
1377 li->next = ignore_suffix;
1378 ignore_suffix = li;
1379 /* Have to copy: buffer is overwritten */
1380 li->suffix = opt_string_alloc(arg);
1383 if (!(dir_stream = opendir(directory)))
1384 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1386 while ((ent = readdir(dir_stream)))
1388 size_t len = strlen(ent->d_name);
1389 struct stat buf;
1391 /* ignore emacs backups and dotfiles */
1392 if (len == 0 ||
1393 ent->d_name[len - 1] == '~' ||
1394 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1395 ent->d_name[0] == '.')
1396 continue;
1398 for (li = ignore_suffix; li; li = li->next)
1400 /* check for proscribed suffices */
1401 size_t ls = strlen(li->suffix);
1402 if (len > ls &&
1403 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1404 break;
1406 if (li)
1407 continue;
1409 path = opt_malloc(strlen(directory) + len + 2);
1410 strcpy(path, directory);
1411 strcat(path, "/");
1412 strcat(path, ent->d_name);
1414 /* files must be readable */
1415 if (stat(path, &buf) == -1)
1416 die(_("cannot access %s: %s"), path, EC_FILE);
1418 /* only reg files allowed. */
1419 if (S_ISREG(buf.st_mode))
1420 one_file(path, 0);
1422 free(path);
1425 closedir(dir_stream);
1426 free(directory);
1427 for(; ignore_suffix; ignore_suffix = li)
1429 li = ignore_suffix->next;
1430 free(ignore_suffix->suffix);
1431 free(ignore_suffix);
1434 break;
1437 case '1': /* --enable-dbus */
1438 set_option_bool(OPT_DBUS);
1439 if (arg)
1440 daemon->dbus_name = opt_string_alloc(arg);
1441 else
1442 daemon->dbus_name = DNSMASQ_SERVICE;
1443 break;
1445 case '8': /* --log-facility */
1446 /* may be a filename */
1447 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1448 daemon->log_file = opt_string_alloc(arg);
1449 else
1451 #ifdef __ANDROID__
1452 ret_err(_("setting log facility is not possible under Android"));
1453 #else
1454 for (i = 0; facilitynames[i].c_name; i++)
1455 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1456 break;
1458 if (facilitynames[i].c_name)
1459 daemon->log_fac = facilitynames[i].c_val;
1460 else
1461 ret_err(_("bad log facility"));
1462 #endif
1464 break;
1466 case 'x': /* --pid-file */
1467 daemon->runfile = opt_string_alloc(arg);
1468 break;
1470 case 'r': /* --resolv-file */
1472 char *name = opt_string_alloc(arg);
1473 struct resolvc *new, *list = daemon->resolv_files;
1475 if (list && list->is_default)
1477 /* replace default resolv file - possibly with nothing */
1478 if (name)
1480 list->is_default = 0;
1481 list->name = name;
1483 else
1484 list = NULL;
1486 else if (name)
1488 new = opt_malloc(sizeof(struct resolvc));
1489 new->next = list;
1490 new->name = name;
1491 new->is_default = 0;
1492 new->mtime = 0;
1493 new->logged = 0;
1494 list = new;
1496 daemon->resolv_files = list;
1497 break;
1500 case 'm': /* --mx-host */
1502 int pref = 1;
1503 struct mx_srv_record *new;
1504 char *name, *target = NULL;
1506 if ((comma = split(arg)))
1508 char *prefstr;
1509 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1510 ret_err(_("bad MX preference"));
1513 if (!(name = canonicalise_opt(arg)) ||
1514 (comma && !(target = canonicalise_opt(comma))))
1515 ret_err(_("bad MX name"));
1517 new = opt_malloc(sizeof(struct mx_srv_record));
1518 new->next = daemon->mxnames;
1519 daemon->mxnames = new;
1520 new->issrv = 0;
1521 new->name = name;
1522 new->target = target; /* may be NULL */
1523 new->weight = pref;
1524 break;
1527 case 't': /* --mx-target */
1528 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1529 ret_err(_("bad MX target"));
1530 break;
1532 #ifdef HAVE_DHCP
1533 case 'l': /* --dhcp-leasefile */
1534 daemon->lease_file = opt_string_alloc(arg);
1535 break;
1537 /* Sorry about the gross pre-processor abuse */
1538 case '6': /* --dhcp-script */
1539 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1540 # if defined(NO_FORK)
1541 ret_err(_("cannot run scripts under uClinux"));
1542 # elif !defined(HAVE_SCRIPT)
1543 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
1544 # else
1545 if (option == LOPT_LUASCRIPT)
1546 # if !defined(HAVE_LUASCRIPT)
1547 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
1548 # else
1549 daemon->luascript = opt_string_alloc(arg);
1550 # endif
1551 else
1552 daemon->lease_change_command = opt_string_alloc(arg);
1553 # endif
1554 break;
1555 #endif /* HAVE_DHCP */
1557 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1558 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1559 case 'H': /* --addn-hosts */
1561 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1562 static int hosts_index = 1;
1563 new->fname = opt_string_alloc(arg);
1564 new->index = hosts_index++;
1565 new->flags = 0;
1566 if (option == 'H')
1568 new->next = daemon->addn_hosts;
1569 daemon->addn_hosts = new;
1571 else if (option == LOPT_DHCP_HOST)
1573 new->next = daemon->dhcp_hosts_file;
1574 daemon->dhcp_hosts_file = new;
1576 else if (option == LOPT_DHCP_OPTS)
1578 new->next = daemon->dhcp_opts_file;
1579 daemon->dhcp_opts_file = new;
1581 break;
1584 case LOPT_AUTHSERV: /* --auth-server */
1585 if (!(comma = split(arg)))
1586 ret_err(gen_err);
1588 daemon->authserver = opt_string_alloc(arg);
1589 arg = comma;
1590 do {
1591 struct iname *new = opt_malloc(sizeof(struct iname));
1592 comma = split(arg);
1593 new->name = NULL;
1594 unhide_metas(arg);
1595 if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
1596 new->addr.sa.sa_family = AF_INET;
1597 #ifdef HAVE_IPV6
1598 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1599 new->addr.sa.sa_family = AF_INET6;
1600 #endif
1601 else
1602 new->name = opt_string_alloc(arg);
1604 new->next = daemon->authinterface;
1605 daemon->authinterface = new;
1607 arg = comma;
1608 } while (arg);
1610 break;
1612 case LOPT_AUTHSFS: /* --auth-sec-servers */
1614 struct name_list *new;
1616 do {
1617 comma = split(arg);
1618 new = opt_malloc(sizeof(struct name_list));
1619 new->name = opt_string_alloc(arg);
1620 new->next = daemon->secondary_forward_server;
1621 daemon->secondary_forward_server = new;
1622 arg = comma;
1623 } while (arg);
1624 break;
1627 case LOPT_AUTHZONE: /* --auth-zone */
1629 struct auth_zone *new;
1631 comma = split(arg);
1633 new = opt_malloc(sizeof(struct auth_zone));
1634 new->domain = opt_string_alloc(arg);
1635 new->subnet = NULL;
1636 new->next = daemon->auth_zones;
1637 daemon->auth_zones = new;
1639 while ((arg = comma))
1641 int prefixlen = 0;
1642 char *prefix;
1643 struct subnet *subnet = opt_malloc(sizeof(struct subnet));
1645 subnet->next = new->subnet;
1646 new->subnet = subnet;
1648 comma = split(arg);
1649 prefix = split_chr(arg, '/');
1651 if (prefix && !atoi_check(prefix, &prefixlen))
1652 ret_err(gen_err);
1654 if (inet_pton(AF_INET, arg, &subnet->addr4))
1656 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
1657 subnet->is6 = 0;
1659 #ifdef HAVE_IPV6
1660 else if (inet_pton(AF_INET6, arg, &subnet->addr6))
1662 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
1663 subnet->is6 = 1;
1665 #endif
1666 else
1667 ret_err(gen_err);
1669 break;
1672 case LOPT_AUTHSOA: /* --auth-soa */
1673 comma = split(arg);
1674 atoi_check(arg, (int *)&daemon->soa_sn);
1675 if (comma)
1677 char *cp;
1678 arg = comma;
1679 comma = split(arg);
1680 daemon->hostmaster = opt_string_alloc(arg);
1681 for (cp = daemon->hostmaster; *cp; cp++)
1682 if (*cp == '@')
1683 *cp = '.';
1685 if (comma)
1687 arg = comma;
1688 comma = split(arg);
1689 atoi_check(arg, (int *)&daemon->soa_refresh);
1690 if (comma)
1692 arg = comma;
1693 comma = split(arg);
1694 atoi_check(arg, (int *)&daemon->soa_retry);
1695 if (comma)
1697 arg = comma;
1698 comma = split(arg);
1699 atoi_check(arg, (int *)&daemon->soa_expiry);
1705 break;
1707 case 's': /* --domain */
1708 case LOPT_SYNTH: /* --synth-domain */
1709 if (strcmp (arg, "#") == 0)
1710 set_option_bool(OPT_RESOLV_DOMAIN);
1711 else
1713 char *d;
1714 comma = split(arg);
1715 if (!(d = canonicalise_opt(arg)))
1716 ret_err(gen_err);
1717 else
1719 if (comma)
1721 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
1722 char *netpart;
1724 new->prefix = NULL;
1726 unhide_metas(comma);
1727 if ((netpart = split_chr(comma, '/')))
1729 int msize;
1731 arg = split(netpart);
1732 if (!atoi_check(netpart, &msize))
1733 ret_err(gen_err);
1734 else if (inet_pton(AF_INET, comma, &new->start))
1736 int mask = (1 << (32 - msize)) - 1;
1737 new->is6 = 0;
1738 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1739 new->end.s_addr = new->start.s_addr | htonl(mask);
1740 if (arg)
1742 if (option != 's')
1744 if (!(new->prefix = canonicalise_opt(arg)) ||
1745 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1746 ret_err(_("bad prefix"));
1748 else if (strcmp(arg, "local") != 0 ||
1749 (msize != 8 && msize != 16 && msize != 24))
1750 ret_err(gen_err);
1751 else
1753 /* generate the equivalent of
1754 local=/<domain>/
1755 local=/xxx.yyy.zzz.in-addr.arpa/ */
1756 struct server *serv = opt_malloc(sizeof(struct server));
1757 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1758 char *p;
1760 memset(serv, 0, sizeof(struct server));
1761 serv->domain = d;
1762 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1763 serv->next = daemon->servers;
1764 daemon->servers = serv;
1766 serv = opt_malloc(sizeof(struct server));
1767 memset(serv, 0, sizeof(struct server));
1768 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1770 if (msize == 24)
1771 p += sprintf(p, "%d.", a & 0xff);
1772 a = a >> 8;
1773 if (msize != 8)
1774 p += sprintf(p, "%d.", a & 0xff);
1775 a = a >> 8;
1776 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
1778 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1779 serv->next = daemon->servers;
1780 daemon->servers = serv;
1784 #ifdef HAVE_IPV6
1785 else if (inet_pton(AF_INET6, comma, &new->start6))
1787 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1788 u64 addrpart = addr6part(&new->start6);
1789 new->is6 = 1;
1791 /* prefix==64 overflows the mask calculation above */
1792 if (msize == 64)
1793 mask = (u64)-1LL;
1795 new->end6 = new->start6;
1796 setaddr6part(&new->start6, addrpart & ~mask);
1797 setaddr6part(&new->end6, addrpart | mask);
1799 if (msize < 64)
1800 ret_err(gen_err);
1801 else if (arg)
1803 if (option != 's')
1805 if (!(new->prefix = canonicalise_opt(arg)) ||
1806 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
1807 ret_err(_("bad prefix"));
1809 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
1810 ret_err(gen_err);
1811 else
1813 /* generate the equivalent of
1814 local=/<domain>/
1815 local=/xxx.yyy.zzz.ip6.arpa/ */
1816 struct server *serv = opt_malloc(sizeof(struct server));
1817 char *p;
1819 memset(serv, 0, sizeof(struct server));
1820 serv->domain = d;
1821 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1822 serv->next = daemon->servers;
1823 daemon->servers = serv;
1825 serv = opt_malloc(sizeof(struct server));
1826 memset(serv, 0, sizeof(struct server));
1827 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1829 for (i = msize-1; i >= 0; i -= 4)
1831 int dig = ((unsigned char *)&new->start6)[i>>3];
1832 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1834 p += sprintf(p, "ip6.arpa");
1836 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1837 serv->next = daemon->servers;
1838 daemon->servers = serv;
1842 #endif
1843 else
1844 ret_err(gen_err);
1846 else
1848 arg = split(comma);
1849 if (inet_pton(AF_INET, comma, &new->start))
1851 new->is6 = 0;
1852 if (!arg)
1853 new->end.s_addr = new->start.s_addr;
1854 else if (!inet_pton(AF_INET, arg, &new->end))
1855 ret_err(gen_err);
1857 #ifdef HAVE_IPV6
1858 else if (inet_pton(AF_INET6, comma, &new->start6))
1860 new->is6 = 1;
1861 if (!arg)
1862 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1863 else if (!inet_pton(AF_INET6, arg, &new->end6))
1864 ret_err(gen_err);
1866 #endif
1867 else
1868 ret_err(gen_err);
1871 new->domain = d;
1872 if (option == 's')
1874 new->next = daemon->cond_domain;
1875 daemon->cond_domain = new;
1877 else
1879 new->next = daemon->synth_domains;
1880 daemon->synth_domains = new;
1883 else if (option == 's')
1884 daemon->domain_suffix = d;
1885 else
1886 ret_err(gen_err);
1889 break;
1891 case 'u': /* --user */
1892 daemon->username = opt_string_alloc(arg);
1893 break;
1895 case 'g': /* --group */
1896 daemon->groupname = opt_string_alloc(arg);
1897 daemon->group_set = 1;
1898 break;
1900 #ifdef HAVE_DHCP
1901 case LOPT_SCRIPTUSR: /* --scriptuser */
1902 daemon->scriptuser = opt_string_alloc(arg);
1903 break;
1904 #endif
1906 case 'i': /* --interface */
1907 do {
1908 struct iname *new = opt_malloc(sizeof(struct iname));
1909 comma = split(arg);
1910 new->next = daemon->if_names;
1911 daemon->if_names = new;
1912 /* new->name may be NULL if someone does
1913 "interface=" to disable all interfaces except loop. */
1914 new->name = opt_string_alloc(arg);
1915 new->used = 0;
1916 arg = comma;
1917 } while (arg);
1918 break;
1920 case 'I': /* --except-interface */
1921 case '2': /* --no-dhcp-interface */
1922 do {
1923 struct iname *new = opt_malloc(sizeof(struct iname));
1924 comma = split(arg);
1925 new->name = opt_string_alloc(arg);
1926 if (option == 'I')
1928 new->next = daemon->if_except;
1929 daemon->if_except = new;
1931 else
1933 new->next = daemon->dhcp_except;
1934 daemon->dhcp_except = new;
1936 arg = comma;
1937 } while (arg);
1938 break;
1940 case 'B': /* --bogus-nxdomain */
1942 struct in_addr addr;
1943 unhide_metas(arg);
1944 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
1946 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1947 baddr->next = daemon->bogus_addr;
1948 daemon->bogus_addr = baddr;
1949 baddr->addr = addr;
1951 else
1952 ret_err(gen_err); /* error */
1953 break;
1956 case 'a': /* --listen-address */
1957 case LOPT_AUTHPEER: /* --auth-peer */
1958 do {
1959 struct iname *new = opt_malloc(sizeof(struct iname));
1960 comma = split(arg);
1961 unhide_metas(arg);
1962 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
1964 new->addr.sa.sa_family = AF_INET;
1965 new->addr.in.sin_port = 0;
1966 #ifdef HAVE_SOCKADDR_SA_LEN
1967 new->addr.in.sin_len = sizeof(new->addr.in);
1968 #endif
1970 #ifdef HAVE_IPV6
1971 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1973 new->addr.sa.sa_family = AF_INET6;
1974 new->addr.in6.sin6_flowinfo = 0;
1975 new->addr.in6.sin6_scope_id = 0;
1976 new->addr.in6.sin6_port = 0;
1977 #ifdef HAVE_SOCKADDR_SA_LEN
1978 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1979 #endif
1981 #endif
1982 else
1983 ret_err(gen_err);
1985 new->used = 0;
1986 if (option == 'a')
1988 new->next = daemon->if_addrs;
1989 daemon->if_addrs = new;
1991 else
1993 new->next = daemon->auth_peers;
1994 daemon->auth_peers = new;
1996 arg = comma;
1997 } while (arg);
1998 break;
2000 case 'S': /* --server */
2001 case LOPT_LOCAL: /* --local */
2002 case 'A': /* --address */
2003 case LOPT_NO_REBIND: /* --rebind-domain-ok */
2005 struct server *serv, *newlist = NULL;
2007 unhide_metas(arg);
2009 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
2011 int rebind = !(*arg == '/');
2012 char *end = NULL;
2013 if (!rebind)
2014 arg++;
2015 while (rebind || (end = split_chr(arg, '/')))
2017 char *domain = NULL;
2018 /* elide leading dots - they are implied in the search algorithm */
2019 while (*arg == '.') arg++;
2020 /* # matches everything and becomes a zero length domain string */
2021 if (strcmp(arg, "#") == 0)
2022 domain = "";
2023 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
2024 option = '?';
2025 serv = opt_malloc(sizeof(struct server));
2026 memset(serv, 0, sizeof(struct server));
2027 serv->next = newlist;
2028 newlist = serv;
2029 serv->domain = domain;
2030 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
2031 arg = end;
2032 if (rebind)
2033 break;
2035 if (!newlist)
2036 ret_err(gen_err);
2038 else
2040 newlist = opt_malloc(sizeof(struct server));
2041 memset(newlist, 0, sizeof(struct server));
2044 if (option == 'A')
2046 newlist->flags |= SERV_LITERAL_ADDRESS;
2047 if (!(newlist->flags & SERV_TYPE))
2048 ret_err(gen_err);
2050 else if (option == LOPT_NO_REBIND)
2051 newlist->flags |= SERV_NO_REBIND;
2053 if (!arg || !*arg)
2055 if (!(newlist->flags & SERV_NO_REBIND))
2056 newlist->flags |= SERV_NO_ADDR; /* no server */
2057 if (newlist->flags & SERV_LITERAL_ADDRESS)
2058 ret_err(gen_err);
2061 else if (strcmp(arg, "#") == 0)
2063 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
2064 if (newlist->flags & SERV_LITERAL_ADDRESS)
2065 ret_err(gen_err);
2067 else
2069 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2070 if (err)
2071 ret_err(err);
2074 serv = newlist;
2075 while (serv->next)
2077 serv->next->flags = serv->flags;
2078 serv->next->addr = serv->addr;
2079 serv->next->source_addr = serv->source_addr;
2080 strcpy(serv->next->interface, serv->interface);
2081 serv = serv->next;
2083 serv->next = daemon->servers;
2084 daemon->servers = newlist;
2085 break;
2088 case LOPT_IPSET: /* --ipset */
2089 #ifndef HAVE_IPSET
2090 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2091 break;
2092 #else
2094 struct ipsets ipsets_head;
2095 struct ipsets *ipsets = &ipsets_head;
2096 int size;
2097 char *end;
2098 char **sets, **sets_pos;
2099 memset(ipsets, 0, sizeof(struct ipsets));
2100 unhide_metas(arg);
2101 if (arg && *arg == '/')
2103 arg++;
2104 while ((end = split_chr(arg, '/')))
2106 char *domain = NULL;
2107 /* elide leading dots - they are implied in the search algorithm */
2108 while (*arg == '.')
2109 arg++;
2110 /* # matches everything and becomes a zero length domain string */
2111 if (strcmp(arg, "#") == 0 || !*arg)
2112 domain = "";
2113 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2114 option = '?';
2115 ipsets->next = opt_malloc(sizeof(struct ipsets));
2116 ipsets = ipsets->next;
2117 memset(ipsets, 0, sizeof(struct ipsets));
2118 ipsets->domain = domain;
2119 arg = end;
2122 else
2124 ipsets->next = opt_malloc(sizeof(struct ipsets));
2125 ipsets = ipsets->next;
2126 memset(ipsets, 0, sizeof(struct ipsets));
2127 ipsets->domain = "";
2129 if (!arg || !*arg)
2131 option = '?';
2132 break;
2134 size = 2;
2135 for (end = arg; *end; ++end)
2136 if (*end == ',')
2137 ++size;
2139 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2141 do {
2142 end = split(arg);
2143 *sets_pos++ = opt_string_alloc(arg);
2144 arg = end;
2145 } while (end);
2146 *sets_pos = 0;
2147 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2148 ipsets->next->sets = sets;
2149 ipsets->next = daemon->ipsets;
2150 daemon->ipsets = ipsets_head.next;
2152 break;
2154 #endif
2156 case 'c': /* --cache-size */
2158 int size;
2160 if (!atoi_check(arg, &size))
2161 ret_err(gen_err);
2162 else
2164 /* zero is OK, and means no caching. */
2166 if (size < 0)
2167 size = 0;
2168 else if (size > 10000)
2169 size = 10000;
2171 daemon->cachesize = size;
2173 break;
2176 case 'p': /* --port */
2177 if (!atoi_check16(arg, &daemon->port))
2178 ret_err(gen_err);
2179 break;
2181 case LOPT_MINPORT: /* --min-port */
2182 if (!atoi_check16(arg, &daemon->min_port))
2183 ret_err(gen_err);
2184 break;
2186 case '0': /* --dns-forward-max */
2187 if (!atoi_check(arg, &daemon->ftabsize))
2188 ret_err(gen_err);
2189 break;
2191 case LOPT_MAX_LOGS: /* --log-async */
2192 daemon->max_logs = LOG_MAX; /* default */
2193 if (arg && !atoi_check(arg, &daemon->max_logs))
2194 ret_err(gen_err);
2195 else if (daemon->max_logs > 100)
2196 daemon->max_logs = 100;
2197 break;
2199 case 'P': /* --edns-packet-max */
2201 int i;
2202 if (!atoi_check(arg, &i))
2203 ret_err(gen_err);
2204 daemon->edns_pktsz = (unsigned short)i;
2205 break;
2208 case 'Q': /* --query-port */
2209 if (!atoi_check16(arg, &daemon->query_port))
2210 ret_err(gen_err);
2211 /* if explicitly set to zero, use single OS ephemeral port
2212 and disable random ports */
2213 if (daemon->query_port == 0)
2214 daemon->osport = 1;
2215 break;
2217 case 'T': /* --local-ttl */
2218 case LOPT_NEGTTL: /* --neg-ttl */
2219 case LOPT_MAXTTL: /* --max-ttl */
2220 case LOPT_MAXCTTL: /* --max-cache-ttl */
2221 case LOPT_AUTHTTL: /* --auth-ttl */
2223 int ttl;
2224 if (!atoi_check(arg, &ttl))
2225 ret_err(gen_err);
2226 else if (option == LOPT_NEGTTL)
2227 daemon->neg_ttl = (unsigned long)ttl;
2228 else if (option == LOPT_MAXTTL)
2229 daemon->max_ttl = (unsigned long)ttl;
2230 else if (option == LOPT_MAXCTTL)
2231 daemon->max_cache_ttl = (unsigned long)ttl;
2232 else if (option == LOPT_AUTHTTL)
2233 daemon->auth_ttl = (unsigned long)ttl;
2234 else
2235 daemon->local_ttl = (unsigned long)ttl;
2236 break;
2239 #ifdef HAVE_DHCP
2240 case 'X': /* --dhcp-lease-max */
2241 if (!atoi_check(arg, &daemon->dhcp_max))
2242 ret_err(gen_err);
2243 break;
2244 #endif
2246 #ifdef HAVE_TFTP
2247 case LOPT_TFTP_MAX: /* --tftp-max */
2248 if (!atoi_check(arg, &daemon->tftp_max))
2249 ret_err(gen_err);
2250 break;
2252 case LOPT_PREFIX: /* --tftp-prefix */
2253 comma = split(arg);
2254 if (comma)
2256 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2257 new->interface = opt_string_alloc(comma);
2258 new->prefix = opt_string_alloc(arg);
2259 new->next = daemon->if_prefix;
2260 daemon->if_prefix = new;
2262 else
2263 daemon->tftp_prefix = opt_string_alloc(arg);
2264 break;
2266 case LOPT_TFTPPORTS: /* --tftp-port-range */
2267 if (!(comma = split(arg)) ||
2268 !atoi_check16(arg, &daemon->start_tftp_port) ||
2269 !atoi_check16(comma, &daemon->end_tftp_port))
2270 ret_err(_("bad port range"));
2272 if (daemon->start_tftp_port > daemon->end_tftp_port)
2274 int tmp = daemon->start_tftp_port;
2275 daemon->start_tftp_port = daemon->end_tftp_port;
2276 daemon->end_tftp_port = tmp;
2279 break;
2280 #endif
2282 case LOPT_BRIDGE: /* --bridge-interface */
2284 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2285 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2286 ret_err(_("bad bridge-interface"));
2288 strcpy(new->iface, arg);
2289 new->alias = NULL;
2290 new->next = daemon->bridges;
2291 daemon->bridges = new;
2293 do {
2294 arg = comma;
2295 comma = split(arg);
2296 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2298 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2299 b->next = new->alias;
2300 new->alias = b;
2301 strcpy(b->iface, arg);
2303 } while (comma);
2305 break;
2308 #ifdef HAVE_DHCP
2309 case 'F': /* --dhcp-range */
2311 int k, leasepos = 2;
2312 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2313 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2315 memset (new, 0, sizeof(*new));
2316 new->lease_time = DEFLEASE;
2318 if (!arg)
2320 option = '?';
2321 break;
2324 while(1)
2326 for (cp = arg; *cp; cp++)
2327 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2328 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2329 (*cp >='0' && *cp <= '9')))
2330 break;
2332 if (*cp != ',' && (comma = split(arg)))
2334 if (is_tag_prefix(arg))
2336 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2337 tt->net = opt_string_alloc(arg+4);
2338 tt->next = new->filter;
2339 new->filter = tt;
2341 else
2343 if (new->netid.net)
2344 ret_err(_("only one tag allowed"));
2345 else if (strstr(arg, "set:") == arg)
2346 new->netid.net = opt_string_alloc(arg+4);
2347 else
2348 new->netid.net = opt_string_alloc(arg);
2350 arg = comma;
2352 else
2354 a[0] = arg;
2355 break;
2359 for (k = 1; k < 8; k++)
2360 if (!(a[k] = split(a[k-1])))
2361 break;
2363 if (k < 2)
2364 ret_err(_("bad dhcp-range"));
2366 if (inet_pton(AF_INET, a[0], &new->start))
2368 new->next = daemon->dhcp;
2369 daemon->dhcp = new;
2370 new->end = new->start;
2371 if (strcmp(a[1], "static") == 0)
2372 new->flags |= CONTEXT_STATIC;
2373 else if (strcmp(a[1], "proxy") == 0)
2374 new->flags |= CONTEXT_PROXY;
2375 else if (!inet_pton(AF_INET, a[1], &new->end))
2376 ret_err(_("bad dhcp-range"));
2378 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2380 struct in_addr tmp = new->start;
2381 new->start = new->end;
2382 new->end = tmp;
2385 if (k >= 3 && strchr(a[2], '.') &&
2386 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
2388 new->flags |= CONTEXT_NETMASK;
2389 leasepos = 3;
2390 if (!is_same_net(new->start, new->end, new->netmask))
2391 ret_err(_("inconsistent DHCP range"));
2394 if (k >= 4 && strchr(a[3], '.') &&
2395 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
2397 new->flags |= CONTEXT_BRDCAST;
2398 leasepos = 4;
2401 #ifdef HAVE_DHCP6
2402 else if (inet_pton(AF_INET6, a[0], &new->start6))
2404 new->prefix = 64; /* default */
2405 new->end6 = new->start6;
2407 /* dhcp-range=:: enables DHCP stateless on any interface */
2408 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6))
2409 new->prefix = 0;
2411 for (leasepos = 1; leasepos < k; leasepos++)
2413 if (strcmp(a[leasepos], "static") == 0)
2414 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2415 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2416 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
2417 else if (strcmp(a[leasepos], "ra-names") == 0)
2418 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
2419 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2420 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
2421 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2422 new->flags |= CONTEXT_DHCP;
2423 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2425 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2426 new->flags |= CONTEXT_TEMPLATE;
2428 else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
2430 new->template_interface = opt_string_alloc(a[leasepos] + 19);
2431 new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
2433 else
2434 break;
2437 new->next = daemon->dhcp6;
2438 daemon->dhcp6 = new;
2440 /* bare integer < 128 is prefix value */
2441 if (leasepos < k)
2443 int pref;
2444 for (cp = a[leasepos]; *cp; cp++)
2445 if (!(*cp >= '0' && *cp <= '9'))
2446 break;
2447 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
2449 new->prefix = pref;
2450 leasepos++;
2451 if (new->prefix != 64)
2453 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2454 ret_err(_("prefix must be exactly 64 for RA subnets"));
2455 else if (new->template_interface)
2456 ret_err(_("prefix must be exactly 64 for subnet constructors"));
2458 if (new->prefix < 64)
2459 ret_err(_("prefix must be at least 64"));
2463 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2464 ret_err(_("inconsistent DHCPv6 range"));
2465 if (addr6part(&new->start6) > addr6part(&new->end6))
2467 struct in6_addr tmp = new->start6;
2468 new->start6 = new->end6;
2469 new->end6 = tmp;
2472 #endif
2473 else
2474 ret_err(_("bad dhcp-range"));
2476 if (leasepos < k)
2478 if (strcmp(a[leasepos], "infinite") == 0)
2479 new->lease_time = 0xffffffff;
2480 else if (strcmp(a[leasepos], "deprecated") == 0)
2481 new->flags |= CONTEXT_DEPRECATE;
2482 else
2484 int fac = 1;
2485 if (strlen(a[leasepos]) > 0)
2487 switch (a[leasepos][strlen(a[leasepos]) - 1])
2489 case 'w':
2490 case 'W':
2491 fac *= 7;
2492 /* fall through */
2493 case 'd':
2494 case 'D':
2495 fac *= 24;
2496 /* fall though */
2497 case 'h':
2498 case 'H':
2499 fac *= 60;
2500 /* fall through */
2501 case 'm':
2502 case 'M':
2503 fac *= 60;
2504 /* fall through */
2505 case 's':
2506 case 'S':
2507 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2510 for (cp = a[leasepos]; *cp; cp++)
2511 if (!(*cp >= '0' && *cp <= '9'))
2512 break;
2514 if (*cp || (leasepos+1 < k))
2515 ret_err(_("bad dhcp-range"));
2517 new->lease_time = atoi(a[leasepos]) * fac;
2518 /* Leases of a minute or less confuse
2519 some clients, notably Apple's */
2520 if (new->lease_time < 120)
2521 new->lease_time = 120;
2525 break;
2528 case LOPT_BANK:
2529 case 'G': /* --dhcp-host */
2531 int j, k = 0;
2532 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2533 struct dhcp_config *new;
2534 struct in_addr in;
2536 new = opt_malloc(sizeof(struct dhcp_config));
2538 new->next = daemon->dhcp_conf;
2539 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2540 new->hwaddr = NULL;
2541 new->netid = NULL;
2543 if ((a[0] = arg))
2544 for (k = 1; k < 7; k++)
2545 if (!(a[k] = split(a[k-1])))
2546 break;
2548 for (j = 0; j < k; j++)
2549 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2551 char *arg = a[j];
2553 if ((arg[0] == 'i' || arg[0] == 'I') &&
2554 (arg[1] == 'd' || arg[1] == 'D') &&
2555 arg[2] == ':')
2557 if (arg[3] == '*')
2558 new->flags |= CONFIG_NOCLID;
2559 else
2561 int len;
2562 arg += 3; /* dump id: */
2563 if (strchr(arg, ':'))
2564 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2565 else
2567 unhide_metas(arg);
2568 len = (int) strlen(arg);
2571 if (len == -1)
2573 ret_err(_("bad hex constant"));
2574 else if ((new->clid = opt_malloc(len)))
2576 new->flags |= CONFIG_CLID;
2577 new->clid_len = len;
2578 memcpy(new->clid, arg, len);
2582 /* dhcp-host has strange backwards-compat needs. */
2583 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2585 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2586 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2587 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2588 newlist->next = new->netid;
2589 new->netid = newlist;
2590 newlist->list = newtag;
2591 strcpy(newtag->net, arg+4);
2592 unhide_metas(newtag->net);
2594 else if (strstr(arg, "tag:") == arg)
2595 ret_err(_("cannot match tags in --dhcp-host"));
2596 #ifdef HAVE_DHCP6
2597 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2599 arg[strlen(arg)-1] = 0;
2600 arg++;
2602 if (!inet_pton(AF_INET6, arg, &new->addr6))
2603 ret_err(_("bad IPv6 address"));
2605 for (i= 0; i < 8; i++)
2606 if (new->addr6.s6_addr[i] != 0)
2607 break;
2609 /* set WILDCARD if network part all zeros */
2610 if (i == 8)
2611 new->flags |= CONFIG_WILDCARD;
2613 new->flags |= CONFIG_ADDR6;
2615 #endif
2616 else
2618 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2619 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2620 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2621 ret_err(_("bad hex constant"));
2622 else
2625 newhw->next = new->hwaddr;
2626 new->hwaddr = newhw;
2630 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
2632 struct dhcp_config *configs;
2634 new->addr = in;
2635 new->flags |= CONFIG_ADDR;
2637 /* If the same IP appears in more than one host config, then DISCOVER
2638 for one of the hosts will get the address, but REQUEST will be NAKed,
2639 since the address is reserved by the other one -> protocol loop. */
2640 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2641 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2643 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2644 return 0;
2647 else
2649 char *cp, *lastp = NULL, last = 0;
2650 int fac = 1;
2652 if (strlen(a[j]) > 1)
2654 lastp = a[j] + strlen(a[j]) - 1;
2655 last = *lastp;
2656 switch (last)
2658 case 'w':
2659 case 'W':
2660 fac *= 7;
2661 /* fall through */
2662 case 'd':
2663 case 'D':
2664 fac *= 24;
2665 /* fall through */
2666 case 'h':
2667 case 'H':
2668 fac *= 60;
2669 /* fall through */
2670 case 'm':
2671 case 'M':
2672 fac *= 60;
2673 /* fall through */
2674 case 's':
2675 case 'S':
2676 *lastp = 0;
2680 for (cp = a[j]; *cp; cp++)
2681 if (!isdigit((unsigned char)*cp) && *cp != ' ')
2682 break;
2684 if (*cp)
2686 if (lastp)
2687 *lastp = last;
2688 if (strcmp(a[j], "infinite") == 0)
2690 new->lease_time = 0xffffffff;
2691 new->flags |= CONFIG_TIME;
2693 else if (strcmp(a[j], "ignore") == 0)
2694 new->flags |= CONFIG_DISABLE;
2695 else
2697 if (!(new->hostname = canonicalise_opt(a[j])) ||
2698 !legal_hostname(new->hostname))
2699 ret_err(_("bad DHCP host name"));
2701 new->flags |= CONFIG_NAME;
2702 new->domain = strip_hostname(new->hostname);
2705 else
2707 new->lease_time = atoi(a[j]) * fac;
2708 /* Leases of a minute or less confuse
2709 some clients, notably Apple's */
2710 if (new->lease_time < 120)
2711 new->lease_time = 120;
2712 new->flags |= CONFIG_TIME;
2716 daemon->dhcp_conf = new;
2717 break;
2720 case LOPT_TAG_IF: /* --tag-if */
2722 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2724 new->tag = NULL;
2725 new->set = NULL;
2726 new->next = NULL;
2728 /* preserve order */
2729 if (!daemon->tag_if)
2730 daemon->tag_if = new;
2731 else
2733 struct tag_if *tmp;
2734 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2735 tmp->next = new;
2738 while (arg)
2740 size_t len;
2742 comma = split(arg);
2743 len = strlen(arg);
2745 if (len < 5)
2747 new->set = NULL;
2748 break;
2750 else
2752 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2753 newtag->net = opt_malloc(len - 3);
2754 strcpy(newtag->net, arg+4);
2755 unhide_metas(newtag->net);
2757 if (strstr(arg, "set:") == arg)
2759 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2760 newlist->next = new->set;
2761 new->set = newlist;
2762 newlist->list = newtag;
2764 else if (strstr(arg, "tag:") == arg)
2766 newtag->next = new->tag;
2767 new->tag = newtag;
2769 else
2771 new->set = NULL;
2772 free(newtag);
2773 break;
2777 arg = comma;
2780 if (!new->set)
2781 ret_err(_("bad tag-if"));
2783 break;
2787 case 'O': /* --dhcp-option */
2788 case LOPT_FORCE: /* --dhcp-option-force */
2789 case LOPT_OPTS:
2790 case LOPT_MATCH: /* --dhcp-match */
2791 return parse_dhcp_opt(errstr, arg,
2792 option == LOPT_FORCE ? DHOPT_FORCE :
2793 (option == LOPT_MATCH ? DHOPT_MATCH :
2794 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2796 case 'M': /* --dhcp-boot */
2798 struct dhcp_netid *id = NULL;
2799 while (is_tag_prefix(arg))
2801 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2802 newid->next = id;
2803 id = newid;
2804 comma = split(arg);
2805 newid->net = opt_string_alloc(arg+4);
2806 arg = comma;
2809 if (!arg)
2810 ret_err(gen_err);
2811 else
2813 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2814 struct in_addr dhcp_next_server;
2815 struct dhcp_boot *new;
2816 comma = split(arg);
2817 dhcp_file = opt_string_alloc(arg);
2818 dhcp_next_server.s_addr = 0;
2819 if (comma)
2821 arg = comma;
2822 comma = split(arg);
2823 dhcp_sname = opt_string_alloc(arg);
2824 if (comma)
2826 unhide_metas(comma);
2827 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2830 * The user may have specified the tftp hostname here.
2831 * save it so that it can be resolved/looked up during
2832 * actual dhcp_reply().
2835 tftp_sname = opt_string_alloc(comma);
2836 dhcp_next_server.s_addr = 0;
2841 new = opt_malloc(sizeof(struct dhcp_boot));
2842 new->file = dhcp_file;
2843 new->sname = dhcp_sname;
2844 new->tftp_sname = tftp_sname;
2845 new->next_server = dhcp_next_server;
2846 new->netid = id;
2847 new->next = daemon->boot_config;
2848 daemon->boot_config = new;
2851 break;
2854 case LOPT_PXE_PROMT: /* --pxe-prompt */
2856 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2857 int timeout;
2859 new->netid = NULL;
2860 new->opt = 10; /* PXE_MENU_PROMPT */
2862 while (is_tag_prefix(arg))
2864 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2865 comma = split(arg);
2866 nn->next = new->netid;
2867 new->netid = nn;
2868 nn->net = opt_string_alloc(arg+4);
2869 arg = comma;
2872 if (!arg)
2873 ret_err(gen_err);
2874 else
2876 comma = split(arg);
2877 unhide_metas(arg);
2878 new->len = strlen(arg) + 1;
2879 new->val = opt_malloc(new->len);
2880 memcpy(new->val + 1, arg, new->len - 1);
2882 new->u.vendor_class = (unsigned char *)"PXEClient";
2883 new->flags = DHOPT_VENDOR;
2885 if (comma && atoi_check(comma, &timeout))
2886 *(new->val) = timeout;
2887 else
2888 *(new->val) = 255;
2890 new->next = daemon->dhcp_opts;
2891 daemon->dhcp_opts = new;
2892 daemon->enable_pxe = 1;
2895 break;
2898 case LOPT_PXE_SERV: /* --pxe-service */
2900 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2901 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2902 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2903 static int boottype = 32768;
2905 new->netid = NULL;
2906 new->sname = NULL;
2907 new->server.s_addr = 0;
2909 while (is_tag_prefix(arg))
2911 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2912 comma = split(arg);
2913 nn->next = new->netid;
2914 new->netid = nn;
2915 nn->net = opt_string_alloc(arg+4);
2916 arg = comma;
2919 if (arg && (comma = split(arg)))
2921 for (i = 0; CSA[i]; i++)
2922 if (strcasecmp(CSA[i], arg) == 0)
2923 break;
2925 if (CSA[i] || atoi_check(arg, &i))
2927 arg = comma;
2928 comma = split(arg);
2930 new->CSA = i;
2931 new->menu = opt_string_alloc(arg);
2933 if (!comma)
2935 new->type = 0; /* local boot */
2936 new->basename = NULL;
2938 else
2940 arg = comma;
2941 comma = split(arg);
2942 if (atoi_check(arg, &i))
2944 new->type = i;
2945 new->basename = NULL;
2947 else
2949 new->type = boottype++;
2950 new->basename = opt_string_alloc(arg);
2953 if (comma)
2955 if (!inet_pton(AF_INET, comma, &new->server))
2957 new->server.s_addr = 0;
2958 new->sname = opt_string_alloc(comma);
2964 /* Order matters */
2965 new->next = NULL;
2966 if (!daemon->pxe_services)
2967 daemon->pxe_services = new;
2968 else
2970 struct pxe_service *s;
2971 for (s = daemon->pxe_services; s->next; s = s->next);
2972 s->next = new;
2975 daemon->enable_pxe = 1;
2976 break;
2981 ret_err(gen_err);
2984 case '4': /* --dhcp-mac */
2986 if (!(comma = split(arg)))
2987 ret_err(gen_err);
2988 else
2990 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2991 new->netid.net = opt_string_alloc(set_prefix(arg));
2992 unhide_metas(comma);
2993 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2994 if (new->hwaddr_len == -1)
2995 ret_err(gen_err);
2996 else
2998 new->next = daemon->dhcp_macs;
2999 daemon->dhcp_macs = new;
3003 break;
3005 #ifdef OPTION6_PREFIX_CLASS
3006 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3008 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3010 if (!(comma = split(arg)) ||
3011 !atoi_check16(comma, &new->class))
3012 ret_err(gen_err);
3014 new->tag.net = opt_string_alloc(set_prefix(arg));
3015 new->next = daemon->prefix_classes;
3016 daemon->prefix_classes = new;
3018 break;
3020 #endif
3023 case 'U': /* --dhcp-vendorclass */
3024 case 'j': /* --dhcp-userclass */
3025 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3026 case LOPT_REMOTE: /* --dhcp-remoteid */
3027 case LOPT_SUBSCR: /* --dhcp-subscrid */
3029 unsigned char *p;
3030 int dig = 0;
3031 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3033 if (!(comma = split(arg)))
3034 ret_err(gen_err);
3036 new->netid.net = opt_string_alloc(set_prefix(arg));
3037 /* check for hex string - must digits may include : must not have nothing else,
3038 only allowed for agent-options. */
3040 arg = comma;
3041 if ((comma = split(arg)))
3043 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3044 ret_err(gen_err);
3045 else
3046 new->enterprise = atoi(arg+11);
3048 else
3049 comma = arg;
3051 for (p = (unsigned char *)comma; *p; p++)
3052 if (isxdigit(*p))
3053 dig = 1;
3054 else if (*p != ':')
3055 break;
3056 unhide_metas(comma);
3057 if (option == 'U' || option == 'j' || *p || !dig)
3059 new->len = strlen(comma);
3060 new->data = opt_malloc(new->len);
3061 memcpy(new->data, comma, new->len);
3063 else
3065 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3066 new->data = opt_malloc(new->len);
3067 memcpy(new->data, comma, new->len);
3070 switch (option)
3072 case 'j':
3073 new->match_type = MATCH_USER;
3074 break;
3075 case 'U':
3076 new->match_type = MATCH_VENDOR;
3077 break;
3078 case LOPT_CIRCUIT:
3079 new->match_type = MATCH_CIRCUIT;
3080 break;
3081 case LOPT_REMOTE:
3082 new->match_type = MATCH_REMOTE;
3083 break;
3084 case LOPT_SUBSCR:
3085 new->match_type = MATCH_SUBSCRIBER;
3086 break;
3088 new->next = daemon->dhcp_vendors;
3089 daemon->dhcp_vendors = new;
3091 break;
3094 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3095 if (!arg)
3097 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3098 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3100 else
3102 comma = split(arg);
3103 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3104 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
3105 ret_err(_("invalid port number"));
3106 if (!comma)
3107 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3109 break;
3111 case 'J': /* --dhcp-ignore */
3112 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3113 case LOPT_BROADCAST: /* --dhcp-broadcast */
3114 case '3': /* --bootp-dynamic */
3115 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
3117 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
3118 struct dhcp_netid *list = NULL;
3119 if (option == 'J')
3121 new->next = daemon->dhcp_ignore;
3122 daemon->dhcp_ignore = new;
3124 else if (option == LOPT_BROADCAST)
3126 new->next = daemon->force_broadcast;
3127 daemon->force_broadcast = new;
3129 else if (option == '3')
3131 new->next = daemon->bootp_dynamic;
3132 daemon->bootp_dynamic = new;
3134 else if (option == LOPT_GEN_NAMES)
3136 new->next = daemon->dhcp_gen_names;
3137 daemon->dhcp_gen_names = new;
3139 else
3141 new->next = daemon->dhcp_ignore_names;
3142 daemon->dhcp_ignore_names = new;
3145 while (arg) {
3146 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3147 comma = split(arg);
3148 member->next = list;
3149 list = member;
3150 if (is_tag_prefix(arg))
3151 member->net = opt_string_alloc(arg+4);
3152 else
3153 member->net = opt_string_alloc(arg);
3154 arg = comma;
3157 new->list = list;
3158 break;
3161 case LOPT_PROXY: /* --dhcp-proxy */
3162 daemon->override = 1;
3163 while (arg) {
3164 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3165 comma = split(arg);
3166 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
3167 ret_err(_("bad dhcp-proxy address"));
3168 new->next = daemon->override_relays;
3169 daemon->override_relays = new;
3170 arg = comma;
3172 break;
3173 #endif
3175 #ifdef HAVE_DHCP6
3176 case LOPT_DUID: /* --dhcp-duid */
3177 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
3178 ret_err(_("bad DUID"));
3179 else
3181 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3182 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3183 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3185 break;
3186 #endif
3188 case 'V': /* --alias */
3190 char *dash, *a[3] = { NULL, NULL, NULL };
3191 int k = 0;
3192 struct doctor *new = opt_malloc(sizeof(struct doctor));
3193 new->next = daemon->doctors;
3194 daemon->doctors = new;
3195 new->mask.s_addr = 0xffffffff;
3196 new->end.s_addr = 0;
3198 if ((a[0] = arg))
3199 for (k = 1; k < 3; k++)
3201 if (!(a[k] = split(a[k-1])))
3202 break;
3203 unhide_metas(a[k]);
3206 dash = split_chr(a[0], '-');
3208 if ((k < 2) ||
3209 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3210 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
3211 option = '?';
3213 if (k == 3)
3214 inet_pton(AF_INET, a[2], &new->mask);
3216 if (dash &&
3217 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
3218 !is_same_net(new->in, new->end, new->mask) ||
3219 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3220 ret_err(_("invalid alias range"));
3222 break;
3225 case LOPT_INTNAME: /* --interface-name */
3227 struct interface_name *new, **up;
3228 char *domain = NULL;
3230 comma = split(arg);
3232 if (!comma || !(domain = canonicalise_opt(arg)))
3233 ret_err(_("bad interface name"));
3235 new = opt_malloc(sizeof(struct interface_name));
3236 new->next = NULL;
3237 new->addr4 = NULL;
3238 #ifdef HAVE_IPV6
3239 new->addr6 = NULL;
3240 #endif
3241 /* Add to the end of the list, so that first name
3242 of an interface is used for PTR lookups. */
3243 for (up = &daemon->int_names; *up; up = &((*up)->next));
3244 *up = new;
3245 new->name = domain;
3246 new->intr = opt_string_alloc(comma);
3247 break;
3250 case LOPT_CNAME: /* --cname */
3252 struct cname *new;
3253 char *alias;
3254 char *target;
3256 if (!(comma = split(arg)))
3257 ret_err(gen_err);
3259 alias = canonicalise_opt(arg);
3260 target = canonicalise_opt(comma);
3262 if (!alias || !target)
3263 ret_err(_("bad CNAME"));
3264 else
3266 for (new = daemon->cnames; new; new = new->next)
3267 if (hostname_isequal(new->alias, arg))
3268 ret_err(_("duplicate CNAME"));
3269 new = opt_malloc(sizeof(struct cname));
3270 new->next = daemon->cnames;
3271 daemon->cnames = new;
3272 new->alias = alias;
3273 new->target = target;
3276 break;
3279 case LOPT_PTR: /* --ptr-record */
3281 struct ptr_record *new;
3282 char *dom, *target = NULL;
3284 comma = split(arg);
3286 if (!(dom = canonicalise_opt(arg)) ||
3287 (comma && !(target = canonicalise_opt(comma))))
3288 ret_err(_("bad PTR record"));
3289 else
3291 new = opt_malloc(sizeof(struct ptr_record));
3292 new->next = daemon->ptr;
3293 daemon->ptr = new;
3294 new->name = dom;
3295 new->ptr = target;
3297 break;
3300 case LOPT_NAPTR: /* --naptr-record */
3302 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3303 int k = 0;
3304 struct naptr *new;
3305 int order, pref;
3306 char *name, *replace = NULL;
3308 if ((a[0] = arg))
3309 for (k = 1; k < 7; k++)
3310 if (!(a[k] = split(a[k-1])))
3311 break;
3314 if (k < 6 ||
3315 !(name = canonicalise_opt(a[0])) ||
3316 !atoi_check16(a[1], &order) ||
3317 !atoi_check16(a[2], &pref) ||
3318 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3319 ret_err(_("bad NAPTR record"));
3320 else
3322 new = opt_malloc(sizeof(struct naptr));
3323 new->next = daemon->naptr;
3324 daemon->naptr = new;
3325 new->name = name;
3326 new->flags = opt_string_alloc(a[3]);
3327 new->services = opt_string_alloc(a[4]);
3328 new->regexp = opt_string_alloc(a[5]);
3329 new->replace = replace;
3330 new->order = order;
3331 new->pref = pref;
3333 break;
3336 case LOPT_RR: /* dns-rr */
3338 struct txt_record *new;
3339 size_t len;
3340 char *data;
3341 int val;
3343 comma = split(arg);
3344 data = split(comma);
3346 new = opt_malloc(sizeof(struct txt_record));
3347 new->next = daemon->rr;
3348 daemon->rr = new;
3350 if (!atoi_check(comma, &val) ||
3351 !(new->name = canonicalise_opt(arg)) ||
3352 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
3353 ret_err(_("bad RR record"));
3355 new->class = val;
3356 new->len = 0;
3358 if (data)
3360 new->txt=opt_malloc(len);
3361 new->len = len;
3362 memcpy(new->txt, data, len);
3365 break;
3368 case 'Y': /* --txt-record */
3370 struct txt_record *new;
3371 unsigned char *p, *cnt;
3372 size_t len;
3374 comma = split(arg);
3376 new = opt_malloc(sizeof(struct txt_record));
3377 new->next = daemon->txt;
3378 daemon->txt = new;
3379 new->class = C_IN;
3381 if (!(new->name = canonicalise_opt(arg)))
3382 ret_err(_("bad TXT record"));
3384 len = comma ? strlen(comma) : 0;
3385 len += (len/255) + 1; /* room for extra counts */
3386 new->txt = p = opt_malloc(len);
3388 cnt = p++;
3389 *cnt = 0;
3391 while (comma && *comma)
3393 unsigned char c = (unsigned char)*comma++;
3395 if (c == ',' || *cnt == 255)
3397 if (c != ',')
3398 comma--;
3399 cnt = p++;
3400 *cnt = 0;
3402 else
3404 *p++ = unhide_meta(c);
3405 (*cnt)++;
3409 new->len = p - new->txt;
3411 break;
3414 case 'W': /* --srv-host */
3416 int port = 1, priority = 0, weight = 0;
3417 char *name, *target = NULL;
3418 struct mx_srv_record *new;
3420 comma = split(arg);
3422 if (!(name = canonicalise_opt(arg)))
3423 ret_err(_("bad SRV record"));
3425 if (comma)
3427 arg = comma;
3428 comma = split(arg);
3429 if (!(target = canonicalise_opt(arg)))
3430 ret_err(_("bad SRV target"));
3432 if (comma)
3434 arg = comma;
3435 comma = split(arg);
3436 if (!atoi_check16(arg, &port))
3437 ret_err(_("invalid port number"));
3439 if (comma)
3441 arg = comma;
3442 comma = split(arg);
3443 if (!atoi_check16(arg, &priority))
3444 ret_err(_("invalid priority"));
3446 if (comma)
3448 arg = comma;
3449 comma = split(arg);
3450 if (!atoi_check16(arg, &weight))
3451 ret_err(_("invalid weight"));
3457 new = opt_malloc(sizeof(struct mx_srv_record));
3458 new->next = daemon->mxnames;
3459 daemon->mxnames = new;
3460 new->issrv = 1;
3461 new->name = name;
3462 new->target = target;
3463 new->srvport = port;
3464 new->priority = priority;
3465 new->weight = weight;
3466 break;
3469 case LOPT_HOST_REC: /* --host-record */
3471 struct host_record *new = opt_malloc(sizeof(struct host_record));
3472 memset(new, 0, sizeof(struct host_record));
3474 if (!arg || !(comma = split(arg)))
3475 ret_err(_("Bad host-record"));
3477 while (arg)
3479 struct all_addr addr;
3480 if (inet_pton(AF_INET, arg, &addr))
3481 new->addr = addr.addr.addr4;
3482 #ifdef HAVE_IPV6
3483 else if (inet_pton(AF_INET6, arg, &addr))
3484 new->addr6 = addr.addr.addr6;
3485 #endif
3486 else
3488 int nomem;
3489 char *canon = canonicalise(arg, &nomem);
3490 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3491 if (!canon)
3492 ret_err(_("Bad name in host-record"));
3494 nl->name = canon;
3495 /* keep order, so that PTR record goes to first name */
3496 nl->next = NULL;
3497 if (!new->names)
3498 new->names = nl;
3499 else
3501 struct name_list *tmp;
3502 for (tmp = new->names; tmp->next; tmp = tmp->next);
3503 tmp->next = nl;
3507 arg = comma;
3508 comma = split(arg);
3511 /* Keep list order */
3512 if (!daemon->host_records_tail)
3513 daemon->host_records = new;
3514 else
3515 daemon->host_records_tail->next = new;
3516 new->next = NULL;
3517 daemon->host_records_tail = new;
3518 break;
3521 default:
3522 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3526 return 1;
3529 static void read_file(char *file, FILE *f, int hard_opt)
3531 volatile int lineno = 0;
3532 char *buff = daemon->namebuff;
3534 while (fgets(buff, MAXDNAME, f))
3536 int white, i, option = hard_opt;
3537 char *errmess, *p, *arg = NULL, *start;
3538 size_t len;
3540 /* Memory allocation failure longjmps here if mem_recover == 1 */
3541 if (option != 0)
3543 if (setjmp(mem_jmp))
3544 continue;
3545 mem_recover = 1;
3548 lineno++;
3549 errmess = NULL;
3551 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3552 metacharacters get hidden also strip comments */
3553 for (white = 1, p = buff; *p; p++)
3555 if (*p == '"')
3557 memmove(p, p+1, strlen(p+1)+1);
3559 for(; *p && *p != '"'; p++)
3561 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3563 if (p[1] == 't')
3564 p[1] = '\t';
3565 else if (p[1] == 'n')
3566 p[1] = '\n';
3567 else if (p[1] == 'b')
3568 p[1] = '\b';
3569 else if (p[1] == 'r')
3570 p[1] = '\r';
3571 else if (p[1] == 'e') /* escape */
3572 p[1] = '\033';
3573 memmove(p, p+1, strlen(p+1)+1);
3575 *p = hide_meta(*p);
3578 if (*p == 0)
3580 errmess = _("missing \"");
3581 goto oops;
3584 memmove(p, p+1, strlen(p+1)+1);
3587 if (isspace(*p))
3589 *p = ' ';
3590 white = 1;
3592 else
3594 if (white && *p == '#')
3596 *p = 0;
3597 break;
3599 white = 0;
3604 /* strip leading spaces */
3605 for (start = buff; *start && *start == ' '; start++);
3607 /* strip trailing spaces */
3608 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3610 if (len == 0)
3611 continue;
3612 else
3613 start[len] = 0;
3615 if (option != 0)
3616 arg = start;
3617 else if ((p=strchr(start, '=')))
3619 /* allow spaces around "=" */
3620 for (arg = p+1; *arg == ' '; arg++);
3621 for (; p >= start && (*p == ' ' || *p == '='); p--)
3622 *p = 0;
3624 else
3625 arg = NULL;
3627 if (option == 0)
3629 for (option = 0, i = 0; opts[i].name; i++)
3630 if (strcmp(opts[i].name, start) == 0)
3632 option = opts[i].val;
3633 break;
3636 if (!option)
3637 errmess = _("bad option");
3638 else if (opts[i].has_arg == 0 && arg)
3639 errmess = _("extraneous parameter");
3640 else if (opts[i].has_arg == 1 && !arg)
3641 errmess = _("missing parameter");
3644 oops:
3645 if (errmess)
3646 strcpy(daemon->namebuff, errmess);
3648 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
3650 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
3651 if (hard_opt != 0)
3652 my_syslog(LOG_ERR, "%s", daemon->namebuff);
3653 else
3654 die("%s", daemon->namebuff, EC_BADCONF);
3658 mem_recover = 0;
3659 fclose(f);
3662 static int one_file(char *file, int hard_opt)
3664 FILE *f;
3665 int nofile_ok = 0;
3666 static int read_stdin = 0;
3667 static struct fileread {
3668 dev_t dev;
3669 ino_t ino;
3670 struct fileread *next;
3671 } *filesread = NULL;
3673 if (hard_opt == '7')
3675 /* default conf-file reading */
3676 hard_opt = 0;
3677 nofile_ok = 1;
3680 if (hard_opt == 0 && strcmp(file, "-") == 0)
3682 if (read_stdin == 1)
3683 return 1;
3684 read_stdin = 1;
3685 file = "stdin";
3686 f = stdin;
3688 else
3690 /* ignore repeated files. */
3691 struct stat statbuf;
3693 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3695 struct fileread *r;
3697 for (r = filesread; r; r = r->next)
3698 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3699 return 1;
3701 r = safe_malloc(sizeof(struct fileread));
3702 r->next = filesread;
3703 filesread = r;
3704 r->dev = statbuf.st_dev;
3705 r->ino = statbuf.st_ino;
3708 if (!(f = fopen(file, "r")))
3710 if (errno == ENOENT && nofile_ok)
3711 return 1; /* No conffile, all done. */
3712 else
3714 char *str = _("cannot read %s: %s");
3715 if (hard_opt != 0)
3717 my_syslog(LOG_ERR, str, file, strerror(errno));
3718 return 0;
3720 else
3721 die(str, file, EC_FILE);
3726 read_file(file, f, hard_opt);
3727 return 1;
3730 /* expand any name which is a directory */
3731 struct hostsfile *expand_filelist(struct hostsfile *list)
3733 int i;
3734 struct hostsfile *ah;
3736 for (i = 0, ah = list; ah; ah = ah->next)
3738 if (i <= ah->index)
3739 i = ah->index + 1;
3741 if (ah->flags & AH_DIR)
3742 ah->flags |= AH_INACTIVE;
3743 else
3744 ah->flags &= ~AH_INACTIVE;
3747 for (ah = list; ah; ah = ah->next)
3748 if (!(ah->flags & AH_INACTIVE))
3750 struct stat buf;
3751 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3753 DIR *dir_stream;
3754 struct dirent *ent;
3756 /* don't read this as a file */
3757 ah->flags |= AH_INACTIVE;
3759 if (!(dir_stream = opendir(ah->fname)))
3760 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3761 ah->fname, strerror(errno));
3762 else
3764 while ((ent = readdir(dir_stream)))
3766 size_t lendir = strlen(ah->fname);
3767 size_t lenfile = strlen(ent->d_name);
3768 struct hostsfile *ah1;
3769 char *path;
3771 /* ignore emacs backups and dotfiles */
3772 if (lenfile == 0 ||
3773 ent->d_name[lenfile - 1] == '~' ||
3774 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3775 ent->d_name[0] == '.')
3776 continue;
3778 /* see if we have an existing record.
3779 dir is ah->fname
3780 file is ent->d_name
3781 path to match is ah1->fname */
3783 for (ah1 = list; ah1; ah1 = ah1->next)
3785 if (lendir < strlen(ah1->fname) &&
3786 strstr(ah1->fname, ah->fname) == ah1->fname &&
3787 ah1->fname[lendir] == '/' &&
3788 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3790 ah1->flags &= ~AH_INACTIVE;
3791 break;
3795 /* make new record */
3796 if (!ah1)
3798 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3799 continue;
3801 if (!(path = whine_malloc(lendir + lenfile + 2)))
3803 free(ah1);
3804 continue;
3807 strcpy(path, ah->fname);
3808 strcat(path, "/");
3809 strcat(path, ent->d_name);
3810 ah1->fname = path;
3811 ah1->index = i++;
3812 ah1->flags = AH_DIR;
3813 ah1->next = list;
3814 list = ah1;
3817 /* inactivate record if not regular file */
3818 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3819 ah1->flags |= AH_INACTIVE;
3822 closedir(dir_stream);
3827 return list;
3831 #ifdef HAVE_DHCP
3832 void reread_dhcp(void)
3834 struct hostsfile *hf;
3836 if (daemon->dhcp_hosts_file)
3838 struct dhcp_config *configs, *cp, **up;
3840 /* remove existing... */
3841 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3843 cp = configs->next;
3845 if (configs->flags & CONFIG_BANK)
3847 struct hwaddr_config *mac, *tmp;
3848 struct dhcp_netid_list *list, *tmplist;
3850 for (mac = configs->hwaddr; mac; mac = tmp)
3852 tmp = mac->next;
3853 free(mac);
3856 if (configs->flags & CONFIG_CLID)
3857 free(configs->clid);
3859 for (list = configs->netid; list; list = tmplist)
3861 free(list->list);
3862 tmplist = list->next;
3863 free(list);
3866 if (configs->flags & CONFIG_NAME)
3867 free(configs->hostname);
3869 *up = configs->next;
3870 free(configs);
3872 else
3873 up = &configs->next;
3876 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3877 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3878 if (!(hf->flags & AH_INACTIVE))
3880 if (one_file(hf->fname, LOPT_BANK))
3881 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3885 if (daemon->dhcp_opts_file)
3887 struct dhcp_opt *opts, *cp, **up;
3888 struct dhcp_netid *id, *next;
3890 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3892 cp = opts->next;
3894 if (opts->flags & DHOPT_BANK)
3896 if ((opts->flags & DHOPT_VENDOR))
3897 free(opts->u.vendor_class);
3898 free(opts->val);
3899 for (id = opts->netid; id; id = next)
3901 next = id->next;
3902 free(id->net);
3903 free(id);
3905 *up = opts->next;
3906 free(opts);
3908 else
3909 up = &opts->next;
3912 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3913 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3914 if (!(hf->flags & AH_INACTIVE))
3916 if (one_file(hf->fname, LOPT_OPTS))
3917 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3921 #endif
3923 void read_opts(int argc, char **argv, char *compile_opts)
3925 char *buff = opt_malloc(MAXDNAME);
3926 int option, conffile_opt = '7', testmode = 0;
3927 char *arg, *conffile = CONFFILE;
3929 opterr = 0;
3931 daemon = opt_malloc(sizeof(struct daemon));
3932 memset(daemon, 0, sizeof(struct daemon));
3933 daemon->namebuff = buff;
3935 /* Set defaults - everything else is zero or NULL */
3936 daemon->cachesize = CACHESIZ;
3937 daemon->ftabsize = FTABSIZ;
3938 daemon->port = NAMESERVER_PORT;
3939 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3940 daemon->dhcp_server_port = DHCP_SERVER_PORT;
3941 daemon->default_resolv.is_default = 1;
3942 daemon->default_resolv.name = RESOLVFILE;
3943 daemon->resolv_files = &daemon->default_resolv;
3944 daemon->username = CHUSER;
3945 daemon->runfile = RUNFILE;
3946 daemon->dhcp_max = MAXLEASES;
3947 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
3948 daemon->edns_pktsz = EDNS_PKTSZ;
3949 daemon->log_fac = -1;
3950 daemon->auth_ttl = AUTH_TTL;
3951 daemon->soa_refresh = SOA_REFRESH;
3952 daemon->soa_retry = SOA_RETRY;
3953 daemon->soa_expiry = SOA_EXPIRY;
3954 add_txt("version.bind", "dnsmasq-" VERSION );
3955 add_txt("authors.bind", "Simon Kelley");
3956 add_txt("copyright.bind", COPYRIGHT);
3958 while (1)
3960 #ifdef HAVE_GETOPT_LONG
3961 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
3962 #else
3963 option = getopt(argc, argv, OPTSTRING);
3964 #endif
3966 if (option == -1)
3968 for (; optind < argc; optind++)
3970 unsigned char *c = (unsigned char *)argv[optind];
3971 for (; *c != 0; c++)
3972 if (!isspace(*c))
3973 die(_("junk found in command line"), NULL, EC_BADCONF);
3975 break;
3978 /* Copy optarg so that argv doesn't get changed */
3979 if (optarg)
3981 strncpy(buff, optarg, MAXDNAME);
3982 buff[MAXDNAME-1] = 0;
3983 arg = buff;
3985 else
3986 arg = NULL;
3988 /* command-line only stuff */
3989 if (option == LOPT_TEST)
3990 testmode = 1;
3991 else if (option == 'w')
3993 #ifdef HAVE_DHCP
3994 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
3995 display_opts();
3996 #ifdef HAVE_DHCP6
3997 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
3998 display_opts6();
3999 #endif
4000 else
4001 #endif
4002 do_usage();
4004 exit(0);
4006 else if (option == 'v')
4008 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
4009 printf(_("Compile time options: %s\n\n"), compile_opts);
4010 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4011 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
4012 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
4013 exit(0);
4015 else if (option == 'C')
4017 conffile_opt = 0; /* file must exist */
4018 conffile = opt_string_alloc(arg);
4020 else
4022 #ifdef HAVE_GETOPT_LONG
4023 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
4024 #else
4025 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
4026 #endif
4027 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
4031 if (conffile)
4032 one_file(conffile, conffile_opt);
4034 /* port might not be known when the address is parsed - fill in here */
4035 if (daemon->servers)
4037 struct server *tmp;
4038 for (tmp = daemon->servers; tmp; tmp = tmp->next)
4039 if (!(tmp->flags & SERV_HAS_SOURCE))
4041 if (tmp->source_addr.sa.sa_family == AF_INET)
4042 tmp->source_addr.in.sin_port = htons(daemon->query_port);
4043 #ifdef HAVE_IPV6
4044 else if (tmp->source_addr.sa.sa_family == AF_INET6)
4045 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
4046 #endif
4050 if (daemon->if_addrs)
4052 struct iname *tmp;
4053 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
4054 if (tmp->addr.sa.sa_family == AF_INET)
4055 tmp->addr.in.sin_port = htons(daemon->port);
4056 #ifdef HAVE_IPV6
4057 else if (tmp->addr.sa.sa_family == AF_INET6)
4058 tmp->addr.in6.sin6_port = htons(daemon->port);
4059 #endif /* IPv6 */
4062 /* create default, if not specified */
4063 if (daemon->authserver && !daemon->hostmaster)
4065 strcpy(buff, "hostmaster.");
4066 strcat(buff, daemon->authserver);
4067 daemon->hostmaster = opt_string_alloc(buff);
4070 /* only one of these need be specified: the other defaults to the host-name */
4071 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
4073 struct mx_srv_record *mx;
4075 if (gethostname(buff, MAXDNAME) == -1)
4076 die(_("cannot get host-name: %s"), NULL, EC_MISC);
4078 for (mx = daemon->mxnames; mx; mx = mx->next)
4079 if (!mx->issrv && hostname_isequal(mx->name, buff))
4080 break;
4082 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
4084 mx = opt_malloc(sizeof(struct mx_srv_record));
4085 mx->next = daemon->mxnames;
4086 mx->issrv = 0;
4087 mx->target = NULL;
4088 mx->name = opt_string_alloc(buff);
4089 daemon->mxnames = mx;
4092 if (!daemon->mxtarget)
4093 daemon->mxtarget = opt_string_alloc(buff);
4095 for (mx = daemon->mxnames; mx; mx = mx->next)
4096 if (!mx->issrv && !mx->target)
4097 mx->target = daemon->mxtarget;
4100 if (!option_bool(OPT_NO_RESOLV) &&
4101 daemon->resolv_files &&
4102 daemon->resolv_files->next &&
4103 option_bool(OPT_NO_POLL))
4104 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
4106 if (option_bool(OPT_RESOLV_DOMAIN))
4108 char *line;
4109 FILE *f;
4111 if (option_bool(OPT_NO_RESOLV) ||
4112 !daemon->resolv_files ||
4113 (daemon->resolv_files)->next)
4114 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
4116 if (!(f = fopen((daemon->resolv_files)->name, "r")))
4117 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
4119 while ((line = fgets(buff, MAXDNAME, f)))
4121 char *token = strtok(line, " \t\n\r");
4123 if (!token || strcmp(token, "search") != 0)
4124 continue;
4126 if ((token = strtok(NULL, " \t\n\r")) &&
4127 (daemon->domain_suffix = canonicalise_opt(token)))
4128 break;
4131 fclose(f);
4133 if (!daemon->domain_suffix)
4134 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
4137 if (daemon->domain_suffix)
4139 /* add domain for any srv record without one. */
4140 struct mx_srv_record *srv;
4142 for (srv = daemon->mxnames; srv; srv = srv->next)
4143 if (srv->issrv &&
4144 strchr(srv->name, '.') &&
4145 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4147 strcpy(buff, srv->name);
4148 strcat(buff, ".");
4149 strcat(buff, daemon->domain_suffix);
4150 free(srv->name);
4151 srv->name = opt_string_alloc(buff);
4154 else if (option_bool(OPT_DHCP_FQDN))
4155 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
4157 if (testmode)
4159 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4160 exit(0);