Dnsmasq 2.67rc4+24Oct13 patches + wrap the wide prefix patch into
[tomato.git] / release / src / router / dnsmasq / src / option.c
blob3184509fd1c3ac756e5b8ca6b782fe6755fa9d8f
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 /* define this to get facilitynames */
18 #define SYSLOG_NAMES
19 #include "dnsmasq.h"
20 #include <setjmp.h>
22 static volatile int mem_recover = 0;
23 static jmp_buf mem_jmp;
24 static int one_file(char *file, int hard_opt);
26 /* Solaris headers don't have facility names. */
27 #ifdef HAVE_SOLARIS_NETWORK
28 static const struct {
29 char *c_name;
30 unsigned int c_val;
31 } facilitynames[] = {
32 { "kern", LOG_KERN },
33 { "user", LOG_USER },
34 { "mail", LOG_MAIL },
35 { "daemon", LOG_DAEMON },
36 { "auth", LOG_AUTH },
37 { "syslog", LOG_SYSLOG },
38 { "lpr", LOG_LPR },
39 { "news", LOG_NEWS },
40 { "uucp", LOG_UUCP },
41 { "audit", LOG_AUDIT },
42 { "cron", LOG_CRON },
43 { "local0", LOG_LOCAL0 },
44 { "local1", LOG_LOCAL1 },
45 { "local2", LOG_LOCAL2 },
46 { "local3", LOG_LOCAL3 },
47 { "local4", LOG_LOCAL4 },
48 { "local5", LOG_LOCAL5 },
49 { "local6", LOG_LOCAL6 },
50 { "local7", LOG_LOCAL7 },
51 { NULL, 0 }
53 #endif
55 #ifndef HAVE_GETOPT_LONG
56 struct myoption {
57 const char *name;
58 int has_arg;
59 int *flag;
60 int val;
62 #endif
64 #define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
66 /* options which don't have a one-char version */
67 #define LOPT_RELOAD 256
68 #define LOPT_NO_NAMES 257
69 #define LOPT_TFTP 258
70 #define LOPT_SECURE 259
71 #define LOPT_PREFIX 260
72 #define LOPT_PTR 261
73 #define LOPT_BRIDGE 262
74 #define LOPT_TFTP_MAX 263
75 #define LOPT_FORCE 264
76 #define LOPT_NOBLOCK 265
77 #define LOPT_LOG_OPTS 266
78 #define LOPT_MAX_LOGS 267
79 #define LOPT_CIRCUIT 268
80 #define LOPT_REMOTE 269
81 #define LOPT_SUBSCR 270
82 #define LOPT_INTNAME 271
83 #define LOPT_BANK 272
84 #define LOPT_DHCP_HOST 273
85 #define LOPT_APREF 274
86 #define LOPT_OVERRIDE 275
87 #define LOPT_TFTPPORTS 276
88 #define LOPT_REBIND 277
89 #define LOPT_NOLAST 278
90 #define LOPT_OPTS 279
91 #define LOPT_DHCP_OPTS 280
92 #define LOPT_MATCH 281
93 #define LOPT_BROADCAST 282
94 #define LOPT_NEGTTL 283
95 #define LOPT_ALTPORT 284
96 #define LOPT_SCRIPTUSR 285
97 #define LOPT_LOCAL 286
98 #define LOPT_NAPTR 287
99 #define LOPT_MINPORT 288
100 #define LOPT_DHCP_FQDN 289
101 #define LOPT_CNAME 290
102 #define LOPT_PXE_PROMT 291
103 #define LOPT_PXE_SERV 292
104 #define LOPT_TEST 293
105 #define LOPT_TAG_IF 294
106 #define LOPT_PROXY 295
107 #define LOPT_GEN_NAMES 296
108 #define LOPT_MAXTTL 297
109 #define LOPT_NO_REBIND 298
110 #define LOPT_LOC_REBND 299
111 #define LOPT_ADD_MAC 300
112 #define LOPT_DNSSEC 301
113 #define LOPT_INCR_ADDR 302
114 #define LOPT_CONNTRACK 303
115 #define LOPT_FQDN 304
116 #define LOPT_LUASCRIPT 305
117 #define LOPT_RA 306
118 #define LOPT_DUID 307
119 #define LOPT_HOST_REC 308
120 #define LOPT_TFTP_LC 309
121 #define LOPT_RR 310
122 #define LOPT_CLVERBIND 311
123 #define LOPT_MAXCTTL 312
124 #define LOPT_AUTHZONE 313
125 #define LOPT_AUTHSERV 314
126 #define LOPT_AUTHTTL 315
127 #define LOPT_AUTHSOA 316
128 #define LOPT_AUTHSFS 317
129 #define LOPT_AUTHPEER 318
130 #define LOPT_IPSET 319
131 #define LOPT_SYNTH 320
132 #ifdef OPTION6_PREFIX_CLASS
133 #define LOPT_PREF_CLSS 321
134 #endif
135 #define LOPT_RELAY 323
136 #define LOPT_RA_PARAM 324
137 #define LOPT_ADD_SBNET 325
138 #define LOPT_QUIET_DHCP 326
139 #define LOPT_QUIET_DHCP6 327
140 #define LOPT_QUIET_RA 328
143 #ifdef HAVE_GETOPT_LONG
144 static const struct option opts[] =
145 #else
146 static const struct myoption opts[] =
147 #endif
149 { "version", 0, 0, 'v' },
150 { "no-hosts", 0, 0, 'h' },
151 { "no-poll", 0, 0, 'n' },
152 { "help", 0, 0, 'w' },
153 { "no-daemon", 0, 0, 'd' },
154 { "log-queries", 0, 0, 'q' },
155 { "user", 2, 0, 'u' },
156 { "group", 2, 0, 'g' },
157 { "resolv-file", 2, 0, 'r' },
158 { "mx-host", 1, 0, 'm' },
159 { "mx-target", 1, 0, 't' },
160 { "cache-size", 2, 0, 'c' },
161 { "port", 1, 0, 'p' },
162 { "dhcp-leasefile", 2, 0, 'l' },
163 { "dhcp-lease", 1, 0, 'l' },
164 { "dhcp-host", 1, 0, 'G' },
165 { "dhcp-range", 1, 0, 'F' },
166 { "dhcp-option", 1, 0, 'O' },
167 { "dhcp-boot", 1, 0, 'M' },
168 { "domain", 1, 0, 's' },
169 { "domain-suffix", 1, 0, 's' },
170 { "interface", 1, 0, 'i' },
171 { "listen-address", 1, 0, 'a' },
172 { "bogus-priv", 0, 0, 'b' },
173 { "bogus-nxdomain", 1, 0, 'B' },
174 { "selfmx", 0, 0, 'e' },
175 { "filterwin2k", 0, 0, 'f' },
176 { "pid-file", 2, 0, 'x' },
177 { "strict-order", 0, 0, 'o' },
178 { "server", 1, 0, 'S' },
179 { "local", 1, 0, LOPT_LOCAL },
180 { "address", 1, 0, 'A' },
181 { "conf-file", 2, 0, 'C' },
182 { "no-resolv", 0, 0, 'R' },
183 { "expand-hosts", 0, 0, 'E' },
184 { "localmx", 0, 0, 'L' },
185 { "local-ttl", 1, 0, 'T' },
186 { "no-negcache", 0, 0, 'N' },
187 { "addn-hosts", 1, 0, 'H' },
188 { "query-port", 1, 0, 'Q' },
189 { "except-interface", 1, 0, 'I' },
190 { "no-dhcp-interface", 1, 0, '2' },
191 { "domain-needed", 0, 0, 'D' },
192 { "dhcp-lease-max", 1, 0, 'X' },
193 { "bind-interfaces", 0, 0, 'z' },
194 { "read-ethers", 0, 0, 'Z' },
195 { "alias", 1, 0, 'V' },
196 { "dhcp-vendorclass", 1, 0, 'U' },
197 { "dhcp-userclass", 1, 0, 'j' },
198 { "dhcp-ignore", 1, 0, 'J' },
199 { "edns-packet-max", 1, 0, 'P' },
200 { "keep-in-foreground", 0, 0, 'k' },
201 { "dhcp-authoritative", 0, 0, 'K' },
202 { "srv-host", 1, 0, 'W' },
203 { "localise-queries", 0, 0, 'y' },
204 { "txt-record", 1, 0, 'Y' },
205 { "dns-rr", 1, 0, LOPT_RR },
206 { "enable-dbus", 2, 0, '1' },
207 { "bootp-dynamic", 2, 0, '3' },
208 { "dhcp-mac", 1, 0, '4' },
209 { "no-ping", 0, 0, '5' },
210 { "dhcp-script", 1, 0, '6' },
211 { "conf-dir", 1, 0, '7' },
212 { "log-facility", 1, 0 ,'8' },
213 { "leasefile-ro", 0, 0, '9' },
214 { "dns-forward-max", 1, 0, '0' },
215 { "clear-on-reload", 0, 0, LOPT_RELOAD },
216 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
217 { "enable-tftp", 2, 0, LOPT_TFTP },
218 { "tftp-secure", 0, 0, LOPT_SECURE },
219 { "tftp-unique-root", 0, 0, LOPT_APREF },
220 { "tftp-root", 1, 0, LOPT_PREFIX },
221 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
222 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
223 { "ptr-record", 1, 0, LOPT_PTR },
224 { "naptr-record", 1, 0, LOPT_NAPTR },
225 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
226 { "dhcp-option-force", 1, 0, LOPT_FORCE },
227 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
228 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
229 { "log-async", 2, 0, LOPT_MAX_LOGS },
230 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
231 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
232 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
233 { "interface-name", 1, 0, LOPT_INTNAME },
234 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
235 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
236 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
237 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
238 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
239 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
240 { "all-servers", 0, 0, LOPT_NOLAST },
241 { "dhcp-match", 1, 0, LOPT_MATCH },
242 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
243 { "neg-ttl", 1, 0, LOPT_NEGTTL },
244 { "max-ttl", 1, 0, LOPT_MAXTTL },
245 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
246 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
247 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
248 { "min-port", 1, 0, LOPT_MINPORT },
249 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
250 { "cname", 1, 0, LOPT_CNAME },
251 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
252 { "pxe-service", 1, 0, LOPT_PXE_SERV },
253 { "test", 0, 0, LOPT_TEST },
254 { "tag-if", 1, 0, LOPT_TAG_IF },
255 { "dhcp-proxy", 2, 0, LOPT_PROXY },
256 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
257 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
258 { "add-mac", 0, 0, LOPT_ADD_MAC },
259 { "add-subnet", 2, 0, LOPT_ADD_SBNET },
260 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
261 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
262 { "conntrack", 0, 0, LOPT_CONNTRACK },
263 { "dhcp-client-update", 0, 0, LOPT_FQDN },
264 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
265 { "enable-ra", 0, 0, LOPT_RA },
266 { "dhcp-duid", 1, 0, LOPT_DUID },
267 { "host-record", 1, 0, LOPT_HOST_REC },
268 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
269 { "auth-zone", 1, 0, LOPT_AUTHZONE },
270 { "auth-server", 1, 0, LOPT_AUTHSERV },
271 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
272 { "auth-soa", 1, 0, LOPT_AUTHSOA },
273 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
274 { "auth-peer", 1, 0, LOPT_AUTHPEER },
275 { "ipset", 1, 0, LOPT_IPSET },
276 { "synth-domain", 1, 0, LOPT_SYNTH },
277 #ifdef OPTION6_PREFIX_CLASS
278 { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
279 #endif
280 { "dhcp-relay", 1, 0, LOPT_RELAY },
281 { "ra-param", 1, 0, LOPT_RA_PARAM },
282 { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
283 { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
284 { "quiet-ra", 0, 0, LOPT_QUIET_RA },
285 { NULL, 0, 0, 0 }
289 #define ARG_DUP OPT_LAST
290 #define ARG_ONE OPT_LAST + 1
291 #define ARG_USED_CL OPT_LAST + 2
292 #define ARG_USED_FILE OPT_LAST + 3
294 static struct {
295 int opt;
296 unsigned int rept;
297 char * const flagdesc;
298 char * const desc;
299 char * const arg;
300 } usage[] = {
301 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
302 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
303 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
304 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
305 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
306 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
307 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
308 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
309 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
310 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
311 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
312 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
313 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
314 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
315 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
316 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
317 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
318 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
319 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
320 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
321 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
322 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
323 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
324 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
325 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
326 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
327 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
328 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
329 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
330 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
331 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
332 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
333 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
334 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
335 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
336 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
337 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
338 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
339 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
340 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
341 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
342 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
343 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
344 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
345 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
346 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
347 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
348 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
349 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
350 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
351 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
352 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
353 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
354 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
355 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
356 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
357 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
358 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
359 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
360 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
361 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
362 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
363 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
364 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
365 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
366 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
367 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
368 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
369 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
370 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
371 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
372 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
373 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
374 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
375 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
376 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
377 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
378 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
379 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
380 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
381 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
382 { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
383 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
384 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
385 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
386 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
387 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
388 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
389 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
390 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
391 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
392 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
393 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
394 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
395 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
396 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
397 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
398 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
399 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
400 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
401 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
402 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
403 { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
404 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
405 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
406 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
407 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
408 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
409 { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL },
410 { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
411 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
412 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
413 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
414 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
415 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
416 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
417 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
418 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
419 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
420 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
421 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
422 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
423 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
424 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
425 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
426 { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
427 #ifdef OPTION6_PREFIX_CLASS
428 { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
429 #endif
430 { LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
431 { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
432 { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
433 { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
434 { 0, 0, NULL, NULL, NULL }
437 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
438 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
439 following sequence so that they map to themselves: it is therefore possible to call
440 unhide_metas repeatedly on string without breaking things.
441 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
442 couple of other places.
443 Note that space is included here so that
444 --dhcp-option=3, string
445 has five characters, whilst
446 --dhcp-option=3," string"
447 has six.
450 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
452 static char hide_meta(char c)
454 unsigned int i;
456 for (i = 0; i < (sizeof(meta) - 1); i++)
457 if (c == meta[i])
458 return (char)i;
460 return c;
463 static char unhide_meta(char cr)
465 unsigned int c = cr;
467 if (c < (sizeof(meta) - 1))
468 cr = meta[c];
470 return cr;
473 static void unhide_metas(char *cp)
475 if (cp)
476 for(; *cp; cp++)
477 *cp = unhide_meta(*cp);
480 static void *opt_malloc(size_t size)
482 void *ret;
484 if (mem_recover)
486 ret = whine_malloc(size);
487 if (!ret)
488 longjmp(mem_jmp, 1);
490 else
491 ret = safe_malloc(size);
493 return ret;
496 static char *opt_string_alloc(char *cp)
498 char *ret = NULL;
500 if (cp && strlen(cp) != 0)
502 ret = opt_malloc(strlen(cp)+1);
503 strcpy(ret, cp);
505 /* restore hidden metachars */
506 unhide_metas(ret);
509 return ret;
513 /* find next comma, split string with zero and eliminate spaces.
514 return start of string following comma */
516 static char *split_chr(char *s, char c)
518 char *comma, *p;
520 if (!s || !(comma = strchr(s, c)))
521 return NULL;
523 p = comma;
524 *comma = ' ';
526 for (; *comma == ' '; comma++);
528 for (; (p >= s) && *p == ' '; p--)
529 *p = 0;
531 return comma;
534 static char *split(char *s)
536 return split_chr(s, ',');
539 static char *canonicalise_opt(char *s)
541 char *ret;
542 int nomem;
544 if (!s)
545 return 0;
547 unhide_metas(s);
548 if (!(ret = canonicalise(s, &nomem)) && nomem)
550 if (mem_recover)
551 longjmp(mem_jmp, 1);
552 else
553 die(_("could not get memory"), NULL, EC_NOMEM);
556 return ret;
559 static int atoi_check(char *a, int *res)
561 char *p;
563 if (!a)
564 return 0;
566 unhide_metas(a);
568 for (p = a; *p; p++)
569 if (*p < '0' || *p > '9')
570 return 0;
572 *res = atoi(a);
573 return 1;
576 static int atoi_check16(char *a, int *res)
578 if (!(atoi_check(a, res)) ||
579 *res < 0 ||
580 *res > 0xffff)
581 return 0;
583 return 1;
586 static void add_txt(char *name, char *txt)
588 size_t len = strlen(txt);
589 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
591 r->name = opt_string_alloc(name);
592 r->next = daemon->txt;
593 daemon->txt = r;
594 r->class = C_CHAOS;
595 r->txt = opt_malloc(len+1);
596 r->len = len+1;
597 *(r->txt) = len;
598 memcpy((r->txt)+1, txt, len);
601 static void do_usage(void)
603 char buff[100];
604 int i, j;
606 struct {
607 char handle;
608 int val;
609 } tab[] = {
610 { '$', CACHESIZ },
611 { '*', EDNS_PKTSZ },
612 { '&', MAXLEASES },
613 { '!', FTABSIZ },
614 { '#', TFTP_MAX_CONNECTIONS },
615 { '\0', 0 }
618 printf(_("Usage: dnsmasq [options]\n\n"));
619 #ifndef HAVE_GETOPT_LONG
620 printf(_("Use short options only on the command line.\n"));
621 #endif
622 printf(_("Valid options are:\n"));
624 for (i = 0; usage[i].opt != 0; i++)
626 char *desc = usage[i].flagdesc;
627 char *eq = "=";
629 if (!desc || *desc == '[')
630 eq = "";
632 if (!desc)
633 desc = "";
635 for ( j = 0; opts[j].name; j++)
636 if (opts[j].val == usage[i].opt)
637 break;
638 if (usage[i].opt < 256)
639 sprintf(buff, "-%c, ", usage[i].opt);
640 else
641 sprintf(buff, " ");
643 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
644 printf("%-40.40s", buff);
646 if (usage[i].arg)
648 strcpy(buff, usage[i].arg);
649 for (j = 0; tab[j].handle; j++)
650 if (tab[j].handle == *(usage[i].arg))
651 sprintf(buff, "%d", tab[j].val);
653 printf(_(usage[i].desc), buff);
654 printf("\n");
658 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
660 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
662 int source_port = 0, serv_port = NAMESERVER_PORT;
663 char *portno, *source;
664 #ifdef HAVE_IPV6
665 int scope_index = 0;
666 char *scope_id;
667 #endif
669 if ((source = split_chr(arg, '@')) && /* is there a source. */
670 (portno = split_chr(source, '#')) &&
671 !atoi_check16(portno, &source_port))
672 return _("bad port");
674 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
675 !atoi_check16(portno, &serv_port))
676 return _("bad port");
678 #ifdef HAVE_IPV6
679 scope_id = split_chr(arg, '%');
680 #endif
682 if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
684 addr->in.sin_port = htons(serv_port);
685 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
686 #ifdef HAVE_SOCKADDR_SA_LEN
687 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
688 #endif
689 source_addr->in.sin_addr.s_addr = INADDR_ANY;
690 source_addr->in.sin_port = htons(daemon->query_port);
692 if (source)
694 if (flags)
695 *flags |= SERV_HAS_SOURCE;
696 source_addr->in.sin_port = htons(source_port);
697 if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
699 #if defined(SO_BINDTODEVICE)
700 source_addr->in.sin_addr.s_addr = INADDR_ANY;
701 strncpy(interface, source, IF_NAMESIZE - 1);
702 #else
703 return _("interface binding not supported");
704 #endif
708 #ifdef HAVE_IPV6
709 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
711 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
712 return _("bad interface name");
714 addr->in6.sin6_port = htons(serv_port);
715 addr->in6.sin6_scope_id = scope_index;
716 source_addr->in6.sin6_addr = in6addr_any;
717 source_addr->in6.sin6_port = htons(daemon->query_port);
718 source_addr->in6.sin6_scope_id = 0;
719 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
720 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
721 #ifdef HAVE_SOCKADDR_SA_LEN
722 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
723 #endif
724 if (source)
726 if (flags)
727 *flags |= SERV_HAS_SOURCE;
728 source_addr->in6.sin6_port = htons(source_port);
729 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
731 #if defined(SO_BINDTODEVICE)
732 source_addr->in6.sin6_addr = in6addr_any;
733 strncpy(interface, source, IF_NAMESIZE - 1);
734 #else
735 return _("interface binding not supported");
736 #endif
740 #endif
741 else
742 return _("bad address");
744 return NULL;
747 #ifdef HAVE_DHCP
749 static int is_tag_prefix(char *arg)
751 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
752 return 1;
754 return 0;
757 static char *set_prefix(char *arg)
759 if (strstr(arg, "set:") == arg)
760 return arg+4;
762 return arg;
765 /* This is too insanely large to keep in-line in the switch */
766 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
768 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
769 char lenchar = 0, *cp;
770 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
771 char *comma = NULL;
772 struct dhcp_netid *np = NULL;
773 u16 opt_len = 0;
774 int is6 = 0;
775 int option_ok = 0;
777 new->len = 0;
778 new->flags = flags;
779 new->netid = NULL;
780 new->val = NULL;
781 new->opt = 0;
783 while (arg)
785 comma = split(arg);
787 for (cp = arg; *cp; cp++)
788 if (*cp < '0' || *cp > '9')
789 break;
791 if (!*cp)
793 new->opt = atoi(arg);
794 opt_len = 0;
795 option_ok = 1;
796 break;
799 if (strstr(arg, "option:") == arg)
801 if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
803 opt_len = lookup_dhcp_len(AF_INET, new->opt);
804 /* option:<optname> must follow tag and vendor string. */
805 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
806 option_ok = 1;
808 break;
810 #ifdef HAVE_DHCP6
811 else if (strstr(arg, "option6:") == arg)
813 for (cp = arg+8; *cp; cp++)
814 if (*cp < '0' || *cp > '9')
815 break;
817 if (!*cp)
819 new->opt = atoi(arg+8);
820 opt_len = 0;
821 option_ok = 1;
823 else
825 if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
827 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
828 if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
829 option_ok = 1;
832 /* option6:<opt>|<optname> must follow tag and vendor string. */
833 is6 = 1;
834 break;
836 #endif
837 else if (strstr(arg, "vendor:") == arg)
839 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
840 new->flags |= DHOPT_VENDOR;
842 else if (strstr(arg, "encap:") == arg)
844 new->u.encap = atoi(arg+6);
845 new->flags |= DHOPT_ENCAPSULATE;
847 else if (strstr(arg, "vi-encap:") == arg)
849 new->u.encap = atoi(arg+9);
850 new->flags |= DHOPT_RFC3925;
851 if (flags == DHOPT_MATCH)
853 option_ok = 1;
854 break;
857 else
859 new->netid = opt_malloc(sizeof (struct dhcp_netid));
860 /* allow optional "net:" or "tag:" for consistency */
861 if (is_tag_prefix(arg))
862 new->netid->net = opt_string_alloc(arg+4);
863 else
864 new->netid->net = opt_string_alloc(set_prefix(arg));
865 new->netid->next = np;
866 np = new->netid;
869 arg = comma;
872 #ifdef HAVE_DHCP6
873 if (is6)
875 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
876 ret_err(_("unsupported encapsulation for IPv6 option"));
878 if (opt_len == 0 &&
879 !(new->flags & DHOPT_RFC3925))
880 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
882 else
883 #endif
884 if (opt_len == 0 &&
885 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
886 opt_len = lookup_dhcp_len(AF_INET, new->opt);
888 /* option may be missing with rfc3925 match */
889 if (!option_ok)
890 ret_err(_("bad dhcp-option"));
892 if (comma)
894 /* characterise the value */
895 char c;
896 int found_dig = 0;
897 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
898 addrs = digs = 1;
899 dots = 0;
900 for (cp = comma; (c = *cp); cp++)
901 if (c == ',')
903 addrs++;
904 is_dec = is_hex = 0;
906 else if (c == ':')
908 digs++;
909 is_dec = is_addr = 0;
911 else if (c == '/')
913 is_addr6 = is_dec = is_hex = 0;
914 if (cp == comma) /* leading / means a pathname */
915 is_addr = 0;
917 else if (c == '.')
919 is_addr6 = is_dec = is_hex = 0;
920 dots++;
922 else if (c == '-')
923 is_hex = is_addr = is_addr6 = 0;
924 else if (c == ' ')
925 is_dec = is_hex = 0;
926 else if (!(c >='0' && c <= '9'))
928 is_addr = 0;
929 if (cp[1] == 0 && is_dec &&
930 (c == 'b' || c == 's' || c == 'i'))
932 lenchar = c;
933 *cp = 0;
935 else
936 is_dec = 0;
937 if (!((c >='A' && c <= 'F') ||
938 (c >='a' && c <= 'f') ||
939 (c == '*' && (flags & DHOPT_MATCH))))
941 is_hex = 0;
942 if (c != '[' && c != ']')
943 is_addr6 = 0;
946 else
947 found_dig = 1;
949 if (!found_dig)
950 is_dec = is_addr = 0;
952 /* We know that some options take addresses */
953 if (opt_len & OT_ADDR_LIST)
955 is_string = is_dec = is_hex = 0;
957 if (!is6 && (!is_addr || dots == 0))
958 ret_err(_("bad IP address"));
960 if (is6 && !is_addr6)
961 ret_err(_("bad IPv6 address"));
963 /* or names */
964 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
965 is_addr6 = is_addr = is_dec = is_hex = 0;
967 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
969 int val, fac = 1;
971 switch (comma[strlen(comma) - 1])
973 case 'w':
974 case 'W':
975 fac *= 7;
976 /* fall through */
977 case 'd':
978 case 'D':
979 fac *= 24;
980 /* fall though */
981 case 'h':
982 case 'H':
983 fac *= 60;
984 /* fall through */
985 case 'm':
986 case 'M':
987 fac *= 60;
988 /* fall through */
989 case 's':
990 case 'S':
991 comma[strlen(comma) - 1] = 0;
994 new->len = 4;
995 new->val = opt_malloc(4);
996 val = atoi(comma);
997 *((int *)new->val) = htonl(val * fac);
999 else if (is_hex && digs > 1)
1001 new->len = digs;
1002 new->val = opt_malloc(new->len);
1003 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
1004 new->flags |= DHOPT_HEX;
1006 else if (is_dec)
1008 int i, val = atoi(comma);
1009 /* assume numeric arg is 1 byte except for
1010 options where it is known otherwise.
1011 For vendor class option, we have to hack. */
1012 if (opt_len != 0)
1013 new->len = opt_len;
1014 else if (val & 0xffff0000)
1015 new->len = 4;
1016 else if (val & 0xff00)
1017 new->len = 2;
1018 else
1019 new->len = 1;
1021 if (lenchar == 'b')
1022 new->len = 1;
1023 else if (lenchar == 's')
1024 new->len = 2;
1025 else if (lenchar == 'i')
1026 new->len = 4;
1028 new->val = opt_malloc(new->len);
1029 for (i=0; i<new->len; i++)
1030 new->val[i] = val>>((new->len - i - 1)*8);
1032 else if (is_addr && !is6)
1034 struct in_addr in;
1035 unsigned char *op;
1036 char *slash;
1037 /* max length of address/subnet descriptor is five bytes,
1038 add one for the option 120 enc byte too */
1039 new->val = op = opt_malloc((5 * addrs) + 1);
1040 new->flags |= DHOPT_ADDR;
1042 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1043 new->opt == OPTION_SIP_SERVER)
1045 *(op++) = 1; /* RFC 3361 "enc byte" */
1046 new->flags &= ~DHOPT_ADDR;
1048 while (addrs--)
1050 cp = comma;
1051 comma = split(cp);
1052 slash = split_chr(cp, '/');
1053 inet_pton(AF_INET, cp, &in);
1054 if (!slash)
1056 memcpy(op, &in, INADDRSZ);
1057 op += INADDRSZ;
1059 else
1061 unsigned char *p = (unsigned char *)&in;
1062 int netsize = atoi(slash);
1063 *op++ = netsize;
1064 if (netsize > 0)
1065 *op++ = *p++;
1066 if (netsize > 8)
1067 *op++ = *p++;
1068 if (netsize > 16)
1069 *op++ = *p++;
1070 if (netsize > 24)
1071 *op++ = *p++;
1072 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1075 new->len = op - new->val;
1077 else if (is_addr6 && is6)
1079 unsigned char *op;
1080 new->val = op = opt_malloc(16 * addrs);
1081 new->flags |= DHOPT_ADDR6;
1082 while (addrs--)
1084 cp = comma;
1085 comma = split(cp);
1087 /* check for [1234::7] */
1088 if (*cp == '[')
1089 cp++;
1090 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1091 cp[strlen(cp)-1] = 0;
1093 if (inet_pton(AF_INET6, cp, op))
1095 op += IN6ADDRSZ;
1096 continue;
1099 ret_err(_("bad IPv6 address"));
1101 new->len = op - new->val;
1103 else if (is_string)
1105 /* text arg */
1106 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
1107 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1109 /* dns search, RFC 3397, or SIP, RFC 3361 */
1110 unsigned char *q, *r, *tail;
1111 unsigned char *p, *m = NULL, *newp;
1112 size_t newlen, len = 0;
1113 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
1115 arg = comma;
1116 comma = split(arg);
1118 while (arg && *arg)
1120 char *in, *dom = NULL;
1121 size_t domlen = 1;
1122 /* Allow "." as an empty domain */
1123 if (strcmp (arg, ".") != 0)
1125 if (!(dom = canonicalise_opt(arg)))
1126 ret_err(_("bad domain in dhcp-option"));
1128 domlen = strlen(dom) + 2;
1131 newp = opt_malloc(len + domlen + header_size);
1132 if (m)
1134 memcpy(newp, m, header_size + len);
1135 free(m);
1137 m = newp;
1138 p = m + header_size;
1139 q = p + len;
1141 /* add string on the end in RFC1035 format */
1142 for (in = dom; in && *in;)
1144 unsigned char *cp = q++;
1145 int j;
1146 for (j = 0; *in && (*in != '.'); in++, j++)
1147 *q++ = *in;
1148 *cp = j;
1149 if (*in)
1150 in++;
1152 *q++ = 0;
1153 free(dom);
1155 /* Now tail-compress using earlier names. */
1156 newlen = q - p;
1157 for (tail = p + len; *tail; tail += (*tail) + 1)
1158 for (r = p; r - p < (int)len; r += (*r) + 1)
1159 if (strcmp((char *)r, (char *)tail) == 0)
1161 PUTSHORT((r - p) | 0xc000, tail);
1162 newlen = tail - p;
1163 goto end;
1165 end:
1166 len = newlen;
1168 arg = comma;
1169 comma = split(arg);
1172 /* RFC 3361, enc byte is zero for names */
1173 if (new->opt == OPTION_SIP_SERVER)
1174 m[0] = 0;
1175 new->len = (int) len + header_size;
1176 new->val = m;
1178 #ifdef HAVE_DHCP6
1179 else if (comma && (opt_len & OT_CSTRING))
1181 /* length fields are two bytes so need 16 bits for each string */
1182 int i, commas = 1;
1183 unsigned char *p, *newp;
1185 for (i = 0; comma[i]; i++)
1186 if (comma[i] == ',')
1187 commas++;
1189 newp = opt_malloc(strlen(comma)+(2*commas));
1190 p = newp;
1191 arg = comma;
1192 comma = split(arg);
1194 while (arg && *arg)
1196 u16 len = strlen(arg);
1197 unhide_metas(arg);
1198 PUTSHORT(len, p);
1199 memcpy(p, arg, len);
1200 p += len;
1202 arg = comma;
1203 comma = split(arg);
1206 new->val = newp;
1207 new->len = p - newp;
1209 else if (comma && (opt_len & OT_RFC1035_NAME))
1211 unsigned char *p = NULL, *newp, *end;
1212 int len = 0;
1213 arg = comma;
1214 comma = split(arg);
1216 while (arg && *arg)
1218 char *dom = canonicalise_opt(arg);
1219 if (!dom)
1220 ret_err(_("bad domain in dhcp-option"));
1222 newp = opt_malloc(len + strlen(dom) + 2);
1224 if (p)
1226 memcpy(newp, p, len);
1227 free(p);
1230 p = newp;
1231 end = do_rfc1035_name(p + len, dom);
1232 *end++ = 0;
1233 len = end - p;
1234 free(dom);
1236 arg = comma;
1237 comma = split(arg);
1240 new->val = p;
1241 new->len = len;
1243 #endif
1244 else
1246 new->len = strlen(comma);
1247 /* keep terminating zero on string */
1248 new->val = (unsigned char *)opt_string_alloc(comma);
1249 new->flags |= DHOPT_STRING;
1254 if (!is6 &&
1255 ((new->len > 255) ||
1256 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1257 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
1258 ret_err(_("dhcp-option too long"));
1260 if (flags == DHOPT_MATCH)
1262 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1263 !new->netid ||
1264 new->netid->next)
1265 ret_err(_("illegal dhcp-match"));
1267 if (is6)
1269 new->next = daemon->dhcp_match6;
1270 daemon->dhcp_match6 = new;
1272 else
1274 new->next = daemon->dhcp_match;
1275 daemon->dhcp_match = new;
1278 else if (is6)
1280 new->next = daemon->dhcp_opts6;
1281 daemon->dhcp_opts6 = new;
1283 else
1285 new->next = daemon->dhcp_opts;
1286 daemon->dhcp_opts = new;
1289 return 1;
1292 #endif
1294 void set_option_bool(unsigned int opt)
1296 if (opt < 32)
1297 daemon->options |= 1u << opt;
1298 else
1299 daemon->options2 |= 1u << (opt - 32);
1302 void reset_option_bool(unsigned int opt)
1304 if (opt < 32)
1305 daemon->options &= ~(1u << opt);
1306 else
1307 daemon->options2 &= ~(1u << (opt - 32));
1310 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
1312 int i;
1313 char *comma;
1315 if (option == '?')
1316 ret_err(gen_err);
1318 for (i=0; usage[i].opt != 0; i++)
1319 if (usage[i].opt == option)
1321 int rept = usage[i].rept;
1323 if (command_line)
1325 /* command line */
1326 if (rept == ARG_USED_CL)
1327 ret_err(_("illegal repeated flag"));
1328 if (rept == ARG_ONE)
1329 usage[i].rept = ARG_USED_CL;
1331 else
1333 /* allow file to override command line */
1334 if (rept == ARG_USED_FILE)
1335 ret_err(_("illegal repeated keyword"));
1336 if (rept == ARG_USED_CL || rept == ARG_ONE)
1337 usage[i].rept = ARG_USED_FILE;
1340 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1342 set_option_bool(rept);
1343 return 1;
1346 break;
1349 switch (option)
1351 case 'C': /* --conf-file */
1353 char *file = opt_string_alloc(arg);
1354 if (file)
1356 one_file(file, 0);
1357 free(file);
1359 break;
1362 case '7': /* --conf-dir */
1364 DIR *dir_stream;
1365 struct dirent *ent;
1366 char *directory, *path;
1367 struct list {
1368 char *suffix;
1369 struct list *next;
1370 } *ignore_suffix = NULL, *li;
1372 comma = split(arg);
1373 if (!(directory = opt_string_alloc(arg)))
1374 break;
1376 for (arg = comma; arg; arg = comma)
1378 comma = split(arg);
1379 li = opt_malloc(sizeof(struct list));
1380 li->next = ignore_suffix;
1381 ignore_suffix = li;
1382 /* Have to copy: buffer is overwritten */
1383 li->suffix = opt_string_alloc(arg);
1386 if (!(dir_stream = opendir(directory)))
1387 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1389 while ((ent = readdir(dir_stream)))
1391 size_t len = strlen(ent->d_name);
1392 struct stat buf;
1394 /* ignore emacs backups and dotfiles */
1395 if (len == 0 ||
1396 ent->d_name[len - 1] == '~' ||
1397 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1398 ent->d_name[0] == '.')
1399 continue;
1401 for (li = ignore_suffix; li; li = li->next)
1403 /* check for proscribed suffices */
1404 size_t ls = strlen(li->suffix);
1405 if (len > ls &&
1406 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1407 break;
1409 if (li)
1410 continue;
1412 path = opt_malloc(strlen(directory) + len + 2);
1413 strcpy(path, directory);
1414 strcat(path, "/");
1415 strcat(path, ent->d_name);
1417 /* files must be readable */
1418 if (stat(path, &buf) == -1)
1419 die(_("cannot access %s: %s"), path, EC_FILE);
1421 /* only reg files allowed. */
1422 if (S_ISREG(buf.st_mode))
1423 one_file(path, 0);
1425 free(path);
1428 closedir(dir_stream);
1429 free(directory);
1430 for(; ignore_suffix; ignore_suffix = li)
1432 li = ignore_suffix->next;
1433 free(ignore_suffix->suffix);
1434 free(ignore_suffix);
1437 break;
1440 case LOPT_ADD_SBNET: /* --add-subnet */
1441 set_option_bool(OPT_CLIENT_SUBNET);
1442 if (arg)
1444 comma = split(arg);
1445 if (!atoi_check(arg, &daemon->addr4_netmask) ||
1446 (comma && !atoi_check(comma, &daemon->addr6_netmask)))
1447 ret_err(gen_err);
1449 break;
1451 case '1': /* --enable-dbus */
1452 set_option_bool(OPT_DBUS);
1453 if (arg)
1454 daemon->dbus_name = opt_string_alloc(arg);
1455 else
1456 daemon->dbus_name = DNSMASQ_SERVICE;
1457 break;
1459 case '8': /* --log-facility */
1460 /* may be a filename */
1461 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1462 daemon->log_file = opt_string_alloc(arg);
1463 else
1465 #ifdef __ANDROID__
1466 ret_err(_("setting log facility is not possible under Android"));
1467 #else
1468 for (i = 0; facilitynames[i].c_name; i++)
1469 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1470 break;
1472 if (facilitynames[i].c_name)
1473 daemon->log_fac = facilitynames[i].c_val;
1474 else
1475 ret_err(_("bad log facility"));
1476 #endif
1478 break;
1480 case 'x': /* --pid-file */
1481 daemon->runfile = opt_string_alloc(arg);
1482 break;
1484 case 'r': /* --resolv-file */
1486 char *name = opt_string_alloc(arg);
1487 struct resolvc *new, *list = daemon->resolv_files;
1489 if (list && list->is_default)
1491 /* replace default resolv file - possibly with nothing */
1492 if (name)
1494 list->is_default = 0;
1495 list->name = name;
1497 else
1498 list = NULL;
1500 else if (name)
1502 new = opt_malloc(sizeof(struct resolvc));
1503 new->next = list;
1504 new->name = name;
1505 new->is_default = 0;
1506 new->mtime = 0;
1507 new->logged = 0;
1508 list = new;
1510 daemon->resolv_files = list;
1511 break;
1514 case 'm': /* --mx-host */
1516 int pref = 1;
1517 struct mx_srv_record *new;
1518 char *name, *target = NULL;
1520 if ((comma = split(arg)))
1522 char *prefstr;
1523 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1524 ret_err(_("bad MX preference"));
1527 if (!(name = canonicalise_opt(arg)) ||
1528 (comma && !(target = canonicalise_opt(comma))))
1529 ret_err(_("bad MX name"));
1531 new = opt_malloc(sizeof(struct mx_srv_record));
1532 new->next = daemon->mxnames;
1533 daemon->mxnames = new;
1534 new->issrv = 0;
1535 new->name = name;
1536 new->target = target; /* may be NULL */
1537 new->weight = pref;
1538 break;
1541 case 't': /* --mx-target */
1542 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1543 ret_err(_("bad MX target"));
1544 break;
1546 #ifdef HAVE_DHCP
1547 case 'l': /* --dhcp-leasefile */
1548 daemon->lease_file = opt_string_alloc(arg);
1549 break;
1551 /* Sorry about the gross pre-processor abuse */
1552 case '6': /* --dhcp-script */
1553 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1554 # if defined(NO_FORK)
1555 ret_err(_("cannot run scripts under uClinux"));
1556 # elif !defined(HAVE_SCRIPT)
1557 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
1558 # else
1559 if (option == LOPT_LUASCRIPT)
1560 # if !defined(HAVE_LUASCRIPT)
1561 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
1562 # else
1563 daemon->luascript = opt_string_alloc(arg);
1564 # endif
1565 else
1566 daemon->lease_change_command = opt_string_alloc(arg);
1567 # endif
1568 break;
1569 #endif /* HAVE_DHCP */
1571 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1572 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1573 case 'H': /* --addn-hosts */
1575 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1576 static int hosts_index = 1;
1577 new->fname = opt_string_alloc(arg);
1578 new->index = hosts_index++;
1579 new->flags = 0;
1580 if (option == 'H')
1582 new->next = daemon->addn_hosts;
1583 daemon->addn_hosts = new;
1585 else if (option == LOPT_DHCP_HOST)
1587 new->next = daemon->dhcp_hosts_file;
1588 daemon->dhcp_hosts_file = new;
1590 else if (option == LOPT_DHCP_OPTS)
1592 new->next = daemon->dhcp_opts_file;
1593 daemon->dhcp_opts_file = new;
1595 break;
1599 #ifdef HAVE_AUTH
1600 case LOPT_AUTHSERV: /* --auth-server */
1601 if (!(comma = split(arg)))
1602 ret_err(gen_err);
1604 daemon->authserver = opt_string_alloc(arg);
1605 arg = comma;
1606 do {
1607 struct iname *new = opt_malloc(sizeof(struct iname));
1608 comma = split(arg);
1609 new->name = NULL;
1610 unhide_metas(arg);
1611 if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
1612 new->addr.sa.sa_family = AF_INET;
1613 #ifdef HAVE_IPV6
1614 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1615 new->addr.sa.sa_family = AF_INET6;
1616 #endif
1617 else
1618 new->name = opt_string_alloc(arg);
1620 new->next = daemon->authinterface;
1621 daemon->authinterface = new;
1623 arg = comma;
1624 } while (arg);
1626 break;
1628 case LOPT_AUTHSFS: /* --auth-sec-servers */
1630 struct name_list *new;
1632 do {
1633 comma = split(arg);
1634 new = opt_malloc(sizeof(struct name_list));
1635 new->name = opt_string_alloc(arg);
1636 new->next = daemon->secondary_forward_server;
1637 daemon->secondary_forward_server = new;
1638 arg = comma;
1639 } while (arg);
1640 break;
1643 case LOPT_AUTHZONE: /* --auth-zone */
1645 struct auth_zone *new;
1647 comma = split(arg);
1649 new = opt_malloc(sizeof(struct auth_zone));
1650 new->domain = opt_string_alloc(arg);
1651 new->subnet = NULL;
1652 new->next = daemon->auth_zones;
1653 daemon->auth_zones = new;
1655 while ((arg = comma))
1657 int prefixlen = 0;
1658 char *prefix;
1659 struct subnet *subnet = opt_malloc(sizeof(struct subnet));
1661 subnet->next = new->subnet;
1662 new->subnet = subnet;
1664 comma = split(arg);
1665 prefix = split_chr(arg, '/');
1667 if (prefix && !atoi_check(prefix, &prefixlen))
1668 ret_err(gen_err);
1670 if (inet_pton(AF_INET, arg, &subnet->addr4))
1672 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
1673 subnet->is6 = 0;
1675 #ifdef HAVE_IPV6
1676 else if (inet_pton(AF_INET6, arg, &subnet->addr6))
1678 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
1679 subnet->is6 = 1;
1681 #endif
1682 else
1683 ret_err(gen_err);
1685 break;
1688 case LOPT_AUTHSOA: /* --auth-soa */
1689 comma = split(arg);
1690 daemon->soa_sn = (u32)atoi(arg);
1691 if (comma)
1693 char *cp;
1694 arg = comma;
1695 comma = split(arg);
1696 daemon->hostmaster = opt_string_alloc(arg);
1697 for (cp = daemon->hostmaster; *cp; cp++)
1698 if (*cp == '@')
1699 *cp = '.';
1701 if (comma)
1703 arg = comma;
1704 comma = split(arg);
1705 daemon->soa_refresh = (u32)atoi(arg);
1706 if (comma)
1708 arg = comma;
1709 comma = split(arg);
1710 daemon->soa_retry = (u32)atoi(arg);
1711 if (comma)
1713 arg = comma;
1714 comma = split(arg);
1715 daemon->soa_expiry = (u32)atoi(arg);
1721 break;
1722 #endif
1724 case 's': /* --domain */
1725 case LOPT_SYNTH: /* --synth-domain */
1726 if (strcmp (arg, "#") == 0)
1727 set_option_bool(OPT_RESOLV_DOMAIN);
1728 else
1730 char *d;
1731 comma = split(arg);
1732 if (!(d = canonicalise_opt(arg)))
1733 ret_err(gen_err);
1734 else
1736 if (comma)
1738 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
1739 char *netpart;
1741 new->prefix = NULL;
1743 unhide_metas(comma);
1744 if ((netpart = split_chr(comma, '/')))
1746 int msize;
1748 arg = split(netpart);
1749 if (!atoi_check(netpart, &msize))
1750 ret_err(gen_err);
1751 else if (inet_pton(AF_INET, comma, &new->start))
1753 int mask = (1 << (32 - msize)) - 1;
1754 new->is6 = 0;
1755 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1756 new->end.s_addr = new->start.s_addr | htonl(mask);
1757 if (arg)
1759 if (option != 's')
1761 if (!(new->prefix = canonicalise_opt(arg)) ||
1762 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1763 ret_err(_("bad prefix"));
1765 else if (strcmp(arg, "local") != 0 ||
1766 (msize != 8 && msize != 16 && msize != 24))
1767 ret_err(gen_err);
1768 else
1770 /* generate the equivalent of
1771 local=/<domain>/
1772 local=/xxx.yyy.zzz.in-addr.arpa/ */
1773 struct server *serv = opt_malloc(sizeof(struct server));
1774 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1775 char *p;
1777 memset(serv, 0, sizeof(struct server));
1778 serv->domain = d;
1779 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1780 serv->next = daemon->servers;
1781 daemon->servers = serv;
1783 serv = opt_malloc(sizeof(struct server));
1784 memset(serv, 0, sizeof(struct server));
1785 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1787 if (msize == 24)
1788 p += sprintf(p, "%d.", a & 0xff);
1789 a = a >> 8;
1790 if (msize != 8)
1791 p += sprintf(p, "%d.", a & 0xff);
1792 a = a >> 8;
1793 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
1795 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1796 serv->next = daemon->servers;
1797 daemon->servers = serv;
1801 #ifdef HAVE_IPV6
1802 else if (inet_pton(AF_INET6, comma, &new->start6))
1804 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1805 u64 addrpart = addr6part(&new->start6);
1806 new->is6 = 1;
1808 /* prefix==64 overflows the mask calculation above */
1809 if (msize == 64)
1810 mask = (u64)-1LL;
1812 new->end6 = new->start6;
1813 setaddr6part(&new->start6, addrpart & ~mask);
1814 setaddr6part(&new->end6, addrpart | mask);
1816 if (msize < 64)
1817 ret_err(gen_err);
1818 else if (arg)
1820 if (option != 's')
1822 if (!(new->prefix = canonicalise_opt(arg)) ||
1823 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
1824 ret_err(_("bad prefix"));
1826 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
1827 ret_err(gen_err);
1828 else
1830 /* generate the equivalent of
1831 local=/<domain>/
1832 local=/xxx.yyy.zzz.ip6.arpa/ */
1833 struct server *serv = opt_malloc(sizeof(struct server));
1834 char *p;
1836 memset(serv, 0, sizeof(struct server));
1837 serv->domain = d;
1838 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1839 serv->next = daemon->servers;
1840 daemon->servers = serv;
1842 serv = opt_malloc(sizeof(struct server));
1843 memset(serv, 0, sizeof(struct server));
1844 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1846 for (i = msize-1; i >= 0; i -= 4)
1848 int dig = ((unsigned char *)&new->start6)[i>>3];
1849 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1851 p += sprintf(p, "ip6.arpa");
1853 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1854 serv->next = daemon->servers;
1855 daemon->servers = serv;
1859 #endif
1860 else
1861 ret_err(gen_err);
1863 else
1865 arg = split(comma);
1866 if (inet_pton(AF_INET, comma, &new->start))
1868 new->is6 = 0;
1869 if (!arg)
1870 new->end.s_addr = new->start.s_addr;
1871 else if (!inet_pton(AF_INET, arg, &new->end))
1872 ret_err(gen_err);
1874 #ifdef HAVE_IPV6
1875 else if (inet_pton(AF_INET6, comma, &new->start6))
1877 new->is6 = 1;
1878 if (!arg)
1879 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1880 else if (!inet_pton(AF_INET6, arg, &new->end6))
1881 ret_err(gen_err);
1883 #endif
1884 else
1885 ret_err(gen_err);
1888 new->domain = d;
1889 if (option == 's')
1891 new->next = daemon->cond_domain;
1892 daemon->cond_domain = new;
1894 else
1896 new->next = daemon->synth_domains;
1897 daemon->synth_domains = new;
1900 else if (option == 's')
1901 daemon->domain_suffix = d;
1902 else
1903 ret_err(gen_err);
1906 break;
1908 case 'u': /* --user */
1909 daemon->username = opt_string_alloc(arg);
1910 break;
1912 case 'g': /* --group */
1913 daemon->groupname = opt_string_alloc(arg);
1914 daemon->group_set = 1;
1915 break;
1917 #ifdef HAVE_DHCP
1918 case LOPT_SCRIPTUSR: /* --scriptuser */
1919 daemon->scriptuser = opt_string_alloc(arg);
1920 break;
1921 #endif
1923 case 'i': /* --interface */
1924 do {
1925 struct iname *new = opt_malloc(sizeof(struct iname));
1926 comma = split(arg);
1927 new->next = daemon->if_names;
1928 daemon->if_names = new;
1929 /* new->name may be NULL if someone does
1930 "interface=" to disable all interfaces except loop. */
1931 new->name = opt_string_alloc(arg);
1932 new->used = 0;
1933 arg = comma;
1934 } while (arg);
1935 break;
1937 case LOPT_TFTP: /* --enable-tftp */
1938 set_option_bool(OPT_TFTP);
1939 if (!arg)
1940 break;
1941 /* fall through */
1943 case 'I': /* --except-interface */
1944 case '2': /* --no-dhcp-interface */
1945 do {
1946 struct iname *new = opt_malloc(sizeof(struct iname));
1947 comma = split(arg);
1948 new->name = opt_string_alloc(arg);
1949 if (option == 'I')
1951 new->next = daemon->if_except;
1952 daemon->if_except = new;
1954 else if (option == LOPT_TFTP)
1956 new->next = daemon->tftp_interfaces;
1957 daemon->tftp_interfaces = new;
1959 else
1961 new->next = daemon->dhcp_except;
1962 daemon->dhcp_except = new;
1964 arg = comma;
1965 } while (arg);
1966 break;
1968 case 'B': /* --bogus-nxdomain */
1970 struct in_addr addr;
1971 unhide_metas(arg);
1972 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
1974 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1975 baddr->next = daemon->bogus_addr;
1976 daemon->bogus_addr = baddr;
1977 baddr->addr = addr;
1979 else
1980 ret_err(gen_err); /* error */
1981 break;
1984 case 'a': /* --listen-address */
1985 case LOPT_AUTHPEER: /* --auth-peer */
1986 do {
1987 struct iname *new = opt_malloc(sizeof(struct iname));
1988 comma = split(arg);
1989 unhide_metas(arg);
1990 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
1992 new->addr.sa.sa_family = AF_INET;
1993 new->addr.in.sin_port = 0;
1994 #ifdef HAVE_SOCKADDR_SA_LEN
1995 new->addr.in.sin_len = sizeof(new->addr.in);
1996 #endif
1998 #ifdef HAVE_IPV6
1999 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
2001 new->addr.sa.sa_family = AF_INET6;
2002 new->addr.in6.sin6_flowinfo = 0;
2003 new->addr.in6.sin6_scope_id = 0;
2004 new->addr.in6.sin6_port = 0;
2005 #ifdef HAVE_SOCKADDR_SA_LEN
2006 new->addr.in6.sin6_len = sizeof(new->addr.in6);
2007 #endif
2009 #endif
2010 else
2011 ret_err(gen_err);
2013 new->used = 0;
2014 if (option == 'a')
2016 new->next = daemon->if_addrs;
2017 daemon->if_addrs = new;
2019 else
2021 new->next = daemon->auth_peers;
2022 daemon->auth_peers = new;
2024 arg = comma;
2025 } while (arg);
2026 break;
2028 case 'S': /* --server */
2029 case LOPT_LOCAL: /* --local */
2030 case 'A': /* --address */
2031 case LOPT_NO_REBIND: /* --rebind-domain-ok */
2033 struct server *serv, *newlist = NULL;
2035 unhide_metas(arg);
2037 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
2039 int rebind = !(*arg == '/');
2040 char *end = NULL;
2041 if (!rebind)
2042 arg++;
2043 while (rebind || (end = split_chr(arg, '/')))
2045 char *domain = NULL;
2046 /* elide leading dots - they are implied in the search algorithm */
2047 while (*arg == '.') arg++;
2048 /* # matches everything and becomes a zero length domain string */
2049 if (strcmp(arg, "#") == 0)
2050 domain = "";
2051 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
2052 option = '?';
2053 serv = opt_malloc(sizeof(struct server));
2054 memset(serv, 0, sizeof(struct server));
2055 serv->next = newlist;
2056 newlist = serv;
2057 serv->domain = domain;
2058 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
2059 arg = end;
2060 if (rebind)
2061 break;
2063 if (!newlist)
2064 ret_err(gen_err);
2066 else
2068 newlist = opt_malloc(sizeof(struct server));
2069 memset(newlist, 0, sizeof(struct server));
2072 if (option == 'A')
2074 newlist->flags |= SERV_LITERAL_ADDRESS;
2075 if (!(newlist->flags & SERV_TYPE))
2076 ret_err(gen_err);
2078 else if (option == LOPT_NO_REBIND)
2079 newlist->flags |= SERV_NO_REBIND;
2081 if (!arg || !*arg)
2083 if (!(newlist->flags & SERV_NO_REBIND))
2084 newlist->flags |= SERV_NO_ADDR; /* no server */
2085 if (newlist->flags & SERV_LITERAL_ADDRESS)
2086 ret_err(gen_err);
2089 else if (strcmp(arg, "#") == 0)
2091 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
2092 if (newlist->flags & SERV_LITERAL_ADDRESS)
2093 ret_err(gen_err);
2095 else
2097 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2098 if (err)
2099 ret_err(err);
2102 serv = newlist;
2103 while (serv->next)
2105 serv->next->flags = serv->flags;
2106 serv->next->addr = serv->addr;
2107 serv->next->source_addr = serv->source_addr;
2108 strcpy(serv->next->interface, serv->interface);
2109 serv = serv->next;
2111 serv->next = daemon->servers;
2112 daemon->servers = newlist;
2113 break;
2116 case LOPT_IPSET: /* --ipset */
2117 #ifndef HAVE_IPSET
2118 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2119 break;
2120 #else
2122 struct ipsets ipsets_head;
2123 struct ipsets *ipsets = &ipsets_head;
2124 int size;
2125 char *end;
2126 char **sets, **sets_pos;
2127 memset(ipsets, 0, sizeof(struct ipsets));
2128 unhide_metas(arg);
2129 if (arg && *arg == '/')
2131 arg++;
2132 while ((end = split_chr(arg, '/')))
2134 char *domain = NULL;
2135 /* elide leading dots - they are implied in the search algorithm */
2136 while (*arg == '.')
2137 arg++;
2138 /* # matches everything and becomes a zero length domain string */
2139 if (strcmp(arg, "#") == 0 || !*arg)
2140 domain = "";
2141 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2142 option = '?';
2143 ipsets->next = opt_malloc(sizeof(struct ipsets));
2144 ipsets = ipsets->next;
2145 memset(ipsets, 0, sizeof(struct ipsets));
2146 ipsets->domain = domain;
2147 arg = end;
2150 else
2152 ipsets->next = opt_malloc(sizeof(struct ipsets));
2153 ipsets = ipsets->next;
2154 memset(ipsets, 0, sizeof(struct ipsets));
2155 ipsets->domain = "";
2157 if (!arg || !*arg)
2159 option = '?';
2160 break;
2162 size = 2;
2163 for (end = arg; *end; ++end)
2164 if (*end == ',')
2165 ++size;
2167 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2169 do {
2170 end = split(arg);
2171 *sets_pos++ = opt_string_alloc(arg);
2172 arg = end;
2173 } while (end);
2174 *sets_pos = 0;
2175 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2176 ipsets->next->sets = sets;
2177 ipsets->next = daemon->ipsets;
2178 daemon->ipsets = ipsets_head.next;
2180 break;
2182 #endif
2184 case 'c': /* --cache-size */
2186 int size;
2188 if (!atoi_check(arg, &size))
2189 ret_err(gen_err);
2190 else
2192 /* zero is OK, and means no caching. */
2194 if (size < 0)
2195 size = 0;
2196 else if (size > 10000)
2197 size = 10000;
2199 daemon->cachesize = size;
2201 break;
2204 case 'p': /* --port */
2205 if (!atoi_check16(arg, &daemon->port))
2206 ret_err(gen_err);
2207 break;
2209 case LOPT_MINPORT: /* --min-port */
2210 if (!atoi_check16(arg, &daemon->min_port))
2211 ret_err(gen_err);
2212 break;
2214 case '0': /* --dns-forward-max */
2215 if (!atoi_check(arg, &daemon->ftabsize))
2216 ret_err(gen_err);
2217 break;
2219 case LOPT_MAX_LOGS: /* --log-async */
2220 daemon->max_logs = LOG_MAX; /* default */
2221 if (arg && !atoi_check(arg, &daemon->max_logs))
2222 ret_err(gen_err);
2223 else if (daemon->max_logs > 100)
2224 daemon->max_logs = 100;
2225 break;
2227 case 'P': /* --edns-packet-max */
2229 int i;
2230 if (!atoi_check(arg, &i))
2231 ret_err(gen_err);
2232 daemon->edns_pktsz = (unsigned short)i;
2233 break;
2236 case 'Q': /* --query-port */
2237 if (!atoi_check16(arg, &daemon->query_port))
2238 ret_err(gen_err);
2239 /* if explicitly set to zero, use single OS ephemeral port
2240 and disable random ports */
2241 if (daemon->query_port == 0)
2242 daemon->osport = 1;
2243 break;
2245 case 'T': /* --local-ttl */
2246 case LOPT_NEGTTL: /* --neg-ttl */
2247 case LOPT_MAXTTL: /* --max-ttl */
2248 case LOPT_MAXCTTL: /* --max-cache-ttl */
2249 case LOPT_AUTHTTL: /* --auth-ttl */
2251 int ttl;
2252 if (!atoi_check(arg, &ttl))
2253 ret_err(gen_err);
2254 else if (option == LOPT_NEGTTL)
2255 daemon->neg_ttl = (unsigned long)ttl;
2256 else if (option == LOPT_MAXTTL)
2257 daemon->max_ttl = (unsigned long)ttl;
2258 else if (option == LOPT_MAXCTTL)
2259 daemon->max_cache_ttl = (unsigned long)ttl;
2260 else if (option == LOPT_AUTHTTL)
2261 daemon->auth_ttl = (unsigned long)ttl;
2262 else
2263 daemon->local_ttl = (unsigned long)ttl;
2264 break;
2267 #ifdef HAVE_DHCP
2268 case 'X': /* --dhcp-lease-max */
2269 if (!atoi_check(arg, &daemon->dhcp_max))
2270 ret_err(gen_err);
2271 break;
2272 #endif
2274 #ifdef HAVE_TFTP
2275 case LOPT_TFTP_MAX: /* --tftp-max */
2276 if (!atoi_check(arg, &daemon->tftp_max))
2277 ret_err(gen_err);
2278 break;
2280 case LOPT_PREFIX: /* --tftp-prefix */
2281 comma = split(arg);
2282 if (comma)
2284 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2285 new->interface = opt_string_alloc(comma);
2286 new->prefix = opt_string_alloc(arg);
2287 new->next = daemon->if_prefix;
2288 daemon->if_prefix = new;
2290 else
2291 daemon->tftp_prefix = opt_string_alloc(arg);
2292 break;
2294 case LOPT_TFTPPORTS: /* --tftp-port-range */
2295 if (!(comma = split(arg)) ||
2296 !atoi_check16(arg, &daemon->start_tftp_port) ||
2297 !atoi_check16(comma, &daemon->end_tftp_port))
2298 ret_err(_("bad port range"));
2300 if (daemon->start_tftp_port > daemon->end_tftp_port)
2302 int tmp = daemon->start_tftp_port;
2303 daemon->start_tftp_port = daemon->end_tftp_port;
2304 daemon->end_tftp_port = tmp;
2307 break;
2308 #endif
2310 case LOPT_BRIDGE: /* --bridge-interface */
2312 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2313 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2314 ret_err(_("bad bridge-interface"));
2316 strcpy(new->iface, arg);
2317 new->alias = NULL;
2318 new->next = daemon->bridges;
2319 daemon->bridges = new;
2321 do {
2322 arg = comma;
2323 comma = split(arg);
2324 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2326 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2327 b->next = new->alias;
2328 new->alias = b;
2329 strcpy(b->iface, arg);
2331 } while (comma);
2333 break;
2336 #ifdef HAVE_DHCP
2337 case 'F': /* --dhcp-range */
2339 int k, leasepos = 2;
2340 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2341 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2343 memset (new, 0, sizeof(*new));
2344 new->lease_time = DEFLEASE;
2346 if (!arg)
2348 option = '?';
2349 break;
2352 while(1)
2354 for (cp = arg; *cp; cp++)
2355 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2356 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2357 (*cp >='0' && *cp <= '9')))
2358 break;
2360 if (*cp != ',' && (comma = split(arg)))
2362 if (is_tag_prefix(arg))
2364 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2365 tt->net = opt_string_alloc(arg+4);
2366 tt->next = new->filter;
2367 /* ignore empty tag */
2368 if (tt->net)
2369 new->filter = tt;
2371 else
2373 if (new->netid.net)
2374 ret_err(_("only one tag allowed"));
2375 else if (strstr(arg, "set:") == arg)
2376 new->netid.net = opt_string_alloc(arg+4);
2377 else
2378 new->netid.net = opt_string_alloc(arg);
2380 arg = comma;
2382 else
2384 a[0] = arg;
2385 break;
2389 for (k = 1; k < 8; k++)
2390 if (!(a[k] = split(a[k-1])))
2391 break;
2393 if (k < 2)
2394 ret_err(_("bad dhcp-range"));
2396 if (inet_pton(AF_INET, a[0], &new->start))
2398 new->next = daemon->dhcp;
2399 daemon->dhcp = new;
2400 new->end = new->start;
2401 if (strcmp(a[1], "static") == 0)
2402 new->flags |= CONTEXT_STATIC;
2403 else if (strcmp(a[1], "proxy") == 0)
2404 new->flags |= CONTEXT_PROXY;
2405 else if (!inet_pton(AF_INET, a[1], &new->end))
2406 ret_err(_("bad dhcp-range"));
2408 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2410 struct in_addr tmp = new->start;
2411 new->start = new->end;
2412 new->end = tmp;
2415 if (k >= 3 && strchr(a[2], '.') &&
2416 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
2418 new->flags |= CONTEXT_NETMASK;
2419 leasepos = 3;
2420 if (!is_same_net(new->start, new->end, new->netmask))
2421 ret_err(_("inconsistent DHCP range"));
2424 if (k >= 4 && strchr(a[3], '.') &&
2425 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
2427 new->flags |= CONTEXT_BRDCAST;
2428 leasepos = 4;
2431 #ifdef HAVE_DHCP6
2432 else if (inet_pton(AF_INET6, a[0], &new->start6))
2434 new->flags |= CONTEXT_V6;
2435 new->prefix = 64; /* default */
2436 new->end6 = new->start6;
2437 new->next = daemon->dhcp6;
2438 daemon->dhcp6 = new;
2440 for (leasepos = 1; leasepos < k; leasepos++)
2442 if (strcmp(a[leasepos], "static") == 0)
2443 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2444 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2445 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
2446 else if (strcmp(a[leasepos], "ra-names") == 0)
2447 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
2448 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2449 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
2450 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2451 new->flags |= CONTEXT_DHCP;
2452 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2454 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2455 new->flags |= CONTEXT_TEMPLATE;
2457 else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
2459 new->template_interface = opt_string_alloc(a[leasepos] + 19);
2460 new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
2462 else
2463 break;
2466 /* bare integer < 128 is prefix value */
2467 if (leasepos < k)
2469 int pref;
2470 for (cp = a[leasepos]; *cp; cp++)
2471 if (!(*cp >= '0' && *cp <= '9'))
2472 break;
2473 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
2475 new->prefix = pref;
2476 leasepos++;
2480 if (new->prefix != 64)
2482 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2483 ret_err(_("prefix length must be exactly 64 for RA subnets"));
2484 else if (new->flags & CONTEXT_TEMPLATE)
2485 ret_err(_("prefix length must be exactly 64 for subnet constructors"));
2488 if (new->prefix < 64)
2489 ret_err(_("prefix length must be at least 64"));
2491 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2492 ret_err(_("inconsistent DHCPv6 range"));
2494 /* dhcp-range=:: enables DHCP stateless on any interface */
2495 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
2496 new->prefix = 0;
2498 if (new->flags & CONTEXT_TEMPLATE)
2500 struct in6_addr zero;
2501 memset(&zero, 0, sizeof(zero));
2502 if (!is_same_net6(&zero, &new->start6, new->prefix))
2503 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2506 if (addr6part(&new->start6) > addr6part(&new->end6))
2508 struct in6_addr tmp = new->start6;
2509 new->start6 = new->end6;
2510 new->end6 = tmp;
2513 #endif
2514 else
2515 ret_err(_("bad dhcp-range"));
2517 if (leasepos < k)
2519 if (strcmp(a[leasepos], "infinite") == 0)
2520 new->lease_time = 0xffffffff;
2521 else if (strcmp(a[leasepos], "deprecated") == 0)
2522 new->flags |= CONTEXT_DEPRECATE;
2523 else
2525 int fac = 1;
2526 if (strlen(a[leasepos]) > 0)
2528 switch (a[leasepos][strlen(a[leasepos]) - 1])
2530 case 'w':
2531 case 'W':
2532 fac *= 7;
2533 /* fall through */
2534 case 'd':
2535 case 'D':
2536 fac *= 24;
2537 /* fall though */
2538 case 'h':
2539 case 'H':
2540 fac *= 60;
2541 /* fall through */
2542 case 'm':
2543 case 'M':
2544 fac *= 60;
2545 /* fall through */
2546 case 's':
2547 case 'S':
2548 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2551 for (cp = a[leasepos]; *cp; cp++)
2552 if (!(*cp >= '0' && *cp <= '9'))
2553 break;
2555 if (*cp || (leasepos+1 < k))
2556 ret_err(_("bad dhcp-range"));
2558 new->lease_time = atoi(a[leasepos]) * fac;
2559 /* Leases of a minute or less confuse
2560 some clients, notably Apple's */
2561 if (new->lease_time < 120)
2562 new->lease_time = 120;
2566 break;
2569 case LOPT_BANK:
2570 case 'G': /* --dhcp-host */
2572 int j, k = 0;
2573 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2574 struct dhcp_config *new;
2575 struct in_addr in;
2577 new = opt_malloc(sizeof(struct dhcp_config));
2579 new->next = daemon->dhcp_conf;
2580 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2581 new->hwaddr = NULL;
2582 new->netid = NULL;
2584 if ((a[0] = arg))
2585 for (k = 1; k < 7; k++)
2586 if (!(a[k] = split(a[k-1])))
2587 break;
2589 for (j = 0; j < k; j++)
2590 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2592 char *arg = a[j];
2594 if ((arg[0] == 'i' || arg[0] == 'I') &&
2595 (arg[1] == 'd' || arg[1] == 'D') &&
2596 arg[2] == ':')
2598 if (arg[3] == '*')
2599 new->flags |= CONFIG_NOCLID;
2600 else
2602 int len;
2603 arg += 3; /* dump id: */
2604 if (strchr(arg, ':'))
2605 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2606 else
2608 unhide_metas(arg);
2609 len = (int) strlen(arg);
2612 if (len == -1)
2614 ret_err(_("bad hex constant"));
2615 else if ((new->clid = opt_malloc(len)))
2617 new->flags |= CONFIG_CLID;
2618 new->clid_len = len;
2619 memcpy(new->clid, arg, len);
2623 /* dhcp-host has strange backwards-compat needs. */
2624 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2626 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2627 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2628 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2629 newlist->next = new->netid;
2630 new->netid = newlist;
2631 newlist->list = newtag;
2632 strcpy(newtag->net, arg+4);
2633 unhide_metas(newtag->net);
2635 else if (strstr(arg, "tag:") == arg)
2636 ret_err(_("cannot match tags in --dhcp-host"));
2637 #ifdef HAVE_DHCP6
2638 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2640 arg[strlen(arg)-1] = 0;
2641 arg++;
2643 if (!inet_pton(AF_INET6, arg, &new->addr6))
2644 ret_err(_("bad IPv6 address"));
2646 for (i= 0; i < 8; i++)
2647 if (new->addr6.s6_addr[i] != 0)
2648 break;
2650 /* set WILDCARD if network part all zeros */
2651 if (i == 8)
2652 new->flags |= CONFIG_WILDCARD;
2654 new->flags |= CONFIG_ADDR6;
2656 #endif
2657 else
2659 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2660 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2661 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2662 ret_err(_("bad hex constant"));
2663 else
2666 newhw->next = new->hwaddr;
2667 new->hwaddr = newhw;
2671 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
2673 struct dhcp_config *configs;
2675 new->addr = in;
2676 new->flags |= CONFIG_ADDR;
2678 /* If the same IP appears in more than one host config, then DISCOVER
2679 for one of the hosts will get the address, but REQUEST will be NAKed,
2680 since the address is reserved by the other one -> protocol loop. */
2681 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2682 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2684 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2685 return 0;
2688 else
2690 char *cp, *lastp = NULL, last = 0;
2691 int fac = 1;
2693 if (strlen(a[j]) > 1)
2695 lastp = a[j] + strlen(a[j]) - 1;
2696 last = *lastp;
2697 switch (last)
2699 case 'w':
2700 case 'W':
2701 fac *= 7;
2702 /* fall through */
2703 case 'd':
2704 case 'D':
2705 fac *= 24;
2706 /* fall through */
2707 case 'h':
2708 case 'H':
2709 fac *= 60;
2710 /* fall through */
2711 case 'm':
2712 case 'M':
2713 fac *= 60;
2714 /* fall through */
2715 case 's':
2716 case 'S':
2717 *lastp = 0;
2721 for (cp = a[j]; *cp; cp++)
2722 if (!isdigit((unsigned char)*cp) && *cp != ' ')
2723 break;
2725 if (*cp)
2727 if (lastp)
2728 *lastp = last;
2729 if (strcmp(a[j], "infinite") == 0)
2731 new->lease_time = 0xffffffff;
2732 new->flags |= CONFIG_TIME;
2734 else if (strcmp(a[j], "ignore") == 0)
2735 new->flags |= CONFIG_DISABLE;
2736 else
2738 if (!(new->hostname = canonicalise_opt(a[j])) ||
2739 !legal_hostname(new->hostname))
2740 ret_err(_("bad DHCP host name"));
2742 new->flags |= CONFIG_NAME;
2743 new->domain = strip_hostname(new->hostname);
2746 else
2748 new->lease_time = atoi(a[j]) * fac;
2749 /* Leases of a minute or less confuse
2750 some clients, notably Apple's */
2751 if (new->lease_time < 120)
2752 new->lease_time = 120;
2753 new->flags |= CONFIG_TIME;
2757 daemon->dhcp_conf = new;
2758 break;
2761 case LOPT_TAG_IF: /* --tag-if */
2763 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2765 new->tag = NULL;
2766 new->set = NULL;
2767 new->next = NULL;
2769 /* preserve order */
2770 if (!daemon->tag_if)
2771 daemon->tag_if = new;
2772 else
2774 struct tag_if *tmp;
2775 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2776 tmp->next = new;
2779 while (arg)
2781 size_t len;
2783 comma = split(arg);
2784 len = strlen(arg);
2786 if (len < 5)
2788 new->set = NULL;
2789 break;
2791 else
2793 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2794 newtag->net = opt_malloc(len - 3);
2795 strcpy(newtag->net, arg+4);
2796 unhide_metas(newtag->net);
2798 if (strstr(arg, "set:") == arg)
2800 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2801 newlist->next = new->set;
2802 new->set = newlist;
2803 newlist->list = newtag;
2805 else if (strstr(arg, "tag:") == arg)
2807 newtag->next = new->tag;
2808 new->tag = newtag;
2810 else
2812 new->set = NULL;
2813 free(newtag);
2814 break;
2818 arg = comma;
2821 if (!new->set)
2822 ret_err(_("bad tag-if"));
2824 break;
2828 case 'O': /* --dhcp-option */
2829 case LOPT_FORCE: /* --dhcp-option-force */
2830 case LOPT_OPTS:
2831 case LOPT_MATCH: /* --dhcp-match */
2832 return parse_dhcp_opt(errstr, arg,
2833 option == LOPT_FORCE ? DHOPT_FORCE :
2834 (option == LOPT_MATCH ? DHOPT_MATCH :
2835 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2837 case 'M': /* --dhcp-boot */
2839 struct dhcp_netid *id = NULL;
2840 while (is_tag_prefix(arg))
2842 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2843 newid->next = id;
2844 id = newid;
2845 comma = split(arg);
2846 newid->net = opt_string_alloc(arg+4);
2847 arg = comma;
2850 if (!arg)
2851 ret_err(gen_err);
2852 else
2854 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2855 struct in_addr dhcp_next_server;
2856 struct dhcp_boot *new;
2857 comma = split(arg);
2858 dhcp_file = opt_string_alloc(arg);
2859 dhcp_next_server.s_addr = 0;
2860 if (comma)
2862 arg = comma;
2863 comma = split(arg);
2864 dhcp_sname = opt_string_alloc(arg);
2865 if (comma)
2867 unhide_metas(comma);
2868 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2871 * The user may have specified the tftp hostname here.
2872 * save it so that it can be resolved/looked up during
2873 * actual dhcp_reply().
2876 tftp_sname = opt_string_alloc(comma);
2877 dhcp_next_server.s_addr = 0;
2882 new = opt_malloc(sizeof(struct dhcp_boot));
2883 new->file = dhcp_file;
2884 new->sname = dhcp_sname;
2885 new->tftp_sname = tftp_sname;
2886 new->next_server = dhcp_next_server;
2887 new->netid = id;
2888 new->next = daemon->boot_config;
2889 daemon->boot_config = new;
2892 break;
2895 case LOPT_PXE_PROMT: /* --pxe-prompt */
2897 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2898 int timeout;
2900 new->netid = NULL;
2901 new->opt = 10; /* PXE_MENU_PROMPT */
2903 while (is_tag_prefix(arg))
2905 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2906 comma = split(arg);
2907 nn->next = new->netid;
2908 new->netid = nn;
2909 nn->net = opt_string_alloc(arg+4);
2910 arg = comma;
2913 if (!arg)
2914 ret_err(gen_err);
2915 else
2917 comma = split(arg);
2918 unhide_metas(arg);
2919 new->len = strlen(arg) + 1;
2920 new->val = opt_malloc(new->len);
2921 memcpy(new->val + 1, arg, new->len - 1);
2923 new->u.vendor_class = (unsigned char *)"PXEClient";
2924 new->flags = DHOPT_VENDOR;
2926 if (comma && atoi_check(comma, &timeout))
2927 *(new->val) = timeout;
2928 else
2929 *(new->val) = 255;
2931 new->next = daemon->dhcp_opts;
2932 daemon->dhcp_opts = new;
2933 daemon->enable_pxe = 1;
2936 break;
2939 case LOPT_PXE_SERV: /* --pxe-service */
2941 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2942 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2943 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2944 static int boottype = 32768;
2946 new->netid = NULL;
2947 new->sname = NULL;
2948 new->server.s_addr = 0;
2950 while (is_tag_prefix(arg))
2952 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2953 comma = split(arg);
2954 nn->next = new->netid;
2955 new->netid = nn;
2956 nn->net = opt_string_alloc(arg+4);
2957 arg = comma;
2960 if (arg && (comma = split(arg)))
2962 for (i = 0; CSA[i]; i++)
2963 if (strcasecmp(CSA[i], arg) == 0)
2964 break;
2966 if (CSA[i] || atoi_check(arg, &i))
2968 arg = comma;
2969 comma = split(arg);
2971 new->CSA = i;
2972 new->menu = opt_string_alloc(arg);
2974 if (!comma)
2976 new->type = 0; /* local boot */
2977 new->basename = NULL;
2979 else
2981 arg = comma;
2982 comma = split(arg);
2983 if (atoi_check(arg, &i))
2985 new->type = i;
2986 new->basename = NULL;
2988 else
2990 new->type = boottype++;
2991 new->basename = opt_string_alloc(arg);
2994 if (comma)
2996 if (!inet_pton(AF_INET, comma, &new->server))
2998 new->server.s_addr = 0;
2999 new->sname = opt_string_alloc(comma);
3005 /* Order matters */
3006 new->next = NULL;
3007 if (!daemon->pxe_services)
3008 daemon->pxe_services = new;
3009 else
3011 struct pxe_service *s;
3012 for (s = daemon->pxe_services; s->next; s = s->next);
3013 s->next = new;
3016 daemon->enable_pxe = 1;
3017 break;
3022 ret_err(gen_err);
3025 case '4': /* --dhcp-mac */
3027 if (!(comma = split(arg)))
3028 ret_err(gen_err);
3029 else
3031 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
3032 new->netid.net = opt_string_alloc(set_prefix(arg));
3033 unhide_metas(comma);
3034 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
3035 if (new->hwaddr_len == -1)
3036 ret_err(gen_err);
3037 else
3039 new->next = daemon->dhcp_macs;
3040 daemon->dhcp_macs = new;
3044 break;
3046 #ifdef OPTION6_PREFIX_CLASS
3047 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3049 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3051 if (!(comma = split(arg)) ||
3052 !atoi_check16(comma, &new->class))
3053 ret_err(gen_err);
3055 new->tag.net = opt_string_alloc(set_prefix(arg));
3056 new->next = daemon->prefix_classes;
3057 daemon->prefix_classes = new;
3059 break;
3061 #endif
3064 case 'U': /* --dhcp-vendorclass */
3065 case 'j': /* --dhcp-userclass */
3066 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3067 case LOPT_REMOTE: /* --dhcp-remoteid */
3068 case LOPT_SUBSCR: /* --dhcp-subscrid */
3070 unsigned char *p;
3071 int dig = 0;
3072 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3074 if (!(comma = split(arg)))
3075 ret_err(gen_err);
3077 new->netid.net = opt_string_alloc(set_prefix(arg));
3078 /* check for hex string - must digits may include : must not have nothing else,
3079 only allowed for agent-options. */
3081 arg = comma;
3082 if ((comma = split(arg)))
3084 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3085 ret_err(gen_err);
3086 else
3087 new->enterprise = atoi(arg+11);
3089 else
3090 comma = arg;
3092 for (p = (unsigned char *)comma; *p; p++)
3093 if (isxdigit(*p))
3094 dig = 1;
3095 else if (*p != ':')
3096 break;
3097 unhide_metas(comma);
3098 if (option == 'U' || option == 'j' || *p || !dig)
3100 new->len = strlen(comma);
3101 new->data = opt_malloc(new->len);
3102 memcpy(new->data, comma, new->len);
3104 else
3106 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3107 new->data = opt_malloc(new->len);
3108 memcpy(new->data, comma, new->len);
3111 switch (option)
3113 case 'j':
3114 new->match_type = MATCH_USER;
3115 break;
3116 case 'U':
3117 new->match_type = MATCH_VENDOR;
3118 break;
3119 case LOPT_CIRCUIT:
3120 new->match_type = MATCH_CIRCUIT;
3121 break;
3122 case LOPT_REMOTE:
3123 new->match_type = MATCH_REMOTE;
3124 break;
3125 case LOPT_SUBSCR:
3126 new->match_type = MATCH_SUBSCRIBER;
3127 break;
3129 new->next = daemon->dhcp_vendors;
3130 daemon->dhcp_vendors = new;
3132 break;
3135 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3136 if (!arg)
3138 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3139 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3141 else
3143 comma = split(arg);
3144 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3145 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
3146 ret_err(_("invalid port number"));
3147 if (!comma)
3148 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3150 break;
3152 case 'J': /* --dhcp-ignore */
3153 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3154 case LOPT_BROADCAST: /* --dhcp-broadcast */
3155 case '3': /* --bootp-dynamic */
3156 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
3158 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
3159 struct dhcp_netid *list = NULL;
3160 if (option == 'J')
3162 new->next = daemon->dhcp_ignore;
3163 daemon->dhcp_ignore = new;
3165 else if (option == LOPT_BROADCAST)
3167 new->next = daemon->force_broadcast;
3168 daemon->force_broadcast = new;
3170 else if (option == '3')
3172 new->next = daemon->bootp_dynamic;
3173 daemon->bootp_dynamic = new;
3175 else if (option == LOPT_GEN_NAMES)
3177 new->next = daemon->dhcp_gen_names;
3178 daemon->dhcp_gen_names = new;
3180 else
3182 new->next = daemon->dhcp_ignore_names;
3183 daemon->dhcp_ignore_names = new;
3186 while (arg) {
3187 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3188 comma = split(arg);
3189 member->next = list;
3190 list = member;
3191 if (is_tag_prefix(arg))
3192 member->net = opt_string_alloc(arg+4);
3193 else
3194 member->net = opt_string_alloc(arg);
3195 arg = comma;
3198 new->list = list;
3199 break;
3202 case LOPT_PROXY: /* --dhcp-proxy */
3203 daemon->override = 1;
3204 while (arg) {
3205 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3206 comma = split(arg);
3207 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
3208 ret_err(_("bad dhcp-proxy address"));
3209 new->next = daemon->override_relays;
3210 daemon->override_relays = new;
3211 arg = comma;
3213 break;
3215 case LOPT_RELAY: /* --dhcp-relay */
3217 struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
3218 comma = split(arg);
3219 new->interface = opt_string_alloc(split(comma));
3220 new->iface_index = 0;
3221 if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
3223 new->next = daemon->relay4;
3224 daemon->relay4 = new;
3226 #ifdef HAVE_DHCP6
3227 else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
3229 new->next = daemon->relay6;
3230 daemon->relay6 = new;
3232 #endif
3233 else
3234 ret_err(_("Bad dhcp-relay"));
3236 break;
3239 #endif
3241 #ifdef HAVE_DHCP6
3242 case LOPT_RA_PARAM: /* --ra-param */
3243 if ((comma = split(arg)))
3245 struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
3246 new->lifetime = -1;
3247 new->prio = 0;
3248 new->name = opt_string_alloc(arg);
3249 if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
3251 if (*comma == 'l' || *comma == 'L')
3252 new->prio = 0x18;
3253 else
3254 new->prio = 0x08;
3255 comma = split(comma);
3257 arg = split(comma);
3258 if (!atoi_check(comma, &new->interval) ||
3259 (arg && !atoi_check(arg, &new->lifetime)))
3260 ret_err(_("bad RA-params"));
3262 new->next = daemon->ra_interfaces;
3263 daemon->ra_interfaces = new;
3265 break;
3267 case LOPT_DUID: /* --dhcp-duid */
3268 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
3269 ret_err(_("bad DUID"));
3270 else
3272 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3273 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3274 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3276 break;
3277 #endif
3279 case 'V': /* --alias */
3281 char *dash, *a[3] = { NULL, NULL, NULL };
3282 int k = 0;
3283 struct doctor *new = opt_malloc(sizeof(struct doctor));
3284 new->next = daemon->doctors;
3285 daemon->doctors = new;
3286 new->mask.s_addr = 0xffffffff;
3287 new->end.s_addr = 0;
3289 if ((a[0] = arg))
3290 for (k = 1; k < 3; k++)
3292 if (!(a[k] = split(a[k-1])))
3293 break;
3294 unhide_metas(a[k]);
3297 dash = split_chr(a[0], '-');
3299 if ((k < 2) ||
3300 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3301 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
3302 option = '?';
3304 if (k == 3)
3305 inet_pton(AF_INET, a[2], &new->mask);
3307 if (dash &&
3308 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
3309 !is_same_net(new->in, new->end, new->mask) ||
3310 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3311 ret_err(_("invalid alias range"));
3313 break;
3316 case LOPT_INTNAME: /* --interface-name */
3318 struct interface_name *new, **up;
3319 char *domain = NULL;
3321 comma = split(arg);
3323 if (!comma || !(domain = canonicalise_opt(arg)))
3324 ret_err(_("bad interface name"));
3326 new = opt_malloc(sizeof(struct interface_name));
3327 new->next = NULL;
3328 new->addr4 = NULL;
3329 #ifdef HAVE_IPV6
3330 new->addr6 = NULL;
3331 #endif
3332 /* Add to the end of the list, so that first name
3333 of an interface is used for PTR lookups. */
3334 for (up = &daemon->int_names; *up; up = &((*up)->next));
3335 *up = new;
3336 new->name = domain;
3337 new->intr = opt_string_alloc(comma);
3338 break;
3341 case LOPT_CNAME: /* --cname */
3343 struct cname *new;
3344 char *alias;
3345 char *target;
3347 if (!(comma = split(arg)))
3348 ret_err(gen_err);
3350 alias = canonicalise_opt(arg);
3351 target = canonicalise_opt(comma);
3353 if (!alias || !target)
3354 ret_err(_("bad CNAME"));
3355 else
3357 for (new = daemon->cnames; new; new = new->next)
3358 if (hostname_isequal(new->alias, arg))
3359 ret_err(_("duplicate CNAME"));
3360 new = opt_malloc(sizeof(struct cname));
3361 new->next = daemon->cnames;
3362 daemon->cnames = new;
3363 new->alias = alias;
3364 new->target = target;
3367 break;
3370 case LOPT_PTR: /* --ptr-record */
3372 struct ptr_record *new;
3373 char *dom, *target = NULL;
3375 comma = split(arg);
3377 if (!(dom = canonicalise_opt(arg)) ||
3378 (comma && !(target = canonicalise_opt(comma))))
3379 ret_err(_("bad PTR record"));
3380 else
3382 new = opt_malloc(sizeof(struct ptr_record));
3383 new->next = daemon->ptr;
3384 daemon->ptr = new;
3385 new->name = dom;
3386 new->ptr = target;
3388 break;
3391 case LOPT_NAPTR: /* --naptr-record */
3393 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3394 int k = 0;
3395 struct naptr *new;
3396 int order, pref;
3397 char *name, *replace = NULL;
3399 if ((a[0] = arg))
3400 for (k = 1; k < 7; k++)
3401 if (!(a[k] = split(a[k-1])))
3402 break;
3405 if (k < 6 ||
3406 !(name = canonicalise_opt(a[0])) ||
3407 !atoi_check16(a[1], &order) ||
3408 !atoi_check16(a[2], &pref) ||
3409 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3410 ret_err(_("bad NAPTR record"));
3411 else
3413 new = opt_malloc(sizeof(struct naptr));
3414 new->next = daemon->naptr;
3415 daemon->naptr = new;
3416 new->name = name;
3417 new->flags = opt_string_alloc(a[3]);
3418 new->services = opt_string_alloc(a[4]);
3419 new->regexp = opt_string_alloc(a[5]);
3420 new->replace = replace;
3421 new->order = order;
3422 new->pref = pref;
3424 break;
3427 case LOPT_RR: /* dns-rr */
3429 struct txt_record *new;
3430 size_t len;
3431 char *data;
3432 int val;
3434 comma = split(arg);
3435 data = split(comma);
3437 new = opt_malloc(sizeof(struct txt_record));
3438 new->next = daemon->rr;
3439 daemon->rr = new;
3441 if (!atoi_check(comma, &val) ||
3442 !(new->name = canonicalise_opt(arg)) ||
3443 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
3444 ret_err(_("bad RR record"));
3446 new->class = val;
3447 new->len = 0;
3449 if (data)
3451 new->txt=opt_malloc(len);
3452 new->len = len;
3453 memcpy(new->txt, data, len);
3456 break;
3459 case 'Y': /* --txt-record */
3461 struct txt_record *new;
3462 unsigned char *p, *cnt;
3463 size_t len;
3465 comma = split(arg);
3467 new = opt_malloc(sizeof(struct txt_record));
3468 new->next = daemon->txt;
3469 daemon->txt = new;
3470 new->class = C_IN;
3472 if (!(new->name = canonicalise_opt(arg)))
3473 ret_err(_("bad TXT record"));
3475 len = comma ? strlen(comma) : 0;
3476 len += (len/255) + 1; /* room for extra counts */
3477 new->txt = p = opt_malloc(len);
3479 cnt = p++;
3480 *cnt = 0;
3482 while (comma && *comma)
3484 unsigned char c = (unsigned char)*comma++;
3486 if (c == ',' || *cnt == 255)
3488 if (c != ',')
3489 comma--;
3490 cnt = p++;
3491 *cnt = 0;
3493 else
3495 *p++ = unhide_meta(c);
3496 (*cnt)++;
3500 new->len = p - new->txt;
3502 break;
3505 case 'W': /* --srv-host */
3507 int port = 1, priority = 0, weight = 0;
3508 char *name, *target = NULL;
3509 struct mx_srv_record *new;
3511 comma = split(arg);
3513 if (!(name = canonicalise_opt(arg)))
3514 ret_err(_("bad SRV record"));
3516 if (comma)
3518 arg = comma;
3519 comma = split(arg);
3520 if (!(target = canonicalise_opt(arg)))
3521 ret_err(_("bad SRV target"));
3523 if (comma)
3525 arg = comma;
3526 comma = split(arg);
3527 if (!atoi_check16(arg, &port))
3528 ret_err(_("invalid port number"));
3530 if (comma)
3532 arg = comma;
3533 comma = split(arg);
3534 if (!atoi_check16(arg, &priority))
3535 ret_err(_("invalid priority"));
3537 if (comma)
3539 arg = comma;
3540 comma = split(arg);
3541 if (!atoi_check16(arg, &weight))
3542 ret_err(_("invalid weight"));
3548 new = opt_malloc(sizeof(struct mx_srv_record));
3549 new->next = daemon->mxnames;
3550 daemon->mxnames = new;
3551 new->issrv = 1;
3552 new->name = name;
3553 new->target = target;
3554 new->srvport = port;
3555 new->priority = priority;
3556 new->weight = weight;
3557 break;
3560 case LOPT_HOST_REC: /* --host-record */
3562 struct host_record *new = opt_malloc(sizeof(struct host_record));
3563 memset(new, 0, sizeof(struct host_record));
3565 if (!arg || !(comma = split(arg)))
3566 ret_err(_("Bad host-record"));
3568 while (arg)
3570 struct all_addr addr;
3571 if (inet_pton(AF_INET, arg, &addr))
3572 new->addr = addr.addr.addr4;
3573 #ifdef HAVE_IPV6
3574 else if (inet_pton(AF_INET6, arg, &addr))
3575 new->addr6 = addr.addr.addr6;
3576 #endif
3577 else
3579 int nomem;
3580 char *canon = canonicalise(arg, &nomem);
3581 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3582 if (!canon)
3583 ret_err(_("Bad name in host-record"));
3585 nl->name = canon;
3586 /* keep order, so that PTR record goes to first name */
3587 nl->next = NULL;
3588 if (!new->names)
3589 new->names = nl;
3590 else
3592 struct name_list *tmp;
3593 for (tmp = new->names; tmp->next; tmp = tmp->next);
3594 tmp->next = nl;
3598 arg = comma;
3599 comma = split(arg);
3602 /* Keep list order */
3603 if (!daemon->host_records_tail)
3604 daemon->host_records = new;
3605 else
3606 daemon->host_records_tail->next = new;
3607 new->next = NULL;
3608 daemon->host_records_tail = new;
3609 break;
3612 default:
3613 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3617 return 1;
3620 static void read_file(char *file, FILE *f, int hard_opt)
3622 volatile int lineno = 0;
3623 char *buff = daemon->namebuff;
3625 while (fgets(buff, MAXDNAME, f))
3627 int white, i, option = hard_opt;
3628 char *errmess, *p, *arg = NULL, *start;
3629 size_t len;
3631 /* Memory allocation failure longjmps here if mem_recover == 1 */
3632 if (option != 0)
3634 if (setjmp(mem_jmp))
3635 continue;
3636 mem_recover = 1;
3639 lineno++;
3640 errmess = NULL;
3642 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3643 metacharacters get hidden also strip comments */
3644 for (white = 1, p = buff; *p; p++)
3646 if (*p == '"')
3648 memmove(p, p+1, strlen(p+1)+1);
3650 for(; *p && *p != '"'; p++)
3652 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3654 if (p[1] == 't')
3655 p[1] = '\t';
3656 else if (p[1] == 'n')
3657 p[1] = '\n';
3658 else if (p[1] == 'b')
3659 p[1] = '\b';
3660 else if (p[1] == 'r')
3661 p[1] = '\r';
3662 else if (p[1] == 'e') /* escape */
3663 p[1] = '\033';
3664 memmove(p, p+1, strlen(p+1)+1);
3666 *p = hide_meta(*p);
3669 if (*p == 0)
3671 errmess = _("missing \"");
3672 goto oops;
3675 memmove(p, p+1, strlen(p+1)+1);
3678 if (isspace(*p))
3680 *p = ' ';
3681 white = 1;
3683 else
3685 if (white && *p == '#')
3687 *p = 0;
3688 break;
3690 white = 0;
3695 /* strip leading spaces */
3696 for (start = buff; *start && *start == ' '; start++);
3698 /* strip trailing spaces */
3699 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3701 if (len == 0)
3702 continue;
3703 else
3704 start[len] = 0;
3706 if (option != 0)
3707 arg = start;
3708 else if ((p=strchr(start, '=')))
3710 /* allow spaces around "=" */
3711 for (arg = p+1; *arg == ' '; arg++);
3712 for (; p >= start && (*p == ' ' || *p == '='); p--)
3713 *p = 0;
3715 else
3716 arg = NULL;
3718 if (option == 0)
3720 for (option = 0, i = 0; opts[i].name; i++)
3721 if (strcmp(opts[i].name, start) == 0)
3723 option = opts[i].val;
3724 break;
3727 if (!option)
3728 errmess = _("bad option");
3729 else if (opts[i].has_arg == 0 && arg)
3730 errmess = _("extraneous parameter");
3731 else if (opts[i].has_arg == 1 && !arg)
3732 errmess = _("missing parameter");
3735 oops:
3736 if (errmess)
3737 strcpy(daemon->namebuff, errmess);
3739 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
3741 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
3742 if (hard_opt != 0)
3743 my_syslog(LOG_ERR, "%s", daemon->namebuff);
3744 else
3745 die("%s", daemon->namebuff, EC_BADCONF);
3749 mem_recover = 0;
3750 fclose(f);
3753 static int one_file(char *file, int hard_opt)
3755 FILE *f;
3756 int nofile_ok = 0;
3757 static int read_stdin = 0;
3758 static struct fileread {
3759 dev_t dev;
3760 ino_t ino;
3761 struct fileread *next;
3762 } *filesread = NULL;
3764 if (hard_opt == '7')
3766 /* default conf-file reading */
3767 hard_opt = 0;
3768 nofile_ok = 1;
3771 if (hard_opt == 0 && strcmp(file, "-") == 0)
3773 if (read_stdin == 1)
3774 return 1;
3775 read_stdin = 1;
3776 file = "stdin";
3777 f = stdin;
3779 else
3781 /* ignore repeated files. */
3782 struct stat statbuf;
3784 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3786 struct fileread *r;
3788 for (r = filesread; r; r = r->next)
3789 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3790 return 1;
3792 r = safe_malloc(sizeof(struct fileread));
3793 r->next = filesread;
3794 filesread = r;
3795 r->dev = statbuf.st_dev;
3796 r->ino = statbuf.st_ino;
3799 if (!(f = fopen(file, "r")))
3801 if (errno == ENOENT && nofile_ok)
3802 return 1; /* No conffile, all done. */
3803 else
3805 char *str = _("cannot read %s: %s");
3806 if (hard_opt != 0)
3808 my_syslog(LOG_ERR, str, file, strerror(errno));
3809 return 0;
3811 else
3812 die(str, file, EC_FILE);
3817 read_file(file, f, hard_opt);
3818 return 1;
3821 /* expand any name which is a directory */
3822 struct hostsfile *expand_filelist(struct hostsfile *list)
3824 int i;
3825 struct hostsfile *ah;
3827 for (i = 0, ah = list; ah; ah = ah->next)
3829 if (i <= ah->index)
3830 i = ah->index + 1;
3832 if (ah->flags & AH_DIR)
3833 ah->flags |= AH_INACTIVE;
3834 else
3835 ah->flags &= ~AH_INACTIVE;
3838 for (ah = list; ah; ah = ah->next)
3839 if (!(ah->flags & AH_INACTIVE))
3841 struct stat buf;
3842 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3844 DIR *dir_stream;
3845 struct dirent *ent;
3847 /* don't read this as a file */
3848 ah->flags |= AH_INACTIVE;
3850 if (!(dir_stream = opendir(ah->fname)))
3851 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3852 ah->fname, strerror(errno));
3853 else
3855 while ((ent = readdir(dir_stream)))
3857 size_t lendir = strlen(ah->fname);
3858 size_t lenfile = strlen(ent->d_name);
3859 struct hostsfile *ah1;
3860 char *path;
3862 /* ignore emacs backups and dotfiles */
3863 if (lenfile == 0 ||
3864 ent->d_name[lenfile - 1] == '~' ||
3865 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3866 ent->d_name[0] == '.')
3867 continue;
3869 /* see if we have an existing record.
3870 dir is ah->fname
3871 file is ent->d_name
3872 path to match is ah1->fname */
3874 for (ah1 = list; ah1; ah1 = ah1->next)
3876 if (lendir < strlen(ah1->fname) &&
3877 strstr(ah1->fname, ah->fname) == ah1->fname &&
3878 ah1->fname[lendir] == '/' &&
3879 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3881 ah1->flags &= ~AH_INACTIVE;
3882 break;
3886 /* make new record */
3887 if (!ah1)
3889 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3890 continue;
3892 if (!(path = whine_malloc(lendir + lenfile + 2)))
3894 free(ah1);
3895 continue;
3898 strcpy(path, ah->fname);
3899 strcat(path, "/");
3900 strcat(path, ent->d_name);
3901 ah1->fname = path;
3902 ah1->index = i++;
3903 ah1->flags = AH_DIR;
3904 ah1->next = list;
3905 list = ah1;
3908 /* inactivate record if not regular file */
3909 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3910 ah1->flags |= AH_INACTIVE;
3913 closedir(dir_stream);
3918 return list;
3922 #ifdef HAVE_DHCP
3923 void reread_dhcp(void)
3925 struct hostsfile *hf;
3927 if (daemon->dhcp_hosts_file)
3929 struct dhcp_config *configs, *cp, **up;
3931 /* remove existing... */
3932 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3934 cp = configs->next;
3936 if (configs->flags & CONFIG_BANK)
3938 struct hwaddr_config *mac, *tmp;
3939 struct dhcp_netid_list *list, *tmplist;
3941 for (mac = configs->hwaddr; mac; mac = tmp)
3943 tmp = mac->next;
3944 free(mac);
3947 if (configs->flags & CONFIG_CLID)
3948 free(configs->clid);
3950 for (list = configs->netid; list; list = tmplist)
3952 free(list->list);
3953 tmplist = list->next;
3954 free(list);
3957 if (configs->flags & CONFIG_NAME)
3958 free(configs->hostname);
3960 *up = configs->next;
3961 free(configs);
3963 else
3964 up = &configs->next;
3967 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3968 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3969 if (!(hf->flags & AH_INACTIVE))
3971 if (one_file(hf->fname, LOPT_BANK))
3972 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3976 if (daemon->dhcp_opts_file)
3978 struct dhcp_opt *opts, *cp, **up;
3979 struct dhcp_netid *id, *next;
3981 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3983 cp = opts->next;
3985 if (opts->flags & DHOPT_BANK)
3987 if ((opts->flags & DHOPT_VENDOR))
3988 free(opts->u.vendor_class);
3989 free(opts->val);
3990 for (id = opts->netid; id; id = next)
3992 next = id->next;
3993 free(id->net);
3994 free(id);
3996 *up = opts->next;
3997 free(opts);
3999 else
4000 up = &opts->next;
4003 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
4004 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
4005 if (!(hf->flags & AH_INACTIVE))
4007 if (one_file(hf->fname, LOPT_OPTS))
4008 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
4012 #endif
4014 void read_opts(int argc, char **argv, char *compile_opts)
4016 char *buff = opt_malloc(MAXDNAME);
4017 int option, conffile_opt = '7', testmode = 0;
4018 char *arg, *conffile = CONFFILE;
4020 opterr = 0;
4022 daemon = opt_malloc(sizeof(struct daemon));
4023 memset(daemon, 0, sizeof(struct daemon));
4024 daemon->namebuff = buff;
4026 /* Set defaults - everything else is zero or NULL */
4027 daemon->cachesize = CACHESIZ;
4028 daemon->ftabsize = FTABSIZ;
4029 daemon->port = NAMESERVER_PORT;
4030 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
4031 daemon->dhcp_server_port = DHCP_SERVER_PORT;
4032 daemon->default_resolv.is_default = 1;
4033 daemon->default_resolv.name = RESOLVFILE;
4034 daemon->resolv_files = &daemon->default_resolv;
4035 daemon->username = CHUSER;
4036 daemon->runfile = RUNFILE;
4037 daemon->dhcp_max = MAXLEASES;
4038 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
4039 daemon->edns_pktsz = EDNS_PKTSZ;
4040 daemon->log_fac = -1;
4041 daemon->auth_ttl = AUTH_TTL;
4042 daemon->soa_refresh = SOA_REFRESH;
4043 daemon->soa_retry = SOA_RETRY;
4044 daemon->soa_expiry = SOA_EXPIRY;
4045 add_txt("version.bind", "dnsmasq-" VERSION );
4046 add_txt("authors.bind", "Simon Kelley");
4047 add_txt("copyright.bind", COPYRIGHT);
4049 while (1)
4051 #ifdef HAVE_GETOPT_LONG
4052 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
4053 #else
4054 option = getopt(argc, argv, OPTSTRING);
4055 #endif
4057 if (option == -1)
4059 for (; optind < argc; optind++)
4061 unsigned char *c = (unsigned char *)argv[optind];
4062 for (; *c != 0; c++)
4063 if (!isspace(*c))
4064 die(_("junk found in command line"), NULL, EC_BADCONF);
4066 break;
4069 /* Copy optarg so that argv doesn't get changed */
4070 if (optarg)
4072 strncpy(buff, optarg, MAXDNAME);
4073 buff[MAXDNAME-1] = 0;
4074 arg = buff;
4076 else
4077 arg = NULL;
4079 /* command-line only stuff */
4080 if (option == LOPT_TEST)
4081 testmode = 1;
4082 else if (option == 'w')
4084 #ifdef HAVE_DHCP
4085 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
4086 display_opts();
4087 #ifdef HAVE_DHCP6
4088 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4089 display_opts6();
4090 #endif
4091 else
4092 #endif
4093 do_usage();
4095 exit(0);
4097 else if (option == 'v')
4099 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
4100 printf(_("Compile time options: %s\n\n"), compile_opts);
4101 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4102 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
4103 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
4104 exit(0);
4106 else if (option == 'C')
4108 conffile_opt = 0; /* file must exist */
4109 conffile = opt_string_alloc(arg);
4111 else
4113 #ifdef HAVE_GETOPT_LONG
4114 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
4115 #else
4116 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
4117 #endif
4118 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
4122 if (conffile)
4123 one_file(conffile, conffile_opt);
4125 /* port might not be known when the address is parsed - fill in here */
4126 if (daemon->servers)
4128 struct server *tmp;
4129 for (tmp = daemon->servers; tmp; tmp = tmp->next)
4130 if (!(tmp->flags & SERV_HAS_SOURCE))
4132 if (tmp->source_addr.sa.sa_family == AF_INET)
4133 tmp->source_addr.in.sin_port = htons(daemon->query_port);
4134 #ifdef HAVE_IPV6
4135 else if (tmp->source_addr.sa.sa_family == AF_INET6)
4136 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
4137 #endif
4141 if (daemon->if_addrs)
4143 struct iname *tmp;
4144 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
4145 if (tmp->addr.sa.sa_family == AF_INET)
4146 tmp->addr.in.sin_port = htons(daemon->port);
4147 #ifdef HAVE_IPV6
4148 else if (tmp->addr.sa.sa_family == AF_INET6)
4149 tmp->addr.in6.sin6_port = htons(daemon->port);
4150 #endif /* IPv6 */
4153 /* create default, if not specified */
4154 if (daemon->authserver && !daemon->hostmaster)
4156 strcpy(buff, "hostmaster.");
4157 strcat(buff, daemon->authserver);
4158 daemon->hostmaster = opt_string_alloc(buff);
4161 /* only one of these need be specified: the other defaults to the host-name */
4162 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
4164 struct mx_srv_record *mx;
4166 if (gethostname(buff, MAXDNAME) == -1)
4167 die(_("cannot get host-name: %s"), NULL, EC_MISC);
4169 for (mx = daemon->mxnames; mx; mx = mx->next)
4170 if (!mx->issrv && hostname_isequal(mx->name, buff))
4171 break;
4173 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
4175 mx = opt_malloc(sizeof(struct mx_srv_record));
4176 mx->next = daemon->mxnames;
4177 mx->issrv = 0;
4178 mx->target = NULL;
4179 mx->name = opt_string_alloc(buff);
4180 daemon->mxnames = mx;
4183 if (!daemon->mxtarget)
4184 daemon->mxtarget = opt_string_alloc(buff);
4186 for (mx = daemon->mxnames; mx; mx = mx->next)
4187 if (!mx->issrv && !mx->target)
4188 mx->target = daemon->mxtarget;
4191 if (!option_bool(OPT_NO_RESOLV) &&
4192 daemon->resolv_files &&
4193 daemon->resolv_files->next &&
4194 option_bool(OPT_NO_POLL))
4195 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
4197 if (option_bool(OPT_RESOLV_DOMAIN))
4199 char *line;
4200 FILE *f;
4202 if (option_bool(OPT_NO_RESOLV) ||
4203 !daemon->resolv_files ||
4204 (daemon->resolv_files)->next)
4205 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
4207 if (!(f = fopen((daemon->resolv_files)->name, "r")))
4208 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
4210 while ((line = fgets(buff, MAXDNAME, f)))
4212 char *token = strtok(line, " \t\n\r");
4214 if (!token || strcmp(token, "search") != 0)
4215 continue;
4217 if ((token = strtok(NULL, " \t\n\r")) &&
4218 (daemon->domain_suffix = canonicalise_opt(token)))
4219 break;
4222 fclose(f);
4224 if (!daemon->domain_suffix)
4225 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
4228 if (daemon->domain_suffix)
4230 /* add domain for any srv record without one. */
4231 struct mx_srv_record *srv;
4233 for (srv = daemon->mxnames; srv; srv = srv->next)
4234 if (srv->issrv &&
4235 strchr(srv->name, '.') &&
4236 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4238 strcpy(buff, srv->name);
4239 strcat(buff, ".");
4240 strcat(buff, daemon->domain_suffix);
4241 free(srv->name);
4242 srv->name = opt_string_alloc(buff);
4245 else if (option_bool(OPT_DHCP_FQDN))
4246 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
4248 if (testmode)
4250 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4251 exit(0);