dnsmasq v2.67 final release + Tomato tweaks
[tomato.git] / release / src / router / dnsmasq / src / option.c
blob0ba266436ba581edb5316ecc3ba9e2d6c3a179b3
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 char *prefstr;
1866 arg = split(comma);
1867 prefstr = split(arg);
1869 if (inet_pton(AF_INET, comma, &new->start))
1871 new->is6 = 0;
1872 if (!arg)
1873 new->end.s_addr = new->start.s_addr;
1874 else if (!inet_pton(AF_INET, arg, &new->end))
1875 ret_err(gen_err);
1877 #ifdef HAVE_IPV6
1878 else if (inet_pton(AF_INET6, comma, &new->start6))
1880 new->is6 = 1;
1881 if (!arg)
1882 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1883 else if (!inet_pton(AF_INET6, arg, &new->end6))
1884 ret_err(gen_err);
1886 #endif
1887 else
1888 ret_err(gen_err);
1890 if (option != 's' && prefstr)
1892 if (!(new->prefix = canonicalise_opt(prefstr)) ||
1893 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
1894 ret_err(_("bad prefix"));
1898 new->domain = d;
1899 if (option == 's')
1901 new->next = daemon->cond_domain;
1902 daemon->cond_domain = new;
1904 else
1906 new->next = daemon->synth_domains;
1907 daemon->synth_domains = new;
1910 else if (option == 's')
1911 daemon->domain_suffix = d;
1912 else
1913 ret_err(gen_err);
1916 break;
1918 case 'u': /* --user */
1919 daemon->username = opt_string_alloc(arg);
1920 break;
1922 case 'g': /* --group */
1923 daemon->groupname = opt_string_alloc(arg);
1924 daemon->group_set = 1;
1925 break;
1927 #ifdef HAVE_DHCP
1928 case LOPT_SCRIPTUSR: /* --scriptuser */
1929 daemon->scriptuser = opt_string_alloc(arg);
1930 break;
1931 #endif
1933 case 'i': /* --interface */
1934 do {
1935 struct iname *new = opt_malloc(sizeof(struct iname));
1936 comma = split(arg);
1937 new->next = daemon->if_names;
1938 daemon->if_names = new;
1939 /* new->name may be NULL if someone does
1940 "interface=" to disable all interfaces except loop. */
1941 new->name = opt_string_alloc(arg);
1942 new->used = 0;
1943 arg = comma;
1944 } while (arg);
1945 break;
1947 case LOPT_TFTP: /* --enable-tftp */
1948 set_option_bool(OPT_TFTP);
1949 if (!arg)
1950 break;
1951 /* fall through */
1953 case 'I': /* --except-interface */
1954 case '2': /* --no-dhcp-interface */
1955 do {
1956 struct iname *new = opt_malloc(sizeof(struct iname));
1957 comma = split(arg);
1958 new->name = opt_string_alloc(arg);
1959 if (option == 'I')
1961 new->next = daemon->if_except;
1962 daemon->if_except = new;
1964 else if (option == LOPT_TFTP)
1966 new->next = daemon->tftp_interfaces;
1967 daemon->tftp_interfaces = new;
1969 else
1971 new->next = daemon->dhcp_except;
1972 daemon->dhcp_except = new;
1974 arg = comma;
1975 } while (arg);
1976 break;
1978 case 'B': /* --bogus-nxdomain */
1980 struct in_addr addr;
1981 unhide_metas(arg);
1982 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
1984 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1985 baddr->next = daemon->bogus_addr;
1986 daemon->bogus_addr = baddr;
1987 baddr->addr = addr;
1989 else
1990 ret_err(gen_err); /* error */
1991 break;
1994 case 'a': /* --listen-address */
1995 case LOPT_AUTHPEER: /* --auth-peer */
1996 do {
1997 struct iname *new = opt_malloc(sizeof(struct iname));
1998 comma = split(arg);
1999 unhide_metas(arg);
2000 if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
2002 new->addr.sa.sa_family = AF_INET;
2003 new->addr.in.sin_port = 0;
2004 #ifdef HAVE_SOCKADDR_SA_LEN
2005 new->addr.in.sin_len = sizeof(new->addr.in);
2006 #endif
2008 #ifdef HAVE_IPV6
2009 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
2011 new->addr.sa.sa_family = AF_INET6;
2012 new->addr.in6.sin6_flowinfo = 0;
2013 new->addr.in6.sin6_scope_id = 0;
2014 new->addr.in6.sin6_port = 0;
2015 #ifdef HAVE_SOCKADDR_SA_LEN
2016 new->addr.in6.sin6_len = sizeof(new->addr.in6);
2017 #endif
2019 #endif
2020 else
2021 ret_err(gen_err);
2023 new->used = 0;
2024 if (option == 'a')
2026 new->next = daemon->if_addrs;
2027 daemon->if_addrs = new;
2029 else
2031 new->next = daemon->auth_peers;
2032 daemon->auth_peers = new;
2034 arg = comma;
2035 } while (arg);
2036 break;
2038 case 'S': /* --server */
2039 case LOPT_LOCAL: /* --local */
2040 case 'A': /* --address */
2041 case LOPT_NO_REBIND: /* --rebind-domain-ok */
2043 struct server *serv, *newlist = NULL;
2045 unhide_metas(arg);
2047 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
2049 int rebind = !(*arg == '/');
2050 char *end = NULL;
2051 if (!rebind)
2052 arg++;
2053 while (rebind || (end = split_chr(arg, '/')))
2055 char *domain = NULL;
2056 /* elide leading dots - they are implied in the search algorithm */
2057 while (*arg == '.') arg++;
2058 /* # matches everything and becomes a zero length domain string */
2059 if (strcmp(arg, "#") == 0)
2060 domain = "";
2061 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
2062 option = '?';
2063 serv = opt_malloc(sizeof(struct server));
2064 memset(serv, 0, sizeof(struct server));
2065 serv->next = newlist;
2066 newlist = serv;
2067 serv->domain = domain;
2068 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
2069 arg = end;
2070 if (rebind)
2071 break;
2073 if (!newlist)
2074 ret_err(gen_err);
2076 else
2078 newlist = opt_malloc(sizeof(struct server));
2079 memset(newlist, 0, sizeof(struct server));
2082 if (option == 'A')
2084 newlist->flags |= SERV_LITERAL_ADDRESS;
2085 if (!(newlist->flags & SERV_TYPE))
2086 ret_err(gen_err);
2088 else if (option == LOPT_NO_REBIND)
2089 newlist->flags |= SERV_NO_REBIND;
2091 if (!arg || !*arg)
2093 if (!(newlist->flags & SERV_NO_REBIND))
2094 newlist->flags |= SERV_NO_ADDR; /* no server */
2095 if (newlist->flags & SERV_LITERAL_ADDRESS)
2096 ret_err(gen_err);
2099 else if (strcmp(arg, "#") == 0)
2101 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
2102 if (newlist->flags & SERV_LITERAL_ADDRESS)
2103 ret_err(gen_err);
2105 else
2107 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2108 if (err)
2109 ret_err(err);
2112 serv = newlist;
2113 while (serv->next)
2115 serv->next->flags = serv->flags;
2116 serv->next->addr = serv->addr;
2117 serv->next->source_addr = serv->source_addr;
2118 strcpy(serv->next->interface, serv->interface);
2119 serv = serv->next;
2121 serv->next = daemon->servers;
2122 daemon->servers = newlist;
2123 break;
2126 case LOPT_IPSET: /* --ipset */
2127 #ifndef HAVE_IPSET
2128 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2129 break;
2130 #else
2132 struct ipsets ipsets_head;
2133 struct ipsets *ipsets = &ipsets_head;
2134 int size;
2135 char *end;
2136 char **sets, **sets_pos;
2137 memset(ipsets, 0, sizeof(struct ipsets));
2138 unhide_metas(arg);
2139 if (arg && *arg == '/')
2141 arg++;
2142 while ((end = split_chr(arg, '/')))
2144 char *domain = NULL;
2145 /* elide leading dots - they are implied in the search algorithm */
2146 while (*arg == '.')
2147 arg++;
2148 /* # matches everything and becomes a zero length domain string */
2149 if (strcmp(arg, "#") == 0 || !*arg)
2150 domain = "";
2151 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2152 option = '?';
2153 ipsets->next = opt_malloc(sizeof(struct ipsets));
2154 ipsets = ipsets->next;
2155 memset(ipsets, 0, sizeof(struct ipsets));
2156 ipsets->domain = domain;
2157 arg = end;
2160 else
2162 ipsets->next = opt_malloc(sizeof(struct ipsets));
2163 ipsets = ipsets->next;
2164 memset(ipsets, 0, sizeof(struct ipsets));
2165 ipsets->domain = "";
2167 if (!arg || !*arg)
2169 option = '?';
2170 break;
2172 size = 2;
2173 for (end = arg; *end; ++end)
2174 if (*end == ',')
2175 ++size;
2177 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2179 do {
2180 end = split(arg);
2181 *sets_pos++ = opt_string_alloc(arg);
2182 arg = end;
2183 } while (end);
2184 *sets_pos = 0;
2185 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2186 ipsets->next->sets = sets;
2187 ipsets->next = daemon->ipsets;
2188 daemon->ipsets = ipsets_head.next;
2190 break;
2192 #endif
2194 case 'c': /* --cache-size */
2196 int size;
2198 if (!atoi_check(arg, &size))
2199 ret_err(gen_err);
2200 else
2202 /* zero is OK, and means no caching. */
2204 if (size < 0)
2205 size = 0;
2206 else if (size > 10000)
2207 size = 10000;
2209 daemon->cachesize = size;
2211 break;
2214 case 'p': /* --port */
2215 if (!atoi_check16(arg, &daemon->port))
2216 ret_err(gen_err);
2217 break;
2219 case LOPT_MINPORT: /* --min-port */
2220 if (!atoi_check16(arg, &daemon->min_port))
2221 ret_err(gen_err);
2222 break;
2224 case '0': /* --dns-forward-max */
2225 if (!atoi_check(arg, &daemon->ftabsize))
2226 ret_err(gen_err);
2227 break;
2229 case LOPT_MAX_LOGS: /* --log-async */
2230 daemon->max_logs = LOG_MAX; /* default */
2231 if (arg && !atoi_check(arg, &daemon->max_logs))
2232 ret_err(gen_err);
2233 else if (daemon->max_logs > 100)
2234 daemon->max_logs = 100;
2235 break;
2237 case 'P': /* --edns-packet-max */
2239 int i;
2240 if (!atoi_check(arg, &i))
2241 ret_err(gen_err);
2242 daemon->edns_pktsz = (unsigned short)i;
2243 break;
2246 case 'Q': /* --query-port */
2247 if (!atoi_check16(arg, &daemon->query_port))
2248 ret_err(gen_err);
2249 /* if explicitly set to zero, use single OS ephemeral port
2250 and disable random ports */
2251 if (daemon->query_port == 0)
2252 daemon->osport = 1;
2253 break;
2255 case 'T': /* --local-ttl */
2256 case LOPT_NEGTTL: /* --neg-ttl */
2257 case LOPT_MAXTTL: /* --max-ttl */
2258 case LOPT_MAXCTTL: /* --max-cache-ttl */
2259 case LOPT_AUTHTTL: /* --auth-ttl */
2261 int ttl;
2262 if (!atoi_check(arg, &ttl))
2263 ret_err(gen_err);
2264 else if (option == LOPT_NEGTTL)
2265 daemon->neg_ttl = (unsigned long)ttl;
2266 else if (option == LOPT_MAXTTL)
2267 daemon->max_ttl = (unsigned long)ttl;
2268 else if (option == LOPT_MAXCTTL)
2269 daemon->max_cache_ttl = (unsigned long)ttl;
2270 else if (option == LOPT_AUTHTTL)
2271 daemon->auth_ttl = (unsigned long)ttl;
2272 else
2273 daemon->local_ttl = (unsigned long)ttl;
2274 break;
2277 #ifdef HAVE_DHCP
2278 case 'X': /* --dhcp-lease-max */
2279 if (!atoi_check(arg, &daemon->dhcp_max))
2280 ret_err(gen_err);
2281 break;
2282 #endif
2284 #ifdef HAVE_TFTP
2285 case LOPT_TFTP_MAX: /* --tftp-max */
2286 if (!atoi_check(arg, &daemon->tftp_max))
2287 ret_err(gen_err);
2288 break;
2290 case LOPT_PREFIX: /* --tftp-prefix */
2291 comma = split(arg);
2292 if (comma)
2294 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2295 new->interface = opt_string_alloc(comma);
2296 new->prefix = opt_string_alloc(arg);
2297 new->next = daemon->if_prefix;
2298 daemon->if_prefix = new;
2300 else
2301 daemon->tftp_prefix = opt_string_alloc(arg);
2302 break;
2304 case LOPT_TFTPPORTS: /* --tftp-port-range */
2305 if (!(comma = split(arg)) ||
2306 !atoi_check16(arg, &daemon->start_tftp_port) ||
2307 !atoi_check16(comma, &daemon->end_tftp_port))
2308 ret_err(_("bad port range"));
2310 if (daemon->start_tftp_port > daemon->end_tftp_port)
2312 int tmp = daemon->start_tftp_port;
2313 daemon->start_tftp_port = daemon->end_tftp_port;
2314 daemon->end_tftp_port = tmp;
2317 break;
2318 #endif
2320 case LOPT_BRIDGE: /* --bridge-interface */
2322 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2323 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2324 ret_err(_("bad bridge-interface"));
2326 strcpy(new->iface, arg);
2327 new->alias = NULL;
2328 new->next = daemon->bridges;
2329 daemon->bridges = new;
2331 do {
2332 arg = comma;
2333 comma = split(arg);
2334 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2336 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2337 b->next = new->alias;
2338 new->alias = b;
2339 strcpy(b->iface, arg);
2341 } while (comma);
2343 break;
2346 #ifdef HAVE_DHCP
2347 case 'F': /* --dhcp-range */
2349 int k, leasepos = 2;
2350 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2351 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2353 memset (new, 0, sizeof(*new));
2354 new->lease_time = DEFLEASE;
2356 if (!arg)
2358 option = '?';
2359 break;
2362 while(1)
2364 for (cp = arg; *cp; cp++)
2365 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2366 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2367 (*cp >='0' && *cp <= '9')))
2368 break;
2370 if (*cp != ',' && (comma = split(arg)))
2372 if (is_tag_prefix(arg))
2374 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2375 tt->net = opt_string_alloc(arg+4);
2376 tt->next = new->filter;
2377 /* ignore empty tag */
2378 if (tt->net)
2379 new->filter = tt;
2381 else
2383 if (new->netid.net)
2384 ret_err(_("only one tag allowed"));
2385 else if (strstr(arg, "set:") == arg)
2386 new->netid.net = opt_string_alloc(arg+4);
2387 else
2388 new->netid.net = opt_string_alloc(arg);
2390 arg = comma;
2392 else
2394 a[0] = arg;
2395 break;
2399 for (k = 1; k < 8; k++)
2400 if (!(a[k] = split(a[k-1])))
2401 break;
2403 if (k < 2)
2404 ret_err(_("bad dhcp-range"));
2406 if (inet_pton(AF_INET, a[0], &new->start))
2408 new->next = daemon->dhcp;
2409 daemon->dhcp = new;
2410 new->end = new->start;
2411 if (strcmp(a[1], "static") == 0)
2412 new->flags |= CONTEXT_STATIC;
2413 else if (strcmp(a[1], "proxy") == 0)
2414 new->flags |= CONTEXT_PROXY;
2415 else if (!inet_pton(AF_INET, a[1], &new->end))
2416 ret_err(_("bad dhcp-range"));
2418 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2420 struct in_addr tmp = new->start;
2421 new->start = new->end;
2422 new->end = tmp;
2425 if (k >= 3 && strchr(a[2], '.') &&
2426 (inet_pton(AF_INET, a[2], &new->netmask) > 0))
2428 new->flags |= CONTEXT_NETMASK;
2429 leasepos = 3;
2430 if (!is_same_net(new->start, new->end, new->netmask))
2431 ret_err(_("inconsistent DHCP range"));
2434 if (k >= 4 && strchr(a[3], '.') &&
2435 (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
2437 new->flags |= CONTEXT_BRDCAST;
2438 leasepos = 4;
2441 #ifdef HAVE_DHCP6
2442 else if (inet_pton(AF_INET6, a[0], &new->start6))
2444 new->flags |= CONTEXT_V6;
2445 new->prefix = 64; /* default */
2446 new->end6 = new->start6;
2447 new->next = daemon->dhcp6;
2448 daemon->dhcp6 = new;
2450 for (leasepos = 1; leasepos < k; leasepos++)
2452 if (strcmp(a[leasepos], "static") == 0)
2453 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2454 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2455 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
2456 else if (strcmp(a[leasepos], "ra-names") == 0)
2457 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
2458 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2459 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
2460 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2461 new->flags |= CONTEXT_DHCP;
2462 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2464 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2465 new->flags |= CONTEXT_TEMPLATE;
2467 else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
2469 new->template_interface = opt_string_alloc(a[leasepos] + 19);
2470 new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
2472 else
2473 break;
2476 /* bare integer < 128 is prefix value */
2477 if (leasepos < k)
2479 int pref;
2480 for (cp = a[leasepos]; *cp; cp++)
2481 if (!(*cp >= '0' && *cp <= '9'))
2482 break;
2483 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
2485 new->prefix = pref;
2486 leasepos++;
2490 if (new->prefix != 64)
2492 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2493 ret_err(_("prefix length must be exactly 64 for RA subnets"));
2494 else if (new->flags & CONTEXT_TEMPLATE)
2495 ret_err(_("prefix length must be exactly 64 for subnet constructors"));
2498 if (new->prefix < 64)
2499 ret_err(_("prefix length must be at least 64"));
2501 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2502 ret_err(_("inconsistent DHCPv6 range"));
2504 /* dhcp-range=:: enables DHCP stateless on any interface */
2505 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
2506 new->prefix = 0;
2508 if (new->flags & CONTEXT_TEMPLATE)
2510 struct in6_addr zero;
2511 memset(&zero, 0, sizeof(zero));
2512 if (!is_same_net6(&zero, &new->start6, new->prefix))
2513 ret_err(_("prefix must be zero with \"constructor:\" argument"));
2516 if (addr6part(&new->start6) > addr6part(&new->end6))
2518 struct in6_addr tmp = new->start6;
2519 new->start6 = new->end6;
2520 new->end6 = tmp;
2523 #endif
2524 else
2525 ret_err(_("bad dhcp-range"));
2527 if (leasepos < k)
2529 if (strcmp(a[leasepos], "infinite") == 0)
2530 new->lease_time = 0xffffffff;
2531 else if (strcmp(a[leasepos], "deprecated") == 0)
2532 new->flags |= CONTEXT_DEPRECATE;
2533 else
2535 int fac = 1;
2536 if (strlen(a[leasepos]) > 0)
2538 switch (a[leasepos][strlen(a[leasepos]) - 1])
2540 case 'w':
2541 case 'W':
2542 fac *= 7;
2543 /* fall through */
2544 case 'd':
2545 case 'D':
2546 fac *= 24;
2547 /* fall though */
2548 case 'h':
2549 case 'H':
2550 fac *= 60;
2551 /* fall through */
2552 case 'm':
2553 case 'M':
2554 fac *= 60;
2555 /* fall through */
2556 case 's':
2557 case 'S':
2558 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2561 for (cp = a[leasepos]; *cp; cp++)
2562 if (!(*cp >= '0' && *cp <= '9'))
2563 break;
2565 if (*cp || (leasepos+1 < k))
2566 ret_err(_("bad dhcp-range"));
2568 new->lease_time = atoi(a[leasepos]) * fac;
2569 /* Leases of a minute or less confuse
2570 some clients, notably Apple's */
2571 if (new->lease_time < 120)
2572 new->lease_time = 120;
2576 break;
2579 case LOPT_BANK:
2580 case 'G': /* --dhcp-host */
2582 int j, k = 0;
2583 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2584 struct dhcp_config *new;
2585 struct in_addr in;
2587 new = opt_malloc(sizeof(struct dhcp_config));
2589 new->next = daemon->dhcp_conf;
2590 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2591 new->hwaddr = NULL;
2592 new->netid = NULL;
2594 if ((a[0] = arg))
2595 for (k = 1; k < 7; k++)
2596 if (!(a[k] = split(a[k-1])))
2597 break;
2599 for (j = 0; j < k; j++)
2600 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2602 char *arg = a[j];
2604 if ((arg[0] == 'i' || arg[0] == 'I') &&
2605 (arg[1] == 'd' || arg[1] == 'D') &&
2606 arg[2] == ':')
2608 if (arg[3] == '*')
2609 new->flags |= CONFIG_NOCLID;
2610 else
2612 int len;
2613 arg += 3; /* dump id: */
2614 if (strchr(arg, ':'))
2615 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2616 else
2618 unhide_metas(arg);
2619 len = (int) strlen(arg);
2622 if (len == -1)
2624 ret_err(_("bad hex constant"));
2625 else if ((new->clid = opt_malloc(len)))
2627 new->flags |= CONFIG_CLID;
2628 new->clid_len = len;
2629 memcpy(new->clid, arg, len);
2633 /* dhcp-host has strange backwards-compat needs. */
2634 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2636 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2637 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2638 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2639 newlist->next = new->netid;
2640 new->netid = newlist;
2641 newlist->list = newtag;
2642 strcpy(newtag->net, arg+4);
2643 unhide_metas(newtag->net);
2645 else if (strstr(arg, "tag:") == arg)
2646 ret_err(_("cannot match tags in --dhcp-host"));
2647 #ifdef HAVE_DHCP6
2648 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2650 arg[strlen(arg)-1] = 0;
2651 arg++;
2653 if (!inet_pton(AF_INET6, arg, &new->addr6))
2654 ret_err(_("bad IPv6 address"));
2656 for (i= 0; i < 8; i++)
2657 if (new->addr6.s6_addr[i] != 0)
2658 break;
2660 /* set WILDCARD if network part all zeros */
2661 if (i == 8)
2662 new->flags |= CONFIG_WILDCARD;
2664 new->flags |= CONFIG_ADDR6;
2666 #endif
2667 else
2669 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2670 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2671 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2672 ret_err(_("bad hex constant"));
2673 else
2676 newhw->next = new->hwaddr;
2677 new->hwaddr = newhw;
2681 else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
2683 struct dhcp_config *configs;
2685 new->addr = in;
2686 new->flags |= CONFIG_ADDR;
2688 /* If the same IP appears in more than one host config, then DISCOVER
2689 for one of the hosts will get the address, but REQUEST will be NAKed,
2690 since the address is reserved by the other one -> protocol loop. */
2691 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2692 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2694 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2695 return 0;
2698 else
2700 char *cp, *lastp = NULL, last = 0;
2701 int fac = 1;
2703 if (strlen(a[j]) > 1)
2705 lastp = a[j] + strlen(a[j]) - 1;
2706 last = *lastp;
2707 switch (last)
2709 case 'w':
2710 case 'W':
2711 fac *= 7;
2712 /* fall through */
2713 case 'd':
2714 case 'D':
2715 fac *= 24;
2716 /* fall through */
2717 case 'h':
2718 case 'H':
2719 fac *= 60;
2720 /* fall through */
2721 case 'm':
2722 case 'M':
2723 fac *= 60;
2724 /* fall through */
2725 case 's':
2726 case 'S':
2727 *lastp = 0;
2731 for (cp = a[j]; *cp; cp++)
2732 if (!isdigit((unsigned char)*cp) && *cp != ' ')
2733 break;
2735 if (*cp)
2737 if (lastp)
2738 *lastp = last;
2739 if (strcmp(a[j], "infinite") == 0)
2741 new->lease_time = 0xffffffff;
2742 new->flags |= CONFIG_TIME;
2744 else if (strcmp(a[j], "ignore") == 0)
2745 new->flags |= CONFIG_DISABLE;
2746 else
2748 if (!(new->hostname = canonicalise_opt(a[j])) ||
2749 !legal_hostname(new->hostname))
2750 ret_err(_("bad DHCP host name"));
2752 new->flags |= CONFIG_NAME;
2753 new->domain = strip_hostname(new->hostname);
2756 else
2758 new->lease_time = atoi(a[j]) * fac;
2759 /* Leases of a minute or less confuse
2760 some clients, notably Apple's */
2761 if (new->lease_time < 120)
2762 new->lease_time = 120;
2763 new->flags |= CONFIG_TIME;
2767 daemon->dhcp_conf = new;
2768 break;
2771 case LOPT_TAG_IF: /* --tag-if */
2773 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2775 new->tag = NULL;
2776 new->set = NULL;
2777 new->next = NULL;
2779 /* preserve order */
2780 if (!daemon->tag_if)
2781 daemon->tag_if = new;
2782 else
2784 struct tag_if *tmp;
2785 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2786 tmp->next = new;
2789 while (arg)
2791 size_t len;
2793 comma = split(arg);
2794 len = strlen(arg);
2796 if (len < 5)
2798 new->set = NULL;
2799 break;
2801 else
2803 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2804 newtag->net = opt_malloc(len - 3);
2805 strcpy(newtag->net, arg+4);
2806 unhide_metas(newtag->net);
2808 if (strstr(arg, "set:") == arg)
2810 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2811 newlist->next = new->set;
2812 new->set = newlist;
2813 newlist->list = newtag;
2815 else if (strstr(arg, "tag:") == arg)
2817 newtag->next = new->tag;
2818 new->tag = newtag;
2820 else
2822 new->set = NULL;
2823 free(newtag);
2824 break;
2828 arg = comma;
2831 if (!new->set)
2832 ret_err(_("bad tag-if"));
2834 break;
2838 case 'O': /* --dhcp-option */
2839 case LOPT_FORCE: /* --dhcp-option-force */
2840 case LOPT_OPTS:
2841 case LOPT_MATCH: /* --dhcp-match */
2842 return parse_dhcp_opt(errstr, arg,
2843 option == LOPT_FORCE ? DHOPT_FORCE :
2844 (option == LOPT_MATCH ? DHOPT_MATCH :
2845 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2847 case 'M': /* --dhcp-boot */
2849 struct dhcp_netid *id = NULL;
2850 while (is_tag_prefix(arg))
2852 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2853 newid->next = id;
2854 id = newid;
2855 comma = split(arg);
2856 newid->net = opt_string_alloc(arg+4);
2857 arg = comma;
2860 if (!arg)
2861 ret_err(gen_err);
2862 else
2864 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2865 struct in_addr dhcp_next_server;
2866 struct dhcp_boot *new;
2867 comma = split(arg);
2868 dhcp_file = opt_string_alloc(arg);
2869 dhcp_next_server.s_addr = 0;
2870 if (comma)
2872 arg = comma;
2873 comma = split(arg);
2874 dhcp_sname = opt_string_alloc(arg);
2875 if (comma)
2877 unhide_metas(comma);
2878 if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
2881 * The user may have specified the tftp hostname here.
2882 * save it so that it can be resolved/looked up during
2883 * actual dhcp_reply().
2886 tftp_sname = opt_string_alloc(comma);
2887 dhcp_next_server.s_addr = 0;
2892 new = opt_malloc(sizeof(struct dhcp_boot));
2893 new->file = dhcp_file;
2894 new->sname = dhcp_sname;
2895 new->tftp_sname = tftp_sname;
2896 new->next_server = dhcp_next_server;
2897 new->netid = id;
2898 new->next = daemon->boot_config;
2899 daemon->boot_config = new;
2902 break;
2905 case LOPT_PXE_PROMT: /* --pxe-prompt */
2907 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2908 int timeout;
2910 new->netid = NULL;
2911 new->opt = 10; /* PXE_MENU_PROMPT */
2913 while (is_tag_prefix(arg))
2915 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2916 comma = split(arg);
2917 nn->next = new->netid;
2918 new->netid = nn;
2919 nn->net = opt_string_alloc(arg+4);
2920 arg = comma;
2923 if (!arg)
2924 ret_err(gen_err);
2925 else
2927 comma = split(arg);
2928 unhide_metas(arg);
2929 new->len = strlen(arg) + 1;
2930 new->val = opt_malloc(new->len);
2931 memcpy(new->val + 1, arg, new->len - 1);
2933 new->u.vendor_class = (unsigned char *)"PXEClient";
2934 new->flags = DHOPT_VENDOR;
2936 if (comma && atoi_check(comma, &timeout))
2937 *(new->val) = timeout;
2938 else
2939 *(new->val) = 255;
2941 new->next = daemon->dhcp_opts;
2942 daemon->dhcp_opts = new;
2943 daemon->enable_pxe = 1;
2946 break;
2949 case LOPT_PXE_SERV: /* --pxe-service */
2951 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2952 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2953 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2954 static int boottype = 32768;
2956 new->netid = NULL;
2957 new->sname = NULL;
2958 new->server.s_addr = 0;
2960 while (is_tag_prefix(arg))
2962 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2963 comma = split(arg);
2964 nn->next = new->netid;
2965 new->netid = nn;
2966 nn->net = opt_string_alloc(arg+4);
2967 arg = comma;
2970 if (arg && (comma = split(arg)))
2972 for (i = 0; CSA[i]; i++)
2973 if (strcasecmp(CSA[i], arg) == 0)
2974 break;
2976 if (CSA[i] || atoi_check(arg, &i))
2978 arg = comma;
2979 comma = split(arg);
2981 new->CSA = i;
2982 new->menu = opt_string_alloc(arg);
2984 if (!comma)
2986 new->type = 0; /* local boot */
2987 new->basename = NULL;
2989 else
2991 arg = comma;
2992 comma = split(arg);
2993 if (atoi_check(arg, &i))
2995 new->type = i;
2996 new->basename = NULL;
2998 else
3000 new->type = boottype++;
3001 new->basename = opt_string_alloc(arg);
3004 if (comma)
3006 if (!inet_pton(AF_INET, comma, &new->server))
3008 new->server.s_addr = 0;
3009 new->sname = opt_string_alloc(comma);
3015 /* Order matters */
3016 new->next = NULL;
3017 if (!daemon->pxe_services)
3018 daemon->pxe_services = new;
3019 else
3021 struct pxe_service *s;
3022 for (s = daemon->pxe_services; s->next; s = s->next);
3023 s->next = new;
3026 daemon->enable_pxe = 1;
3027 break;
3032 ret_err(gen_err);
3035 case '4': /* --dhcp-mac */
3037 if (!(comma = split(arg)))
3038 ret_err(gen_err);
3039 else
3041 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
3042 new->netid.net = opt_string_alloc(set_prefix(arg));
3043 unhide_metas(comma);
3044 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
3045 if (new->hwaddr_len == -1)
3046 ret_err(gen_err);
3047 else
3049 new->next = daemon->dhcp_macs;
3050 daemon->dhcp_macs = new;
3054 break;
3056 #ifdef OPTION6_PREFIX_CLASS
3057 case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
3059 struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
3061 if (!(comma = split(arg)) ||
3062 !atoi_check16(comma, &new->class))
3063 ret_err(gen_err);
3065 new->tag.net = opt_string_alloc(set_prefix(arg));
3066 new->next = daemon->prefix_classes;
3067 daemon->prefix_classes = new;
3069 break;
3071 #endif
3074 case 'U': /* --dhcp-vendorclass */
3075 case 'j': /* --dhcp-userclass */
3076 case LOPT_CIRCUIT: /* --dhcp-circuitid */
3077 case LOPT_REMOTE: /* --dhcp-remoteid */
3078 case LOPT_SUBSCR: /* --dhcp-subscrid */
3080 unsigned char *p;
3081 int dig = 0;
3082 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
3084 if (!(comma = split(arg)))
3085 ret_err(gen_err);
3087 new->netid.net = opt_string_alloc(set_prefix(arg));
3088 /* check for hex string - must digits may include : must not have nothing else,
3089 only allowed for agent-options. */
3091 arg = comma;
3092 if ((comma = split(arg)))
3094 if (option != 'U' || strstr(arg, "enterprise:") != arg)
3095 ret_err(gen_err);
3096 else
3097 new->enterprise = atoi(arg+11);
3099 else
3100 comma = arg;
3102 for (p = (unsigned char *)comma; *p; p++)
3103 if (isxdigit(*p))
3104 dig = 1;
3105 else if (*p != ':')
3106 break;
3107 unhide_metas(comma);
3108 if (option == 'U' || option == 'j' || *p || !dig)
3110 new->len = strlen(comma);
3111 new->data = opt_malloc(new->len);
3112 memcpy(new->data, comma, new->len);
3114 else
3116 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
3117 new->data = opt_malloc(new->len);
3118 memcpy(new->data, comma, new->len);
3121 switch (option)
3123 case 'j':
3124 new->match_type = MATCH_USER;
3125 break;
3126 case 'U':
3127 new->match_type = MATCH_VENDOR;
3128 break;
3129 case LOPT_CIRCUIT:
3130 new->match_type = MATCH_CIRCUIT;
3131 break;
3132 case LOPT_REMOTE:
3133 new->match_type = MATCH_REMOTE;
3134 break;
3135 case LOPT_SUBSCR:
3136 new->match_type = MATCH_SUBSCRIBER;
3137 break;
3139 new->next = daemon->dhcp_vendors;
3140 daemon->dhcp_vendors = new;
3142 break;
3145 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3146 if (!arg)
3148 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3149 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3151 else
3153 comma = split(arg);
3154 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3155 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
3156 ret_err(_("invalid port number"));
3157 if (!comma)
3158 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3160 break;
3162 case 'J': /* --dhcp-ignore */
3163 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3164 case LOPT_BROADCAST: /* --dhcp-broadcast */
3165 case '3': /* --bootp-dynamic */
3166 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
3168 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
3169 struct dhcp_netid *list = NULL;
3170 if (option == 'J')
3172 new->next = daemon->dhcp_ignore;
3173 daemon->dhcp_ignore = new;
3175 else if (option == LOPT_BROADCAST)
3177 new->next = daemon->force_broadcast;
3178 daemon->force_broadcast = new;
3180 else if (option == '3')
3182 new->next = daemon->bootp_dynamic;
3183 daemon->bootp_dynamic = new;
3185 else if (option == LOPT_GEN_NAMES)
3187 new->next = daemon->dhcp_gen_names;
3188 daemon->dhcp_gen_names = new;
3190 else
3192 new->next = daemon->dhcp_ignore_names;
3193 daemon->dhcp_ignore_names = new;
3196 while (arg) {
3197 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3198 comma = split(arg);
3199 member->next = list;
3200 list = member;
3201 if (is_tag_prefix(arg))
3202 member->net = opt_string_alloc(arg+4);
3203 else
3204 member->net = opt_string_alloc(arg);
3205 arg = comma;
3208 new->list = list;
3209 break;
3212 case LOPT_PROXY: /* --dhcp-proxy */
3213 daemon->override = 1;
3214 while (arg) {
3215 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3216 comma = split(arg);
3217 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
3218 ret_err(_("bad dhcp-proxy address"));
3219 new->next = daemon->override_relays;
3220 daemon->override_relays = new;
3221 arg = comma;
3223 break;
3225 case LOPT_RELAY: /* --dhcp-relay */
3227 struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
3228 comma = split(arg);
3229 new->interface = opt_string_alloc(split(comma));
3230 new->iface_index = 0;
3231 if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
3233 new->next = daemon->relay4;
3234 daemon->relay4 = new;
3236 #ifdef HAVE_DHCP6
3237 else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
3239 new->next = daemon->relay6;
3240 daemon->relay6 = new;
3242 #endif
3243 else
3244 ret_err(_("Bad dhcp-relay"));
3246 break;
3249 #endif
3251 #ifdef HAVE_DHCP6
3252 case LOPT_RA_PARAM: /* --ra-param */
3253 if ((comma = split(arg)))
3255 struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
3256 new->lifetime = -1;
3257 new->prio = 0;
3258 new->name = opt_string_alloc(arg);
3259 if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
3261 if (*comma == 'l' || *comma == 'L')
3262 new->prio = 0x18;
3263 else
3264 new->prio = 0x08;
3265 comma = split(comma);
3267 arg = split(comma);
3268 if (!atoi_check(comma, &new->interval) ||
3269 (arg && !atoi_check(arg, &new->lifetime)))
3270 ret_err(_("bad RA-params"));
3272 new->next = daemon->ra_interfaces;
3273 daemon->ra_interfaces = new;
3275 break;
3277 case LOPT_DUID: /* --dhcp-duid */
3278 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
3279 ret_err(_("bad DUID"));
3280 else
3282 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3283 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3284 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3286 break;
3287 #endif
3289 case 'V': /* --alias */
3291 char *dash, *a[3] = { NULL, NULL, NULL };
3292 int k = 0;
3293 struct doctor *new = opt_malloc(sizeof(struct doctor));
3294 new->next = daemon->doctors;
3295 daemon->doctors = new;
3296 new->mask.s_addr = 0xffffffff;
3297 new->end.s_addr = 0;
3299 if ((a[0] = arg))
3300 for (k = 1; k < 3; k++)
3302 if (!(a[k] = split(a[k-1])))
3303 break;
3304 unhide_metas(a[k]);
3307 dash = split_chr(a[0], '-');
3309 if ((k < 2) ||
3310 (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
3311 (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
3312 option = '?';
3314 if (k == 3)
3315 inet_pton(AF_INET, a[2], &new->mask);
3317 if (dash &&
3318 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
3319 !is_same_net(new->in, new->end, new->mask) ||
3320 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3321 ret_err(_("invalid alias range"));
3323 break;
3326 case LOPT_INTNAME: /* --interface-name */
3328 struct interface_name *new, **up;
3329 char *domain = NULL;
3331 comma = split(arg);
3333 if (!comma || !(domain = canonicalise_opt(arg)))
3334 ret_err(_("bad interface name"));
3336 new = opt_malloc(sizeof(struct interface_name));
3337 new->next = NULL;
3338 new->addr4 = NULL;
3339 #ifdef HAVE_IPV6
3340 new->addr6 = NULL;
3341 #endif
3342 /* Add to the end of the list, so that first name
3343 of an interface is used for PTR lookups. */
3344 for (up = &daemon->int_names; *up; up = &((*up)->next));
3345 *up = new;
3346 new->name = domain;
3347 new->intr = opt_string_alloc(comma);
3348 break;
3351 case LOPT_CNAME: /* --cname */
3353 struct cname *new;
3354 char *alias;
3355 char *target;
3357 if (!(comma = split(arg)))
3358 ret_err(gen_err);
3360 alias = canonicalise_opt(arg);
3361 target = canonicalise_opt(comma);
3363 if (!alias || !target)
3364 ret_err(_("bad CNAME"));
3365 else
3367 for (new = daemon->cnames; new; new = new->next)
3368 if (hostname_isequal(new->alias, arg))
3369 ret_err(_("duplicate CNAME"));
3370 new = opt_malloc(sizeof(struct cname));
3371 new->next = daemon->cnames;
3372 daemon->cnames = new;
3373 new->alias = alias;
3374 new->target = target;
3377 break;
3380 case LOPT_PTR: /* --ptr-record */
3382 struct ptr_record *new;
3383 char *dom, *target = NULL;
3385 comma = split(arg);
3387 if (!(dom = canonicalise_opt(arg)) ||
3388 (comma && !(target = canonicalise_opt(comma))))
3389 ret_err(_("bad PTR record"));
3390 else
3392 new = opt_malloc(sizeof(struct ptr_record));
3393 new->next = daemon->ptr;
3394 daemon->ptr = new;
3395 new->name = dom;
3396 new->ptr = target;
3398 break;
3401 case LOPT_NAPTR: /* --naptr-record */
3403 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3404 int k = 0;
3405 struct naptr *new;
3406 int order, pref;
3407 char *name, *replace = NULL;
3409 if ((a[0] = arg))
3410 for (k = 1; k < 7; k++)
3411 if (!(a[k] = split(a[k-1])))
3412 break;
3415 if (k < 6 ||
3416 !(name = canonicalise_opt(a[0])) ||
3417 !atoi_check16(a[1], &order) ||
3418 !atoi_check16(a[2], &pref) ||
3419 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3420 ret_err(_("bad NAPTR record"));
3421 else
3423 new = opt_malloc(sizeof(struct naptr));
3424 new->next = daemon->naptr;
3425 daemon->naptr = new;
3426 new->name = name;
3427 new->flags = opt_string_alloc(a[3]);
3428 new->services = opt_string_alloc(a[4]);
3429 new->regexp = opt_string_alloc(a[5]);
3430 new->replace = replace;
3431 new->order = order;
3432 new->pref = pref;
3434 break;
3437 case LOPT_RR: /* dns-rr */
3439 struct txt_record *new;
3440 size_t len;
3441 char *data;
3442 int val;
3444 comma = split(arg);
3445 data = split(comma);
3447 new = opt_malloc(sizeof(struct txt_record));
3448 new->next = daemon->rr;
3449 daemon->rr = new;
3451 if (!atoi_check(comma, &val) ||
3452 !(new->name = canonicalise_opt(arg)) ||
3453 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
3454 ret_err(_("bad RR record"));
3456 new->class = val;
3457 new->len = 0;
3459 if (data)
3461 new->txt=opt_malloc(len);
3462 new->len = len;
3463 memcpy(new->txt, data, len);
3466 break;
3469 case 'Y': /* --txt-record */
3471 struct txt_record *new;
3472 unsigned char *p, *cnt;
3473 size_t len;
3475 comma = split(arg);
3477 new = opt_malloc(sizeof(struct txt_record));
3478 new->next = daemon->txt;
3479 daemon->txt = new;
3480 new->class = C_IN;
3482 if (!(new->name = canonicalise_opt(arg)))
3483 ret_err(_("bad TXT record"));
3485 len = comma ? strlen(comma) : 0;
3486 len += (len/255) + 1; /* room for extra counts */
3487 new->txt = p = opt_malloc(len);
3489 cnt = p++;
3490 *cnt = 0;
3492 while (comma && *comma)
3494 unsigned char c = (unsigned char)*comma++;
3496 if (c == ',' || *cnt == 255)
3498 if (c != ',')
3499 comma--;
3500 cnt = p++;
3501 *cnt = 0;
3503 else
3505 *p++ = unhide_meta(c);
3506 (*cnt)++;
3510 new->len = p - new->txt;
3512 break;
3515 case 'W': /* --srv-host */
3517 int port = 1, priority = 0, weight = 0;
3518 char *name, *target = NULL;
3519 struct mx_srv_record *new;
3521 comma = split(arg);
3523 if (!(name = canonicalise_opt(arg)))
3524 ret_err(_("bad SRV record"));
3526 if (comma)
3528 arg = comma;
3529 comma = split(arg);
3530 if (!(target = canonicalise_opt(arg)))
3531 ret_err(_("bad SRV target"));
3533 if (comma)
3535 arg = comma;
3536 comma = split(arg);
3537 if (!atoi_check16(arg, &port))
3538 ret_err(_("invalid port number"));
3540 if (comma)
3542 arg = comma;
3543 comma = split(arg);
3544 if (!atoi_check16(arg, &priority))
3545 ret_err(_("invalid priority"));
3547 if (comma)
3549 arg = comma;
3550 comma = split(arg);
3551 if (!atoi_check16(arg, &weight))
3552 ret_err(_("invalid weight"));
3558 new = opt_malloc(sizeof(struct mx_srv_record));
3559 new->next = daemon->mxnames;
3560 daemon->mxnames = new;
3561 new->issrv = 1;
3562 new->name = name;
3563 new->target = target;
3564 new->srvport = port;
3565 new->priority = priority;
3566 new->weight = weight;
3567 break;
3570 case LOPT_HOST_REC: /* --host-record */
3572 struct host_record *new = opt_malloc(sizeof(struct host_record));
3573 memset(new, 0, sizeof(struct host_record));
3575 if (!arg || !(comma = split(arg)))
3576 ret_err(_("Bad host-record"));
3578 while (arg)
3580 struct all_addr addr;
3581 if (inet_pton(AF_INET, arg, &addr))
3582 new->addr = addr.addr.addr4;
3583 #ifdef HAVE_IPV6
3584 else if (inet_pton(AF_INET6, arg, &addr))
3585 new->addr6 = addr.addr.addr6;
3586 #endif
3587 else
3589 int nomem;
3590 char *canon = canonicalise(arg, &nomem);
3591 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3592 if (!canon)
3593 ret_err(_("Bad name in host-record"));
3595 nl->name = canon;
3596 /* keep order, so that PTR record goes to first name */
3597 nl->next = NULL;
3598 if (!new->names)
3599 new->names = nl;
3600 else
3602 struct name_list *tmp;
3603 for (tmp = new->names; tmp->next; tmp = tmp->next);
3604 tmp->next = nl;
3608 arg = comma;
3609 comma = split(arg);
3612 /* Keep list order */
3613 if (!daemon->host_records_tail)
3614 daemon->host_records = new;
3615 else
3616 daemon->host_records_tail->next = new;
3617 new->next = NULL;
3618 daemon->host_records_tail = new;
3619 break;
3622 default:
3623 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3627 return 1;
3630 static void read_file(char *file, FILE *f, int hard_opt)
3632 volatile int lineno = 0;
3633 char *buff = daemon->namebuff;
3635 while (fgets(buff, MAXDNAME, f))
3637 int white, i, option = hard_opt;
3638 char *errmess, *p, *arg = NULL, *start;
3639 size_t len;
3641 /* Memory allocation failure longjmps here if mem_recover == 1 */
3642 if (option != 0)
3644 if (setjmp(mem_jmp))
3645 continue;
3646 mem_recover = 1;
3649 lineno++;
3650 errmess = NULL;
3652 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3653 metacharacters get hidden also strip comments */
3654 for (white = 1, p = buff; *p; p++)
3656 if (*p == '"')
3658 memmove(p, p+1, strlen(p+1)+1);
3660 for(; *p && *p != '"'; p++)
3662 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3664 if (p[1] == 't')
3665 p[1] = '\t';
3666 else if (p[1] == 'n')
3667 p[1] = '\n';
3668 else if (p[1] == 'b')
3669 p[1] = '\b';
3670 else if (p[1] == 'r')
3671 p[1] = '\r';
3672 else if (p[1] == 'e') /* escape */
3673 p[1] = '\033';
3674 memmove(p, p+1, strlen(p+1)+1);
3676 *p = hide_meta(*p);
3679 if (*p == 0)
3681 errmess = _("missing \"");
3682 goto oops;
3685 memmove(p, p+1, strlen(p+1)+1);
3688 if (isspace(*p))
3690 *p = ' ';
3691 white = 1;
3693 else
3695 if (white && *p == '#')
3697 *p = 0;
3698 break;
3700 white = 0;
3705 /* strip leading spaces */
3706 for (start = buff; *start && *start == ' '; start++);
3708 /* strip trailing spaces */
3709 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3711 if (len == 0)
3712 continue;
3713 else
3714 start[len] = 0;
3716 if (option != 0)
3717 arg = start;
3718 else if ((p=strchr(start, '=')))
3720 /* allow spaces around "=" */
3721 for (arg = p+1; *arg == ' '; arg++);
3722 for (; p >= start && (*p == ' ' || *p == '='); p--)
3723 *p = 0;
3725 else
3726 arg = NULL;
3728 if (option == 0)
3730 for (option = 0, i = 0; opts[i].name; i++)
3731 if (strcmp(opts[i].name, start) == 0)
3733 option = opts[i].val;
3734 break;
3737 if (!option)
3738 errmess = _("bad option");
3739 else if (opts[i].has_arg == 0 && arg)
3740 errmess = _("extraneous parameter");
3741 else if (opts[i].has_arg == 1 && !arg)
3742 errmess = _("missing parameter");
3745 oops:
3746 if (errmess)
3747 strcpy(daemon->namebuff, errmess);
3749 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
3751 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
3752 if (hard_opt != 0)
3753 my_syslog(LOG_ERR, "%s", daemon->namebuff);
3754 else
3755 die("%s", daemon->namebuff, EC_BADCONF);
3759 mem_recover = 0;
3760 fclose(f);
3763 static int one_file(char *file, int hard_opt)
3765 FILE *f;
3766 int nofile_ok = 0;
3767 static int read_stdin = 0;
3768 static struct fileread {
3769 dev_t dev;
3770 ino_t ino;
3771 struct fileread *next;
3772 } *filesread = NULL;
3774 if (hard_opt == '7')
3776 /* default conf-file reading */
3777 hard_opt = 0;
3778 nofile_ok = 1;
3781 if (hard_opt == 0 && strcmp(file, "-") == 0)
3783 if (read_stdin == 1)
3784 return 1;
3785 read_stdin = 1;
3786 file = "stdin";
3787 f = stdin;
3789 else
3791 /* ignore repeated files. */
3792 struct stat statbuf;
3794 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3796 struct fileread *r;
3798 for (r = filesread; r; r = r->next)
3799 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3800 return 1;
3802 r = safe_malloc(sizeof(struct fileread));
3803 r->next = filesread;
3804 filesread = r;
3805 r->dev = statbuf.st_dev;
3806 r->ino = statbuf.st_ino;
3809 if (!(f = fopen(file, "r")))
3811 if (errno == ENOENT && nofile_ok)
3812 return 1; /* No conffile, all done. */
3813 else
3815 char *str = _("cannot read %s: %s");
3816 if (hard_opt != 0)
3818 my_syslog(LOG_ERR, str, file, strerror(errno));
3819 return 0;
3821 else
3822 die(str, file, EC_FILE);
3827 read_file(file, f, hard_opt);
3828 return 1;
3831 /* expand any name which is a directory */
3832 struct hostsfile *expand_filelist(struct hostsfile *list)
3834 int i;
3835 struct hostsfile *ah;
3837 for (i = 0, ah = list; ah; ah = ah->next)
3839 if (i <= ah->index)
3840 i = ah->index + 1;
3842 if (ah->flags & AH_DIR)
3843 ah->flags |= AH_INACTIVE;
3844 else
3845 ah->flags &= ~AH_INACTIVE;
3848 for (ah = list; ah; ah = ah->next)
3849 if (!(ah->flags & AH_INACTIVE))
3851 struct stat buf;
3852 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3854 DIR *dir_stream;
3855 struct dirent *ent;
3857 /* don't read this as a file */
3858 ah->flags |= AH_INACTIVE;
3860 if (!(dir_stream = opendir(ah->fname)))
3861 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3862 ah->fname, strerror(errno));
3863 else
3865 while ((ent = readdir(dir_stream)))
3867 size_t lendir = strlen(ah->fname);
3868 size_t lenfile = strlen(ent->d_name);
3869 struct hostsfile *ah1;
3870 char *path;
3872 /* ignore emacs backups and dotfiles */
3873 if (lenfile == 0 ||
3874 ent->d_name[lenfile - 1] == '~' ||
3875 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3876 ent->d_name[0] == '.')
3877 continue;
3879 /* see if we have an existing record.
3880 dir is ah->fname
3881 file is ent->d_name
3882 path to match is ah1->fname */
3884 for (ah1 = list; ah1; ah1 = ah1->next)
3886 if (lendir < strlen(ah1->fname) &&
3887 strstr(ah1->fname, ah->fname) == ah1->fname &&
3888 ah1->fname[lendir] == '/' &&
3889 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3891 ah1->flags &= ~AH_INACTIVE;
3892 break;
3896 /* make new record */
3897 if (!ah1)
3899 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3900 continue;
3902 if (!(path = whine_malloc(lendir + lenfile + 2)))
3904 free(ah1);
3905 continue;
3908 strcpy(path, ah->fname);
3909 strcat(path, "/");
3910 strcat(path, ent->d_name);
3911 ah1->fname = path;
3912 ah1->index = i++;
3913 ah1->flags = AH_DIR;
3914 ah1->next = list;
3915 list = ah1;
3918 /* inactivate record if not regular file */
3919 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3920 ah1->flags |= AH_INACTIVE;
3923 closedir(dir_stream);
3928 return list;
3932 #ifdef HAVE_DHCP
3933 void reread_dhcp(void)
3935 struct hostsfile *hf;
3937 if (daemon->dhcp_hosts_file)
3939 struct dhcp_config *configs, *cp, **up;
3941 /* remove existing... */
3942 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3944 cp = configs->next;
3946 if (configs->flags & CONFIG_BANK)
3948 struct hwaddr_config *mac, *tmp;
3949 struct dhcp_netid_list *list, *tmplist;
3951 for (mac = configs->hwaddr; mac; mac = tmp)
3953 tmp = mac->next;
3954 free(mac);
3957 if (configs->flags & CONFIG_CLID)
3958 free(configs->clid);
3960 for (list = configs->netid; list; list = tmplist)
3962 free(list->list);
3963 tmplist = list->next;
3964 free(list);
3967 if (configs->flags & CONFIG_NAME)
3968 free(configs->hostname);
3970 *up = configs->next;
3971 free(configs);
3973 else
3974 up = &configs->next;
3977 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3978 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3979 if (!(hf->flags & AH_INACTIVE))
3981 if (one_file(hf->fname, LOPT_BANK))
3982 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3986 if (daemon->dhcp_opts_file)
3988 struct dhcp_opt *opts, *cp, **up;
3989 struct dhcp_netid *id, *next;
3991 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3993 cp = opts->next;
3995 if (opts->flags & DHOPT_BANK)
3997 if ((opts->flags & DHOPT_VENDOR))
3998 free(opts->u.vendor_class);
3999 free(opts->val);
4000 for (id = opts->netid; id; id = next)
4002 next = id->next;
4003 free(id->net);
4004 free(id);
4006 *up = opts->next;
4007 free(opts);
4009 else
4010 up = &opts->next;
4013 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
4014 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
4015 if (!(hf->flags & AH_INACTIVE))
4017 if (one_file(hf->fname, LOPT_OPTS))
4018 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
4022 #endif
4024 void read_opts(int argc, char **argv, char *compile_opts)
4026 char *buff = opt_malloc(MAXDNAME);
4027 int option, conffile_opt = '7', testmode = 0;
4028 char *arg, *conffile = CONFFILE;
4030 opterr = 0;
4032 daemon = opt_malloc(sizeof(struct daemon));
4033 memset(daemon, 0, sizeof(struct daemon));
4034 daemon->namebuff = buff;
4036 /* Set defaults - everything else is zero or NULL */
4037 daemon->cachesize = CACHESIZ;
4038 daemon->ftabsize = FTABSIZ;
4039 daemon->port = NAMESERVER_PORT;
4040 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
4041 daemon->dhcp_server_port = DHCP_SERVER_PORT;
4042 daemon->default_resolv.is_default = 1;
4043 daemon->default_resolv.name = RESOLVFILE;
4044 daemon->resolv_files = &daemon->default_resolv;
4045 daemon->username = CHUSER;
4046 daemon->runfile = RUNFILE;
4047 daemon->dhcp_max = MAXLEASES;
4048 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
4049 daemon->edns_pktsz = EDNS_PKTSZ;
4050 daemon->log_fac = -1;
4051 daemon->auth_ttl = AUTH_TTL;
4052 daemon->soa_refresh = SOA_REFRESH;
4053 daemon->soa_retry = SOA_RETRY;
4054 daemon->soa_expiry = SOA_EXPIRY;
4055 add_txt("version.bind", "dnsmasq-" VERSION );
4056 add_txt("authors.bind", "Simon Kelley");
4057 add_txt("copyright.bind", COPYRIGHT);
4059 while (1)
4061 #ifdef HAVE_GETOPT_LONG
4062 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
4063 #else
4064 option = getopt(argc, argv, OPTSTRING);
4065 #endif
4067 if (option == -1)
4069 for (; optind < argc; optind++)
4071 unsigned char *c = (unsigned char *)argv[optind];
4072 for (; *c != 0; c++)
4073 if (!isspace(*c))
4074 die(_("junk found in command line"), NULL, EC_BADCONF);
4076 break;
4079 /* Copy optarg so that argv doesn't get changed */
4080 if (optarg)
4082 strncpy(buff, optarg, MAXDNAME);
4083 buff[MAXDNAME-1] = 0;
4084 arg = buff;
4086 else
4087 arg = NULL;
4089 /* command-line only stuff */
4090 if (option == LOPT_TEST)
4091 testmode = 1;
4092 else if (option == 'w')
4094 #ifdef HAVE_DHCP
4095 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
4096 display_opts();
4097 #ifdef HAVE_DHCP6
4098 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
4099 display_opts6();
4100 #endif
4101 else
4102 #endif
4103 do_usage();
4105 exit(0);
4107 else if (option == 'v')
4109 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
4110 printf(_("Compile time options: %s\n\n"), compile_opts);
4111 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
4112 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
4113 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
4114 exit(0);
4116 else if (option == 'C')
4118 conffile_opt = 0; /* file must exist */
4119 conffile = opt_string_alloc(arg);
4121 else
4123 #ifdef HAVE_GETOPT_LONG
4124 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
4125 #else
4126 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
4127 #endif
4128 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
4132 if (conffile)
4133 one_file(conffile, conffile_opt);
4135 /* port might not be known when the address is parsed - fill in here */
4136 if (daemon->servers)
4138 struct server *tmp;
4139 for (tmp = daemon->servers; tmp; tmp = tmp->next)
4140 if (!(tmp->flags & SERV_HAS_SOURCE))
4142 if (tmp->source_addr.sa.sa_family == AF_INET)
4143 tmp->source_addr.in.sin_port = htons(daemon->query_port);
4144 #ifdef HAVE_IPV6
4145 else if (tmp->source_addr.sa.sa_family == AF_INET6)
4146 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
4147 #endif
4151 if (daemon->if_addrs)
4153 struct iname *tmp;
4154 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
4155 if (tmp->addr.sa.sa_family == AF_INET)
4156 tmp->addr.in.sin_port = htons(daemon->port);
4157 #ifdef HAVE_IPV6
4158 else if (tmp->addr.sa.sa_family == AF_INET6)
4159 tmp->addr.in6.sin6_port = htons(daemon->port);
4160 #endif /* IPv6 */
4163 /* create default, if not specified */
4164 if (daemon->authserver && !daemon->hostmaster)
4166 strcpy(buff, "hostmaster.");
4167 strcat(buff, daemon->authserver);
4168 daemon->hostmaster = opt_string_alloc(buff);
4171 /* only one of these need be specified: the other defaults to the host-name */
4172 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
4174 struct mx_srv_record *mx;
4176 if (gethostname(buff, MAXDNAME) == -1)
4177 die(_("cannot get host-name: %s"), NULL, EC_MISC);
4179 for (mx = daemon->mxnames; mx; mx = mx->next)
4180 if (!mx->issrv && hostname_isequal(mx->name, buff))
4181 break;
4183 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
4185 mx = opt_malloc(sizeof(struct mx_srv_record));
4186 mx->next = daemon->mxnames;
4187 mx->issrv = 0;
4188 mx->target = NULL;
4189 mx->name = opt_string_alloc(buff);
4190 daemon->mxnames = mx;
4193 if (!daemon->mxtarget)
4194 daemon->mxtarget = opt_string_alloc(buff);
4196 for (mx = daemon->mxnames; mx; mx = mx->next)
4197 if (!mx->issrv && !mx->target)
4198 mx->target = daemon->mxtarget;
4201 if (!option_bool(OPT_NO_RESOLV) &&
4202 daemon->resolv_files &&
4203 daemon->resolv_files->next &&
4204 option_bool(OPT_NO_POLL))
4205 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
4207 if (option_bool(OPT_RESOLV_DOMAIN))
4209 char *line;
4210 FILE *f;
4212 if (option_bool(OPT_NO_RESOLV) ||
4213 !daemon->resolv_files ||
4214 (daemon->resolv_files)->next)
4215 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
4217 if (!(f = fopen((daemon->resolv_files)->name, "r")))
4218 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
4220 while ((line = fgets(buff, MAXDNAME, f)))
4222 char *token = strtok(line, " \t\n\r");
4224 if (!token || strcmp(token, "search") != 0)
4225 continue;
4227 if ((token = strtok(NULL, " \t\n\r")) &&
4228 (daemon->domain_suffix = canonicalise_opt(token)))
4229 break;
4232 fclose(f);
4234 if (!daemon->domain_suffix)
4235 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
4238 if (daemon->domain_suffix)
4240 /* add domain for any srv record without one. */
4241 struct mx_srv_record *srv;
4243 for (srv = daemon->mxnames; srv; srv = srv->next)
4244 if (srv->issrv &&
4245 strchr(srv->name, '.') &&
4246 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4248 strcpy(buff, srv->name);
4249 strcat(buff, ".");
4250 strcat(buff, daemon->domain_suffix);
4251 free(srv->name);
4252 srv->name = opt_string_alloc(buff);
4255 else if (option_bool(OPT_DHCP_FQDN))
4256 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
4258 if (testmode)
4260 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4261 exit(0);