]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/option.c
Add --ipset option.
[people/ms/dnsmasq.git] / src / option.c
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
2
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.
7
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.
12
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/>.
15 */
16
17 /* define this to get facilitynames */
18 #define SYSLOG_NAMES
19 #include "dnsmasq.h"
20 #include <setjmp.h>
21
22 static volatile int mem_recover = 0;
23 static jmp_buf mem_jmp;
24 static int one_file(char *file, int hard_opt);
25
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 }
52 };
53 #endif
54
55 #ifndef HAVE_GETOPT_LONG
56 struct myoption {
57 const char *name;
58 int has_arg;
59 int *flag;
60 int val;
61 };
62 #endif
63
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:"
65
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
132 #ifdef HAVE_GETOPT_LONG
133 static const struct option opts[] =
134 #else
135 static const struct myoption opts[] =
136 #endif
137 {
138 { "version", 0, 0, 'v' },
139 { "no-hosts", 0, 0, 'h' },
140 { "no-poll", 0, 0, 'n' },
141 { "help", 0, 0, 'w' },
142 { "no-daemon", 0, 0, 'd' },
143 { "log-queries", 0, 0, 'q' },
144 { "user", 2, 0, 'u' },
145 { "group", 2, 0, 'g' },
146 { "resolv-file", 2, 0, 'r' },
147 { "mx-host", 1, 0, 'm' },
148 { "mx-target", 1, 0, 't' },
149 { "cache-size", 2, 0, 'c' },
150 { "port", 1, 0, 'p' },
151 { "dhcp-leasefile", 2, 0, 'l' },
152 { "dhcp-lease", 1, 0, 'l' },
153 { "dhcp-host", 1, 0, 'G' },
154 { "dhcp-range", 1, 0, 'F' },
155 { "dhcp-option", 1, 0, 'O' },
156 { "dhcp-boot", 1, 0, 'M' },
157 { "domain", 1, 0, 's' },
158 { "domain-suffix", 1, 0, 's' },
159 { "interface", 1, 0, 'i' },
160 { "listen-address", 1, 0, 'a' },
161 { "bogus-priv", 0, 0, 'b' },
162 { "bogus-nxdomain", 1, 0, 'B' },
163 { "selfmx", 0, 0, 'e' },
164 { "filterwin2k", 0, 0, 'f' },
165 { "pid-file", 2, 0, 'x' },
166 { "strict-order", 0, 0, 'o' },
167 { "server", 1, 0, 'S' },
168 { "local", 1, 0, LOPT_LOCAL },
169 { "address", 1, 0, 'A' },
170 { "conf-file", 2, 0, 'C' },
171 { "no-resolv", 0, 0, 'R' },
172 { "expand-hosts", 0, 0, 'E' },
173 { "localmx", 0, 0, 'L' },
174 { "local-ttl", 1, 0, 'T' },
175 { "no-negcache", 0, 0, 'N' },
176 { "addn-hosts", 1, 0, 'H' },
177 { "query-port", 1, 0, 'Q' },
178 { "except-interface", 1, 0, 'I' },
179 { "no-dhcp-interface", 1, 0, '2' },
180 { "domain-needed", 0, 0, 'D' },
181 { "dhcp-lease-max", 1, 0, 'X' },
182 { "bind-interfaces", 0, 0, 'z' },
183 { "read-ethers", 0, 0, 'Z' },
184 { "alias", 1, 0, 'V' },
185 { "dhcp-vendorclass", 1, 0, 'U' },
186 { "dhcp-userclass", 1, 0, 'j' },
187 { "dhcp-ignore", 1, 0, 'J' },
188 { "edns-packet-max", 1, 0, 'P' },
189 { "keep-in-foreground", 0, 0, 'k' },
190 { "dhcp-authoritative", 0, 0, 'K' },
191 { "srv-host", 1, 0, 'W' },
192 { "localise-queries", 0, 0, 'y' },
193 { "txt-record", 1, 0, 'Y' },
194 { "dns-rr", 1, 0, LOPT_RR },
195 { "enable-dbus", 2, 0, '1' },
196 { "bootp-dynamic", 2, 0, '3' },
197 { "dhcp-mac", 1, 0, '4' },
198 { "no-ping", 0, 0, '5' },
199 { "dhcp-script", 1, 0, '6' },
200 { "conf-dir", 1, 0, '7' },
201 { "log-facility", 1, 0 ,'8' },
202 { "leasefile-ro", 0, 0, '9' },
203 { "dns-forward-max", 1, 0, '0' },
204 { "clear-on-reload", 0, 0, LOPT_RELOAD },
205 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
206 { "enable-tftp", 0, 0, LOPT_TFTP },
207 { "tftp-secure", 0, 0, LOPT_SECURE },
208 { "tftp-unique-root", 0, 0, LOPT_APREF },
209 { "tftp-root", 1, 0, LOPT_PREFIX },
210 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
211 { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
212 { "ptr-record", 1, 0, LOPT_PTR },
213 { "naptr-record", 1, 0, LOPT_NAPTR },
214 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
215 { "dhcp-option-force", 1, 0, LOPT_FORCE },
216 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
217 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
218 { "log-async", 2, 0, LOPT_MAX_LOGS },
219 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
220 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
221 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
222 { "interface-name", 1, 0, LOPT_INTNAME },
223 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
224 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
225 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
226 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
227 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
228 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
229 { "all-servers", 0, 0, LOPT_NOLAST },
230 { "dhcp-match", 1, 0, LOPT_MATCH },
231 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
232 { "neg-ttl", 1, 0, LOPT_NEGTTL },
233 { "max-ttl", 1, 0, LOPT_MAXTTL },
234 { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
235 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
236 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
237 { "min-port", 1, 0, LOPT_MINPORT },
238 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
239 { "cname", 1, 0, LOPT_CNAME },
240 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
241 { "pxe-service", 1, 0, LOPT_PXE_SERV },
242 { "test", 0, 0, LOPT_TEST },
243 { "tag-if", 1, 0, LOPT_TAG_IF },
244 { "dhcp-proxy", 2, 0, LOPT_PROXY },
245 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
246 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
247 { "add-mac", 0, 0, LOPT_ADD_MAC },
248 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
249 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
250 { "conntrack", 0, 0, LOPT_CONNTRACK },
251 { "dhcp-client-update", 0, 0, LOPT_FQDN },
252 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
253 { "enable-ra", 0, 0, LOPT_RA },
254 { "dhcp-duid", 1, 0, LOPT_DUID },
255 { "host-record", 1, 0, LOPT_HOST_REC },
256 { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
257 { "auth-zone", 1, 0, LOPT_AUTHZONE },
258 { "auth-server", 1, 0, LOPT_AUTHSERV },
259 { "auth-ttl", 1, 0, LOPT_AUTHTTL },
260 { "auth-soa", 1, 0, LOPT_AUTHSOA },
261 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
262 { "auth-peer", 1, 0, LOPT_AUTHPEER },
263 { "ipset", 1, 0, LOPT_IPSET },
264 { NULL, 0, 0, 0 }
265 };
266
267
268 #define ARG_DUP OPT_LAST
269 #define ARG_ONE OPT_LAST + 1
270 #define ARG_USED_CL OPT_LAST + 2
271 #define ARG_USED_FILE OPT_LAST + 3
272
273 static struct {
274 int opt;
275 unsigned int rept;
276 char * const flagdesc;
277 char * const desc;
278 char * const arg;
279 } usage[] = {
280 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
281 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
282 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
283 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
284 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
285 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
286 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
287 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
288 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
289 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
290 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
291 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
292 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
293 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
294 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
295 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
296 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
297 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
298 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
299 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
300 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
301 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
302 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
303 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
304 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
305 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
306 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
307 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
308 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
309 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
310 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
311 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
312 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
313 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
314 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
315 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
316 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
317 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
318 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
319 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
320 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
321 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
322 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
323 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
324 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
325 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
326 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
327 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
328 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
329 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
330 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
331 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
332 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
333 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
334 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
335 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
336 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
337 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
338 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
339 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
340 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
341 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
342 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
343 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
344 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
345 { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
346 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
347 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
348 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
349 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
350 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
351 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
352 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
353 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
354 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
355 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
356 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
357 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
358 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
359 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
360 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
361 { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
362 { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
363 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
364 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
365 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
366 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
367 { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
368 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
369 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
370 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
371 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
372 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
373 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
374 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
375 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
376 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
377 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
378 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
379 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
380 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
381 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
382 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
383 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
384 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
385 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
386 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
387 { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
388 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
389 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
390 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
391 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
392 { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
393 { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
394 { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
395 { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
396 { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
397 { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
398 { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
399 { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
400 { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
401 { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
402 { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
403 { 0, 0, NULL, NULL, NULL }
404 };
405
406 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
407 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
408 following sequence so that they map to themselves: it is therefore possible to call
409 unhide_metas repeatedly on string without breaking things.
410 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
411 couple of other places.
412 Note that space is included here so that
413 --dhcp-option=3, string
414 has five characters, whilst
415 --dhcp-option=3," string"
416 has six.
417 */
418
419 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
420
421 static char hide_meta(char c)
422 {
423 unsigned int i;
424
425 for (i = 0; i < (sizeof(meta) - 1); i++)
426 if (c == meta[i])
427 return (char)i;
428
429 return c;
430 }
431
432 static char unhide_meta(char cr)
433 {
434 unsigned int c = cr;
435
436 if (c < (sizeof(meta) - 1))
437 cr = meta[c];
438
439 return cr;
440 }
441
442 static void unhide_metas(char *cp)
443 {
444 if (cp)
445 for(; *cp; cp++)
446 *cp = unhide_meta(*cp);
447 }
448
449 static void *opt_malloc(size_t size)
450 {
451 void *ret;
452
453 if (mem_recover)
454 {
455 ret = whine_malloc(size);
456 if (!ret)
457 longjmp(mem_jmp, 1);
458 }
459 else
460 ret = safe_malloc(size);
461
462 return ret;
463 }
464
465 static char *opt_string_alloc(char *cp)
466 {
467 char *ret = NULL;
468
469 if (cp && strlen(cp) != 0)
470 {
471 ret = opt_malloc(strlen(cp)+1);
472 strcpy(ret, cp);
473
474 /* restore hidden metachars */
475 unhide_metas(ret);
476 }
477
478 return ret;
479 }
480
481
482 /* find next comma, split string with zero and eliminate spaces.
483 return start of string following comma */
484
485 static char *split_chr(char *s, char c)
486 {
487 char *comma, *p;
488
489 if (!s || !(comma = strchr(s, c)))
490 return NULL;
491
492 p = comma;
493 *comma = ' ';
494
495 for (; *comma == ' '; comma++);
496
497 for (; (p >= s) && *p == ' '; p--)
498 *p = 0;
499
500 return comma;
501 }
502
503 static char *split(char *s)
504 {
505 return split_chr(s, ',');
506 }
507
508 static char *canonicalise_opt(char *s)
509 {
510 char *ret;
511 int nomem;
512
513 if (!s)
514 return 0;
515
516 unhide_metas(s);
517 if (!(ret = canonicalise(s, &nomem)) && nomem)
518 {
519 if (mem_recover)
520 longjmp(mem_jmp, 1);
521 else
522 die(_("could not get memory"), NULL, EC_NOMEM);
523 }
524
525 return ret;
526 }
527
528 static int atoi_check(char *a, int *res)
529 {
530 char *p;
531
532 if (!a)
533 return 0;
534
535 unhide_metas(a);
536
537 for (p = a; *p; p++)
538 if (*p < '0' || *p > '9')
539 return 0;
540
541 *res = atoi(a);
542 return 1;
543 }
544
545 static int atoi_check16(char *a, int *res)
546 {
547 if (!(atoi_check(a, res)) ||
548 *res < 0 ||
549 *res > 0xffff)
550 return 0;
551
552 return 1;
553 }
554
555 static void add_txt(char *name, char *txt)
556 {
557 size_t len = strlen(txt);
558 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
559
560 r->name = opt_string_alloc(name);
561 r->next = daemon->txt;
562 daemon->txt = r;
563 r->class = C_CHAOS;
564 r->txt = opt_malloc(len+1);
565 r->len = len+1;
566 *(r->txt) = len;
567 memcpy((r->txt)+1, txt, len);
568 }
569
570 static void do_usage(void)
571 {
572 char buff[100];
573 int i, j;
574
575 struct {
576 char handle;
577 int val;
578 } tab[] = {
579 { '$', CACHESIZ },
580 { '*', EDNS_PKTSZ },
581 { '&', MAXLEASES },
582 { '!', FTABSIZ },
583 { '#', TFTP_MAX_CONNECTIONS },
584 { '\0', 0 }
585 };
586
587 printf(_("Usage: dnsmasq [options]\n\n"));
588 #ifndef HAVE_GETOPT_LONG
589 printf(_("Use short options only on the command line.\n"));
590 #endif
591 printf(_("Valid options are:\n"));
592
593 for (i = 0; usage[i].opt != 0; i++)
594 {
595 char *desc = usage[i].flagdesc;
596 char *eq = "=";
597
598 if (!desc || *desc == '[')
599 eq = "";
600
601 if (!desc)
602 desc = "";
603
604 for ( j = 0; opts[j].name; j++)
605 if (opts[j].val == usage[i].opt)
606 break;
607 if (usage[i].opt < 256)
608 sprintf(buff, "-%c, ", usage[i].opt);
609 else
610 sprintf(buff, " ");
611
612 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
613 printf("%-40.40s", buff);
614
615 if (usage[i].arg)
616 {
617 strcpy(buff, usage[i].arg);
618 for (j = 0; tab[j].handle; j++)
619 if (tab[j].handle == *(usage[i].arg))
620 sprintf(buff, "%d", tab[j].val);
621 }
622 printf(_(usage[i].desc), buff);
623 printf("\n");
624 }
625 }
626
627 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
628
629 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
630 {
631 int source_port = 0, serv_port = NAMESERVER_PORT;
632 char *portno, *source;
633 #ifdef HAVE_IPV6
634 int scope_index = 0;
635 char *scope_id;
636 #endif
637
638 if ((source = split_chr(arg, '@')) && /* is there a source. */
639 (portno = split_chr(source, '#')) &&
640 !atoi_check16(portno, &source_port))
641 return _("bad port");
642
643 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
644 !atoi_check16(portno, &serv_port))
645 return _("bad port");
646
647 #ifdef HAVE_IPV6
648 scope_id = split_chr(arg, '%');
649 #endif
650
651 if ((addr->in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
652 {
653 addr->in.sin_port = htons(serv_port);
654 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
655 #ifdef HAVE_SOCKADDR_SA_LEN
656 source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
657 #endif
658 source_addr->in.sin_addr.s_addr = INADDR_ANY;
659 source_addr->in.sin_port = htons(daemon->query_port);
660
661 if (source)
662 {
663 if (flags)
664 *flags |= SERV_HAS_SOURCE;
665 source_addr->in.sin_port = htons(source_port);
666 if ((source_addr->in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
667 {
668 #if defined(SO_BINDTODEVICE)
669 source_addr->in.sin_addr.s_addr = INADDR_ANY;
670 strncpy(interface, source, IF_NAMESIZE - 1);
671 #else
672 return _("interface binding not supported");
673 #endif
674 }
675 }
676 }
677 #ifdef HAVE_IPV6
678 else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
679 {
680 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
681 return _("bad interface name");
682
683 addr->in6.sin6_port = htons(serv_port);
684 addr->in6.sin6_scope_id = scope_index;
685 source_addr->in6.sin6_addr = in6addr_any;
686 source_addr->in6.sin6_port = htons(daemon->query_port);
687 source_addr->in6.sin6_scope_id = 0;
688 addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
689 addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
690 #ifdef HAVE_SOCKADDR_SA_LEN
691 addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
692 #endif
693 if (source)
694 {
695 if (flags)
696 *flags |= SERV_HAS_SOURCE;
697 source_addr->in6.sin6_port = htons(source_port);
698 if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
699 {
700 #if defined(SO_BINDTODEVICE)
701 source_addr->in6.sin6_addr = in6addr_any;
702 strncpy(interface, source, IF_NAMESIZE - 1);
703 #else
704 return _("interface binding not supported");
705 #endif
706 }
707 }
708 }
709 #endif
710 else
711 return _("bad address");
712
713 return NULL;
714 }
715
716 #ifdef HAVE_DHCP
717
718 static int is_tag_prefix(char *arg)
719 {
720 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
721 return 1;
722
723 return 0;
724 }
725
726 static char *set_prefix(char *arg)
727 {
728 if (strstr(arg, "set:") == arg)
729 return arg+4;
730
731 return arg;
732 }
733
734 /* This is too insanely large to keep in-line in the switch */
735 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
736 {
737 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
738 char lenchar = 0, *cp;
739 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
740 char *comma = NULL;
741 struct dhcp_netid *np = NULL;
742 u16 opt_len = 0;
743 int is6 = 0;
744
745 new->len = 0;
746 new->flags = flags;
747 new->netid = NULL;
748 new->val = NULL;
749 new->opt = 0;
750
751 while (arg)
752 {
753 comma = split(arg);
754
755 for (cp = arg; *cp; cp++)
756 if (*cp < '0' || *cp > '9')
757 break;
758
759 if (!*cp)
760 {
761 new->opt = atoi(arg);
762 opt_len = 0;
763 break;
764 }
765
766 if (strstr(arg, "option:") == arg)
767 {
768 new->opt = lookup_dhcp_opt(AF_INET, arg+7);
769 opt_len = lookup_dhcp_len(AF_INET, new->opt);
770 /* option:<optname> must follow tag and vendor string. */
771 break;
772 }
773 #ifdef HAVE_DHCP6
774 else if (strstr(arg, "option6:") == arg)
775 {
776 for (cp = arg+8; *cp; cp++)
777 if (*cp < '0' || *cp > '9')
778 break;
779
780 if (!*cp)
781 {
782 new->opt = atoi(arg+8);
783 opt_len = 0;
784 }
785 else
786 {
787 new->opt = lookup_dhcp_opt(AF_INET6, arg+8);
788 opt_len = lookup_dhcp_len(AF_INET6, new->opt);
789 }
790 /* option6:<opt>|<optname> must follow tag and vendor string. */
791 is6 = 1;
792 break;
793 }
794 #endif
795 else if (strstr(arg, "vendor:") == arg)
796 {
797 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
798 new->flags |= DHOPT_VENDOR;
799 }
800 else if (strstr(arg, "encap:") == arg)
801 {
802 new->u.encap = atoi(arg+6);
803 new->flags |= DHOPT_ENCAPSULATE;
804 }
805 else if (strstr(arg, "vi-encap:") == arg)
806 {
807 new->u.encap = atoi(arg+9);
808 new->flags |= DHOPT_RFC3925;
809 if (flags == DHOPT_MATCH)
810 {
811 new->opt = 1; /* avoid error below */
812 break;
813 }
814 }
815 else
816 {
817 new->netid = opt_malloc(sizeof (struct dhcp_netid));
818 /* allow optional "net:" or "tag:" for consistency */
819 if (is_tag_prefix(arg))
820 new->netid->net = opt_string_alloc(arg+4);
821 else
822 new->netid->net = opt_string_alloc(set_prefix(arg));
823 new->netid->next = np;
824 np = new->netid;
825 }
826
827 arg = comma;
828 }
829
830 #ifdef HAVE_DHCP6
831 if (is6)
832 {
833 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
834 ret_err(_("unsupported encapsulation for IPv6 option"));
835
836 if (opt_len == 0 &&
837 !(new->flags & DHOPT_RFC3925))
838 opt_len = lookup_dhcp_len(AF_INET6 ,new->opt);
839 }
840 else
841 #endif
842 if (opt_len == 0 &&
843 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
844 opt_len = lookup_dhcp_len(AF_INET ,new->opt);
845
846 /* option may be missing with rfc3925 match */
847 if (new->opt == 0)
848 ret_err(_("bad dhcp-option"));
849
850 if (comma)
851 {
852 /* characterise the value */
853 char c;
854 int found_dig = 0;
855 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
856 addrs = digs = 1;
857 dots = 0;
858 for (cp = comma; (c = *cp); cp++)
859 if (c == ',')
860 {
861 addrs++;
862 is_dec = is_hex = 0;
863 }
864 else if (c == ':')
865 {
866 digs++;
867 is_dec = is_addr = 0;
868 }
869 else if (c == '/')
870 {
871 is_addr6 = is_dec = is_hex = 0;
872 if (cp == comma) /* leading / means a pathname */
873 is_addr = 0;
874 }
875 else if (c == '.')
876 {
877 is_addr6 = is_dec = is_hex = 0;
878 dots++;
879 }
880 else if (c == '-')
881 is_hex = is_addr = is_addr6 = 0;
882 else if (c == ' ')
883 is_dec = is_hex = 0;
884 else if (!(c >='0' && c <= '9'))
885 {
886 is_addr = 0;
887 if (cp[1] == 0 && is_dec &&
888 (c == 'b' || c == 's' || c == 'i'))
889 {
890 lenchar = c;
891 *cp = 0;
892 }
893 else
894 is_dec = 0;
895 if (!((c >='A' && c <= 'F') ||
896 (c >='a' && c <= 'f') ||
897 (c == '*' && (flags & DHOPT_MATCH))))
898 {
899 is_hex = 0;
900 if (c != '[' && c != ']')
901 is_addr6 = 0;
902 }
903 }
904 else
905 found_dig = 1;
906
907 if (!found_dig)
908 is_dec = is_addr = 0;
909
910 /* We know that some options take addresses */
911 if (opt_len & OT_ADDR_LIST)
912 {
913 is_string = is_dec = is_hex = 0;
914
915 if (!is6 && (!is_addr || dots == 0))
916 ret_err(_("bad IP address"));
917
918 if (is6 && !is_addr6)
919 ret_err(_("bad IPv6 address"));
920 }
921 /* or names */
922 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
923 is_addr6 = is_addr = is_dec = is_hex = 0;
924
925 if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
926 {
927 int val, fac = 1;
928
929 switch (comma[strlen(comma) - 1])
930 {
931 case 'w':
932 case 'W':
933 fac *= 7;
934 /* fall through */
935 case 'd':
936 case 'D':
937 fac *= 24;
938 /* fall though */
939 case 'h':
940 case 'H':
941 fac *= 60;
942 /* fall through */
943 case 'm':
944 case 'M':
945 fac *= 60;
946 /* fall through */
947 case 's':
948 case 'S':
949 comma[strlen(comma) - 1] = 0;
950 }
951
952 new->len = 4;
953 new->val = opt_malloc(4);
954 val = atoi(comma);
955 *((int *)new->val) = htonl(val * fac);
956 }
957 else if (is_hex && digs > 1)
958 {
959 new->len = digs;
960 new->val = opt_malloc(new->len);
961 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
962 new->flags |= DHOPT_HEX;
963 }
964 else if (is_dec)
965 {
966 int i, val = atoi(comma);
967 /* assume numeric arg is 1 byte except for
968 options where it is known otherwise.
969 For vendor class option, we have to hack. */
970 if (opt_len != 0)
971 new->len = opt_len;
972 else if (val & 0xffff0000)
973 new->len = 4;
974 else if (val & 0xff00)
975 new->len = 2;
976 else
977 new->len = 1;
978
979 if (lenchar == 'b')
980 new->len = 1;
981 else if (lenchar == 's')
982 new->len = 2;
983 else if (lenchar == 'i')
984 new->len = 4;
985
986 new->val = opt_malloc(new->len);
987 for (i=0; i<new->len; i++)
988 new->val[i] = val>>((new->len - i - 1)*8);
989 }
990 else if (is_addr && !is6)
991 {
992 struct in_addr in;
993 unsigned char *op;
994 char *slash;
995 /* max length of address/subnet descriptor is five bytes,
996 add one for the option 120 enc byte too */
997 new->val = op = opt_malloc((5 * addrs) + 1);
998 new->flags |= DHOPT_ADDR;
999
1000 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1001 new->opt == OPTION_SIP_SERVER)
1002 {
1003 *(op++) = 1; /* RFC 3361 "enc byte" */
1004 new->flags &= ~DHOPT_ADDR;
1005 }
1006 while (addrs--)
1007 {
1008 cp = comma;
1009 comma = split(cp);
1010 slash = split_chr(cp, '/');
1011 in.s_addr = inet_addr(cp);
1012 if (!slash)
1013 {
1014 memcpy(op, &in, INADDRSZ);
1015 op += INADDRSZ;
1016 }
1017 else
1018 {
1019 unsigned char *p = (unsigned char *)&in;
1020 int netsize = atoi(slash);
1021 *op++ = netsize;
1022 if (netsize > 0)
1023 *op++ = *p++;
1024 if (netsize > 8)
1025 *op++ = *p++;
1026 if (netsize > 16)
1027 *op++ = *p++;
1028 if (netsize > 24)
1029 *op++ = *p++;
1030 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1031 }
1032 }
1033 new->len = op - new->val;
1034 }
1035 else if (is_addr6 && is6)
1036 {
1037 unsigned char *op;
1038 new->val = op = opt_malloc(16 * addrs);
1039 new->flags |= DHOPT_ADDR6;
1040 while (addrs--)
1041 {
1042 cp = comma;
1043 comma = split(cp);
1044
1045 /* check for [1234::7] */
1046 if (*cp == '[')
1047 cp++;
1048 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1049 cp[strlen(cp)-1] = 0;
1050
1051 if (inet_pton(AF_INET6, cp, op))
1052 {
1053 op += IN6ADDRSZ;
1054 continue;
1055 }
1056
1057 ret_err(_("bad IPv6 address"));
1058 }
1059 new->len = op - new->val;
1060 }
1061 else if (is_string)
1062 {
1063 /* text arg */
1064 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
1065 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1066 {
1067 /* dns search, RFC 3397, or SIP, RFC 3361 */
1068 unsigned char *q, *r, *tail;
1069 unsigned char *p, *m = NULL, *newp;
1070 size_t newlen, len = 0;
1071 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
1072
1073 arg = comma;
1074 comma = split(arg);
1075
1076 while (arg && *arg)
1077 {
1078 char *in, *dom = NULL;
1079 size_t domlen = 1;
1080 /* Allow "." as an empty domain */
1081 if (strcmp (arg, ".") != 0)
1082 {
1083 if (!(dom = canonicalise_opt(arg)))
1084 ret_err(_("bad domain in dhcp-option"));
1085
1086 domlen = strlen(dom) + 2;
1087 }
1088
1089 newp = opt_malloc(len + domlen + header_size);
1090 if (m)
1091 {
1092 memcpy(newp, m, header_size + len);
1093 free(m);
1094 }
1095 m = newp;
1096 p = m + header_size;
1097 q = p + len;
1098
1099 /* add string on the end in RFC1035 format */
1100 for (in = dom; in && *in;)
1101 {
1102 unsigned char *cp = q++;
1103 int j;
1104 for (j = 0; *in && (*in != '.'); in++, j++)
1105 *q++ = *in;
1106 *cp = j;
1107 if (*in)
1108 in++;
1109 }
1110 *q++ = 0;
1111 free(dom);
1112
1113 /* Now tail-compress using earlier names. */
1114 newlen = q - p;
1115 for (tail = p + len; *tail; tail += (*tail) + 1)
1116 for (r = p; r - p < (int)len; r += (*r) + 1)
1117 if (strcmp((char *)r, (char *)tail) == 0)
1118 {
1119 PUTSHORT((r - p) | 0xc000, tail);
1120 newlen = tail - p;
1121 goto end;
1122 }
1123 end:
1124 len = newlen;
1125
1126 arg = comma;
1127 comma = split(arg);
1128 }
1129
1130 /* RFC 3361, enc byte is zero for names */
1131 if (new->opt == OPTION_SIP_SERVER)
1132 m[0] = 0;
1133 new->len = (int) len + header_size;
1134 new->val = m;
1135 }
1136 #ifdef HAVE_DHCP6
1137 else if (comma && (opt_len & OT_CSTRING))
1138 {
1139 /* length fields are two bytes so need 16 bits for each string */
1140 int i, commas = 1;
1141 unsigned char *p, *newp;
1142
1143 for (i = 0; comma[i]; i++)
1144 if (comma[i] == ',')
1145 commas++;
1146
1147 newp = opt_malloc(strlen(comma)+(2*commas));
1148 p = newp;
1149 arg = comma;
1150 comma = split(arg);
1151
1152 while (arg && *arg)
1153 {
1154 u16 len = strlen(arg);
1155 unhide_metas(arg);
1156 PUTSHORT(len, p);
1157 memcpy(p, arg, len);
1158 p += len;
1159
1160 arg = comma;
1161 comma = split(arg);
1162 }
1163
1164 new->val = newp;
1165 new->len = p - newp;
1166 }
1167 else if (comma && (opt_len & OT_RFC1035_NAME))
1168 {
1169 unsigned char *p = NULL, *newp, *end;
1170 int len = 0;
1171 arg = comma;
1172 comma = split(arg);
1173
1174 while (arg && *arg)
1175 {
1176 char *dom = canonicalise_opt(arg);
1177 if (!dom)
1178 ret_err(_("bad domain in dhcp-option"));
1179
1180 newp = opt_malloc(len + strlen(dom) + 2);
1181
1182 if (p)
1183 {
1184 memcpy(newp, p, len);
1185 free(p);
1186 }
1187
1188 p = newp;
1189 end = do_rfc1035_name(p + len, dom);
1190 *end++ = 0;
1191 len = end - p;
1192 free(dom);
1193
1194 arg = comma;
1195 comma = split(arg);
1196 }
1197
1198 new->val = p;
1199 new->len = len;
1200 }
1201 #endif
1202 else
1203 {
1204 new->len = strlen(comma);
1205 /* keep terminating zero on string */
1206 new->val = (unsigned char *)opt_string_alloc(comma);
1207 new->flags |= DHOPT_STRING;
1208 }
1209 }
1210 }
1211
1212 if (!is6 &&
1213 ((new->len > 255) ||
1214 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1215 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
1216 ret_err(_("dhcp-option too long"));
1217
1218 if (flags == DHOPT_MATCH)
1219 {
1220 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1221 !new->netid ||
1222 new->netid->next)
1223 ret_err(_("illegal dhcp-match"));
1224
1225 if (is6)
1226 {
1227 new->next = daemon->dhcp_match6;
1228 daemon->dhcp_match6 = new;
1229 }
1230 else
1231 {
1232 new->next = daemon->dhcp_match;
1233 daemon->dhcp_match = new;
1234 }
1235 }
1236 else if (is6)
1237 {
1238 new->next = daemon->dhcp_opts6;
1239 daemon->dhcp_opts6 = new;
1240 }
1241 else
1242 {
1243 new->next = daemon->dhcp_opts;
1244 daemon->dhcp_opts = new;
1245 }
1246
1247 return 1;
1248 }
1249
1250 #endif
1251
1252 void set_option_bool(unsigned int opt)
1253 {
1254 if (opt < 32)
1255 daemon->options |= 1u << opt;
1256 else
1257 daemon->options2 |= 1u << (opt - 32);
1258 }
1259
1260 void reset_option_bool(unsigned int opt)
1261 {
1262 if (opt < 32)
1263 daemon->options &= ~(1u << opt);
1264 else
1265 daemon->options2 &= ~(1u << (opt - 32));
1266 }
1267
1268 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
1269 {
1270 int i;
1271 char *comma;
1272
1273 if (option == '?')
1274 ret_err(gen_err);
1275
1276 for (i=0; usage[i].opt != 0; i++)
1277 if (usage[i].opt == option)
1278 {
1279 int rept = usage[i].rept;
1280
1281 if (command_line)
1282 {
1283 /* command line */
1284 if (rept == ARG_USED_CL)
1285 ret_err(_("illegal repeated flag"));
1286 if (rept == ARG_ONE)
1287 usage[i].rept = ARG_USED_CL;
1288 }
1289 else
1290 {
1291 /* allow file to override command line */
1292 if (rept == ARG_USED_FILE)
1293 ret_err(_("illegal repeated keyword"));
1294 if (rept == ARG_USED_CL || rept == ARG_ONE)
1295 usage[i].rept = ARG_USED_FILE;
1296 }
1297
1298 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1299 {
1300 set_option_bool(rept);
1301 return 1;
1302 }
1303
1304 break;
1305 }
1306
1307 switch (option)
1308 {
1309 case 'C': /* --conf-file */
1310 {
1311 char *file = opt_string_alloc(arg);
1312 if (file)
1313 {
1314 one_file(file, 0);
1315 free(file);
1316 }
1317 break;
1318 }
1319
1320 case '7': /* --conf-dir */
1321 {
1322 DIR *dir_stream;
1323 struct dirent *ent;
1324 char *directory, *path;
1325 struct list {
1326 char *suffix;
1327 struct list *next;
1328 } *ignore_suffix = NULL, *li;
1329
1330 comma = split(arg);
1331 if (!(directory = opt_string_alloc(arg)))
1332 break;
1333
1334 for (arg = comma; arg; arg = comma)
1335 {
1336 comma = split(arg);
1337 li = opt_malloc(sizeof(struct list));
1338 li->next = ignore_suffix;
1339 ignore_suffix = li;
1340 /* Have to copy: buffer is overwritten */
1341 li->suffix = opt_string_alloc(arg);
1342 };
1343
1344 if (!(dir_stream = opendir(directory)))
1345 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1346
1347 while ((ent = readdir(dir_stream)))
1348 {
1349 size_t len = strlen(ent->d_name);
1350 struct stat buf;
1351
1352 /* ignore emacs backups and dotfiles */
1353 if (len == 0 ||
1354 ent->d_name[len - 1] == '~' ||
1355 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1356 ent->d_name[0] == '.')
1357 continue;
1358
1359 for (li = ignore_suffix; li; li = li->next)
1360 {
1361 /* check for proscribed suffices */
1362 size_t ls = strlen(li->suffix);
1363 if (len > ls &&
1364 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1365 break;
1366 }
1367 if (li)
1368 continue;
1369
1370 path = opt_malloc(strlen(directory) + len + 2);
1371 strcpy(path, directory);
1372 strcat(path, "/");
1373 strcat(path, ent->d_name);
1374
1375 /* files must be readable */
1376 if (stat(path, &buf) == -1)
1377 die(_("cannot access %s: %s"), path, EC_FILE);
1378
1379 /* only reg files allowed. */
1380 if (S_ISREG(buf.st_mode))
1381 one_file(path, 0);
1382
1383 free(path);
1384 }
1385
1386 closedir(dir_stream);
1387 free(directory);
1388 for(; ignore_suffix; ignore_suffix = li)
1389 {
1390 li = ignore_suffix->next;
1391 free(ignore_suffix->suffix);
1392 free(ignore_suffix);
1393 }
1394
1395 break;
1396 }
1397
1398 case '1': /* --enable-dbus */
1399 set_option_bool(OPT_DBUS);
1400 if (arg)
1401 daemon->dbus_name = opt_string_alloc(arg);
1402 else
1403 daemon->dbus_name = DNSMASQ_SERVICE;
1404 break;
1405
1406 case '8': /* --log-facility */
1407 /* may be a filename */
1408 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1409 daemon->log_file = opt_string_alloc(arg);
1410 else
1411 {
1412 #ifdef __ANDROID__
1413 ret_err(_("setting log facility is not possible under Android"));
1414 #else
1415 for (i = 0; facilitynames[i].c_name; i++)
1416 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1417 break;
1418
1419 if (facilitynames[i].c_name)
1420 daemon->log_fac = facilitynames[i].c_val;
1421 else
1422 ret_err(_("bad log facility"));
1423 #endif
1424 }
1425 break;
1426
1427 case 'x': /* --pid-file */
1428 daemon->runfile = opt_string_alloc(arg);
1429 break;
1430
1431 case 'r': /* --resolv-file */
1432 {
1433 char *name = opt_string_alloc(arg);
1434 struct resolvc *new, *list = daemon->resolv_files;
1435
1436 if (list && list->is_default)
1437 {
1438 /* replace default resolv file - possibly with nothing */
1439 if (name)
1440 {
1441 list->is_default = 0;
1442 list->name = name;
1443 }
1444 else
1445 list = NULL;
1446 }
1447 else if (name)
1448 {
1449 new = opt_malloc(sizeof(struct resolvc));
1450 new->next = list;
1451 new->name = name;
1452 new->is_default = 0;
1453 new->mtime = 0;
1454 new->logged = 0;
1455 list = new;
1456 }
1457 daemon->resolv_files = list;
1458 break;
1459 }
1460
1461 case 'm': /* --mx-host */
1462 {
1463 int pref = 1;
1464 struct mx_srv_record *new;
1465 char *name, *target = NULL;
1466
1467 if ((comma = split(arg)))
1468 {
1469 char *prefstr;
1470 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1471 ret_err(_("bad MX preference"));
1472 }
1473
1474 if (!(name = canonicalise_opt(arg)) ||
1475 (comma && !(target = canonicalise_opt(comma))))
1476 ret_err(_("bad MX name"));
1477
1478 new = opt_malloc(sizeof(struct mx_srv_record));
1479 new->next = daemon->mxnames;
1480 daemon->mxnames = new;
1481 new->issrv = 0;
1482 new->name = name;
1483 new->target = target; /* may be NULL */
1484 new->weight = pref;
1485 break;
1486 }
1487
1488 case 't': /* --mx-target */
1489 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1490 ret_err(_("bad MX target"));
1491 break;
1492
1493 #ifdef HAVE_DHCP
1494 case 'l': /* --dhcp-leasefile */
1495 daemon->lease_file = opt_string_alloc(arg);
1496 break;
1497
1498 /* Sorry about the gross pre-processor abuse */
1499 case '6': /* --dhcp-script */
1500 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1501 # if defined(NO_FORK)
1502 ret_err(_("cannot run scripts under uClinux"));
1503 # elif !defined(HAVE_SCRIPT)
1504 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
1505 # else
1506 if (option == LOPT_LUASCRIPT)
1507 # if !defined(HAVE_LUASCRIPT)
1508 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
1509 # else
1510 daemon->luascript = opt_string_alloc(arg);
1511 # endif
1512 else
1513 daemon->lease_change_command = opt_string_alloc(arg);
1514 # endif
1515 break;
1516 #endif /* HAVE_DHCP */
1517
1518 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1519 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1520 case 'H': /* --addn-hosts */
1521 {
1522 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1523 static int hosts_index = 1;
1524 new->fname = opt_string_alloc(arg);
1525 new->index = hosts_index++;
1526 new->flags = 0;
1527 if (option == 'H')
1528 {
1529 new->next = daemon->addn_hosts;
1530 daemon->addn_hosts = new;
1531 }
1532 else if (option == LOPT_DHCP_HOST)
1533 {
1534 new->next = daemon->dhcp_hosts_file;
1535 daemon->dhcp_hosts_file = new;
1536 }
1537 else if (option == LOPT_DHCP_OPTS)
1538 {
1539 new->next = daemon->dhcp_opts_file;
1540 daemon->dhcp_opts_file = new;
1541 }
1542 break;
1543 }
1544
1545 case LOPT_AUTHSERV: /* --auth-server */
1546 if (!(comma = split(arg)))
1547 ret_err(gen_err);
1548
1549 daemon->authserver = opt_string_alloc(arg);
1550 arg = comma;
1551 do {
1552 struct iname *new = opt_malloc(sizeof(struct iname));
1553 comma = split(arg);
1554 new->name = NULL;
1555 unhide_metas(arg);
1556 if ((new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1557 new->addr.sa.sa_family = AF_INET;
1558 #ifdef HAVE_IPV6
1559 else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1560 new->addr.sa.sa_family = AF_INET6;
1561 #endif
1562 else
1563 new->name = opt_string_alloc(arg);
1564
1565 new->next = daemon->authinterface;
1566 daemon->authinterface = new;
1567
1568 arg = comma;
1569 } while (arg);
1570
1571 break;
1572
1573 case LOPT_AUTHSFS: /* --auth-sec-servers */
1574 {
1575 struct name_list *new;
1576
1577 do {
1578 comma = split(arg);
1579 new = opt_malloc(sizeof(struct name_list));
1580 new->name = opt_string_alloc(arg);
1581 new->next = daemon->secondary_forward_server;
1582 daemon->secondary_forward_server = new;
1583 arg = comma;
1584 } while (arg);
1585 break;
1586 }
1587
1588 case LOPT_AUTHZONE: /* --auth-zone */
1589 {
1590 struct auth_zone *new;
1591
1592 comma = split(arg);
1593
1594 new = opt_malloc(sizeof(struct auth_zone));
1595 new->domain = opt_string_alloc(arg);
1596 new->subnet = NULL;
1597 new->next = daemon->auth_zones;
1598 daemon->auth_zones = new;
1599
1600 while ((arg = comma))
1601 {
1602 int prefixlen = 0;
1603 char *prefix;
1604 struct subnet *subnet = opt_malloc(sizeof(struct subnet));
1605
1606 subnet->next = new->subnet;
1607 new->subnet = subnet;
1608
1609 comma = split(arg);
1610 prefix = split_chr(arg, '/');
1611
1612 if (prefix && !atoi_check(prefix, &prefixlen))
1613 ret_err(gen_err);
1614
1615 if (inet_pton(AF_INET, arg, &subnet->addr4))
1616 {
1617 if ((prefixlen & 0x07) != 0 || prefixlen > 24)
1618 ret_err(_("bad prefix"));
1619 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
1620 subnet->is6 = 0;
1621 }
1622 #ifdef HAVE_IPV6
1623 else if (inet_pton(AF_INET6, arg, &subnet->addr6))
1624 {
1625 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
1626 subnet->is6 = 1;
1627 }
1628 #endif
1629 else
1630 ret_err(gen_err);
1631 }
1632 break;
1633 }
1634
1635 case LOPT_AUTHSOA: /* --auth-soa */
1636 comma = split(arg);
1637 atoi_check(arg, (int *)&daemon->soa_sn);
1638 if (comma)
1639 {
1640 char *cp;
1641 arg = comma;
1642 comma = split(arg);
1643 daemon->hostmaster = opt_string_alloc(arg);
1644 for (cp = daemon->hostmaster; *cp; cp++)
1645 if (*cp == '@')
1646 *cp = '.';
1647
1648 if (comma)
1649 {
1650 arg = comma;
1651 comma = split(arg);
1652 atoi_check(arg, (int *)&daemon->soa_refresh);
1653 if (comma)
1654 {
1655 arg = comma;
1656 comma = split(arg);
1657 atoi_check(arg, (int *)&daemon->soa_retry);
1658 if (comma)
1659 {
1660 arg = comma;
1661 comma = split(arg);
1662 atoi_check(arg, (int *)&daemon->soa_expiry);
1663 }
1664 }
1665 }
1666 }
1667
1668 break;
1669
1670 case 's': /* --domain */
1671 if (strcmp (arg, "#") == 0)
1672 set_option_bool(OPT_RESOLV_DOMAIN);
1673 else
1674 {
1675 char *d;
1676 comma = split(arg);
1677 if (!(d = canonicalise_opt(arg)))
1678 ret_err(gen_err);
1679 else
1680 {
1681 if (comma)
1682 {
1683 struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
1684 char *netpart;
1685
1686 unhide_metas(comma);
1687 if ((netpart = split_chr(comma, '/')))
1688 {
1689 int msize;
1690
1691 arg = split(netpart);
1692 if (!atoi_check(netpart, &msize))
1693 ret_err(gen_err);
1694 else if (inet_pton(AF_INET, comma, &new->start))
1695 {
1696 int mask = (1 << (32 - msize)) - 1;
1697 new->is6 = 0;
1698 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1699 new->end.s_addr = new->start.s_addr | htonl(mask);
1700 if (arg)
1701 {
1702 /* generate the equivalent of
1703 local=/<domain>/
1704 local=/xxx.yyy.zzz.in-addr.arpa/ */
1705
1706 if (strcmp(arg, "local") != 0 ||
1707 (msize != 8 && msize != 16 && msize != 24))
1708 ret_err(gen_err);
1709 else
1710 {
1711 struct server *serv = opt_malloc(sizeof(struct server));
1712 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1713 char *p;
1714
1715 memset(serv, 0, sizeof(struct server));
1716 serv->domain = d;
1717 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1718 serv->next = daemon->servers;
1719 daemon->servers = serv;
1720
1721 serv = opt_malloc(sizeof(struct server));
1722 memset(serv, 0, sizeof(struct server));
1723 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1724
1725 if (msize == 24)
1726 p += sprintf(p, "%d.", a & 0xff);
1727 a = a >> 8;
1728 if (msize != 8)
1729 p += sprintf(p, "%d.", a & 0xff);
1730 a = a >> 8;
1731 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
1732
1733 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1734 serv->next = daemon->servers;
1735 daemon->servers = serv;
1736 }
1737 }
1738 }
1739 #ifdef HAVE_IPV6
1740 else if (inet_pton(AF_INET6, comma, &new->start6))
1741 {
1742 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1743 u64 addrpart = addr6part(&new->start6);
1744 new->is6 = 1;
1745
1746 /* prefix==64 overflows the mask calculation above */
1747 if (msize == 64)
1748 mask = (u64)-1LL;
1749
1750 new->end6 = new->start6;
1751 setaddr6part(&new->start6, addrpart & ~mask);
1752 setaddr6part(&new->end6, addrpart | mask);
1753
1754 if (msize < 64)
1755 ret_err(gen_err);
1756 else if (arg)
1757 {
1758 /* generate the equivalent of
1759 local=/<domain>/
1760 local=/xxx.yyy.zzz.ip6.arpa/ */
1761
1762 if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
1763 ret_err(gen_err);
1764 else
1765 {
1766 struct server *serv = opt_malloc(sizeof(struct server));
1767 char *p;
1768
1769 memset(serv, 0, sizeof(struct server));
1770 serv->domain = d;
1771 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1772 serv->next = daemon->servers;
1773 daemon->servers = serv;
1774
1775 serv = opt_malloc(sizeof(struct server));
1776 memset(serv, 0, sizeof(struct server));
1777 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1778
1779 for (i = msize-1; i >= 0; i -= 4)
1780 {
1781 int dig = ((unsigned char *)&new->start6)[i>>3];
1782 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1783 }
1784 p += sprintf(p, "ip6.arpa");
1785
1786 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1787 serv->next = daemon->servers;
1788 daemon->servers = serv;
1789 }
1790 }
1791 }
1792 #endif
1793 else
1794 ret_err(gen_err);
1795 }
1796 else
1797 {
1798 arg = split(comma);
1799 if (inet_pton(AF_INET, comma, &new->start))
1800 {
1801 new->is6 = 0;
1802 if (!arg)
1803 new->end.s_addr = new->start.s_addr;
1804 else if (!inet_pton(AF_INET, arg, &new->end))
1805 ret_err(gen_err);
1806 }
1807 #ifdef HAVE_IPV6
1808 else if (inet_pton(AF_INET6, comma, &new->start6))
1809 {
1810 new->is6 = 1;
1811 if (!arg)
1812 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1813 else if (!inet_pton(AF_INET6, arg, &new->end6))
1814 ret_err(gen_err);
1815 }
1816 #endif
1817 else
1818 ret_err(gen_err);
1819 }
1820
1821 new->domain = d;
1822 new->next = daemon->cond_domain;
1823 daemon->cond_domain = new;
1824 }
1825 else
1826 daemon->domain_suffix = d;
1827 }
1828 }
1829 break;
1830
1831 case 'u': /* --user */
1832 daemon->username = opt_string_alloc(arg);
1833 break;
1834
1835 case 'g': /* --group */
1836 daemon->groupname = opt_string_alloc(arg);
1837 daemon->group_set = 1;
1838 break;
1839
1840 #ifdef HAVE_DHCP
1841 case LOPT_SCRIPTUSR: /* --scriptuser */
1842 daemon->scriptuser = opt_string_alloc(arg);
1843 break;
1844 #endif
1845
1846 case 'i': /* --interface */
1847 do {
1848 struct iname *new = opt_malloc(sizeof(struct iname));
1849 comma = split(arg);
1850 new->next = daemon->if_names;
1851 daemon->if_names = new;
1852 /* new->name may be NULL if someone does
1853 "interface=" to disable all interfaces except loop. */
1854 new->name = opt_string_alloc(arg);
1855 new->used = 0;
1856 arg = comma;
1857 } while (arg);
1858 break;
1859
1860 case 'I': /* --except-interface */
1861 case '2': /* --no-dhcp-interface */
1862 do {
1863 struct iname *new = opt_malloc(sizeof(struct iname));
1864 comma = split(arg);
1865 new->name = opt_string_alloc(arg);
1866 if (option == 'I')
1867 {
1868 new->next = daemon->if_except;
1869 daemon->if_except = new;
1870 }
1871 else
1872 {
1873 new->next = daemon->dhcp_except;
1874 daemon->dhcp_except = new;
1875 }
1876 arg = comma;
1877 } while (arg);
1878 break;
1879
1880 case 'B': /* --bogus-nxdomain */
1881 {
1882 struct in_addr addr;
1883 unhide_metas(arg);
1884 if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1885 {
1886 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1887 baddr->next = daemon->bogus_addr;
1888 daemon->bogus_addr = baddr;
1889 baddr->addr = addr;
1890 }
1891 else
1892 ret_err(gen_err); /* error */
1893 break;
1894 }
1895
1896 case 'a': /* --listen-address */
1897 case LOPT_AUTHPEER: /* --auth-peer */
1898 do {
1899 struct iname *new = opt_malloc(sizeof(struct iname));
1900 comma = split(arg);
1901 unhide_metas(arg);
1902 if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1903 {
1904 new->addr.sa.sa_family = AF_INET;
1905 new->addr.in.sin_port = 0;
1906 #ifdef HAVE_SOCKADDR_SA_LEN
1907 new->addr.in.sin_len = sizeof(new->addr.in);
1908 #endif
1909 }
1910 #ifdef HAVE_IPV6
1911 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1912 {
1913 new->addr.sa.sa_family = AF_INET6;
1914 new->addr.in6.sin6_flowinfo = 0;
1915 new->addr.in6.sin6_scope_id = 0;
1916 new->addr.in6.sin6_port = 0;
1917 #ifdef HAVE_SOCKADDR_SA_LEN
1918 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1919 #endif
1920 }
1921 #endif
1922 else
1923 ret_err(gen_err);
1924
1925 new->used = 0;
1926 if (option == 'a')
1927 {
1928 new->next = daemon->if_addrs;
1929 daemon->if_addrs = new;
1930 }
1931 else
1932 {
1933 new->next = daemon->auth_peers;
1934 daemon->auth_peers = new;
1935 }
1936 arg = comma;
1937 } while (arg);
1938 break;
1939
1940 case 'S': /* --server */
1941 case LOPT_LOCAL: /* --local */
1942 case 'A': /* --address */
1943 case LOPT_NO_REBIND: /* --rebind-domain-ok */
1944 {
1945 struct server *serv, *newlist = NULL;
1946
1947 unhide_metas(arg);
1948
1949 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
1950 {
1951 int rebind = !(*arg == '/');
1952 char *end = NULL;
1953 if (!rebind)
1954 arg++;
1955 while (rebind || (end = split_chr(arg, '/')))
1956 {
1957 char *domain = NULL;
1958 /* elide leading dots - they are implied in the search algorithm */
1959 while (*arg == '.') arg++;
1960 /* # matches everything and becomes a zero length domain string */
1961 if (strcmp(arg, "#") == 0)
1962 domain = "";
1963 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1964 option = '?';
1965 serv = opt_malloc(sizeof(struct server));
1966 memset(serv, 0, sizeof(struct server));
1967 serv->next = newlist;
1968 newlist = serv;
1969 serv->domain = domain;
1970 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1971 arg = end;
1972 if (rebind)
1973 break;
1974 }
1975 if (!newlist)
1976 ret_err(gen_err);
1977 }
1978 else
1979 {
1980 newlist = opt_malloc(sizeof(struct server));
1981 memset(newlist, 0, sizeof(struct server));
1982 }
1983
1984 if (option == 'A')
1985 {
1986 newlist->flags |= SERV_LITERAL_ADDRESS;
1987 if (!(newlist->flags & SERV_TYPE))
1988 ret_err(gen_err);
1989 }
1990 else if (option == LOPT_NO_REBIND)
1991 newlist->flags |= SERV_NO_REBIND;
1992
1993 if (!arg || !*arg)
1994 {
1995 if (!(newlist->flags & SERV_NO_REBIND))
1996 newlist->flags |= SERV_NO_ADDR; /* no server */
1997 if (newlist->flags & SERV_LITERAL_ADDRESS)
1998 ret_err(gen_err);
1999 }
2000
2001 else if (strcmp(arg, "#") == 0)
2002 {
2003 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
2004 if (newlist->flags & SERV_LITERAL_ADDRESS)
2005 ret_err(gen_err);
2006 }
2007 else
2008 {
2009 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
2010 if (err)
2011 ret_err(err);
2012 }
2013
2014 serv = newlist;
2015 while (serv->next)
2016 {
2017 serv->next->flags = serv->flags;
2018 serv->next->addr = serv->addr;
2019 serv->next->source_addr = serv->source_addr;
2020 strcpy(serv->next->interface, serv->interface);
2021 serv = serv->next;
2022 }
2023 serv->next = daemon->servers;
2024 daemon->servers = newlist;
2025 break;
2026 }
2027
2028 case LOPT_IPSET: /* --ipset */
2029 #ifndef HAVE_IPSET
2030 ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
2031 break;
2032 #else
2033 {
2034 struct ipsets ipsets_head;
2035 struct ipsets *ipsets = &ipsets_head;
2036 int size;
2037 char *end;
2038 char **sets, **sets_pos;
2039 memset(ipsets, 0, sizeof(struct ipsets));
2040 unhide_metas(arg);
2041 if (arg && *arg == '/')
2042 {
2043 arg++;
2044 while ((end = split_chr(arg, '/')))
2045 {
2046 char *domain = NULL;
2047 /* elide leading dots - they are implied in the search algorithm */
2048 while (*arg == '.')
2049 arg++;
2050 /* # matches everything and becomes a zero length domain string */
2051 if (strcmp(arg, "#") == 0 || !*arg)
2052 domain = "";
2053 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
2054 option = '?';
2055 ipsets->next = opt_malloc(sizeof(struct ipsets));
2056 ipsets = ipsets->next;
2057 memset(ipsets, 0, sizeof(struct ipsets));
2058 ipsets->domain = domain;
2059 arg = end;
2060 }
2061 }
2062 else
2063 {
2064 ipsets->next = opt_malloc(sizeof(struct ipsets));
2065 ipsets = ipsets->next;
2066 memset(ipsets, 0, sizeof(struct ipsets));
2067 ipsets->domain = "";
2068 }
2069 if (!arg || !*arg)
2070 {
2071 option = '?';
2072 break;
2073 }
2074 size = 2;
2075 for (end = arg; *end; ++end)
2076 if (*end == ',')
2077 ++size;
2078
2079 sets = sets_pos = opt_malloc(sizeof(char *) * size);
2080
2081 do {
2082 end = split(arg);
2083 *sets_pos++ = opt_string_alloc(arg);
2084 arg = end;
2085 } while (end);
2086 *sets_pos = 0;
2087 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
2088 ipsets->next->sets = sets;
2089 ipsets->next = daemon->ipsets;
2090 daemon->ipsets = ipsets_head.next;
2091
2092 break;
2093 }
2094 #endif
2095
2096 case 'c': /* --cache-size */
2097 {
2098 int size;
2099
2100 if (!atoi_check(arg, &size))
2101 ret_err(gen_err);
2102 else
2103 {
2104 /* zero is OK, and means no caching. */
2105
2106 if (size < 0)
2107 size = 0;
2108 else if (size > 10000)
2109 size = 10000;
2110
2111 daemon->cachesize = size;
2112 }
2113 break;
2114 }
2115
2116 case 'p': /* --port */
2117 if (!atoi_check16(arg, &daemon->port))
2118 ret_err(gen_err);
2119 break;
2120
2121 case LOPT_MINPORT: /* --min-port */
2122 if (!atoi_check16(arg, &daemon->min_port))
2123 ret_err(gen_err);
2124 break;
2125
2126 case '0': /* --dns-forward-max */
2127 if (!atoi_check(arg, &daemon->ftabsize))
2128 ret_err(gen_err);
2129 break;
2130
2131 case LOPT_MAX_LOGS: /* --log-async */
2132 daemon->max_logs = LOG_MAX; /* default */
2133 if (arg && !atoi_check(arg, &daemon->max_logs))
2134 ret_err(gen_err);
2135 else if (daemon->max_logs > 100)
2136 daemon->max_logs = 100;
2137 break;
2138
2139 case 'P': /* --edns-packet-max */
2140 {
2141 int i;
2142 if (!atoi_check(arg, &i))
2143 ret_err(gen_err);
2144 daemon->edns_pktsz = (unsigned short)i;
2145 break;
2146 }
2147
2148 case 'Q': /* --query-port */
2149 if (!atoi_check16(arg, &daemon->query_port))
2150 ret_err(gen_err);
2151 /* if explicitly set to zero, use single OS ephemeral port
2152 and disable random ports */
2153 if (daemon->query_port == 0)
2154 daemon->osport = 1;
2155 break;
2156
2157 case 'T': /* --local-ttl */
2158 case LOPT_NEGTTL: /* --neg-ttl */
2159 case LOPT_MAXTTL: /* --max-ttl */
2160 case LOPT_MAXCTTL: /* --max-cache-ttl */
2161 case LOPT_AUTHTTL: /* --auth-ttl */
2162 {
2163 int ttl;
2164 if (!atoi_check(arg, &ttl))
2165 ret_err(gen_err);
2166 else if (option == LOPT_NEGTTL)
2167 daemon->neg_ttl = (unsigned long)ttl;
2168 else if (option == LOPT_MAXTTL)
2169 daemon->max_ttl = (unsigned long)ttl;
2170 else if (option == LOPT_MAXCTTL)
2171 daemon->max_cache_ttl = (unsigned long)ttl;
2172 else if (option == LOPT_AUTHTTL)
2173 daemon->auth_ttl = (unsigned long)ttl;
2174 else
2175 daemon->local_ttl = (unsigned long)ttl;
2176 break;
2177 }
2178
2179 #ifdef HAVE_DHCP
2180 case 'X': /* --dhcp-lease-max */
2181 if (!atoi_check(arg, &daemon->dhcp_max))
2182 ret_err(gen_err);
2183 break;
2184 #endif
2185
2186 #ifdef HAVE_TFTP
2187 case LOPT_TFTP_MAX: /* --tftp-max */
2188 if (!atoi_check(arg, &daemon->tftp_max))
2189 ret_err(gen_err);
2190 break;
2191
2192 case LOPT_PREFIX: /* --tftp-prefix */
2193 comma = split(arg);
2194 if (comma)
2195 {
2196 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2197 new->interface = opt_string_alloc(comma);
2198 new->prefix = opt_string_alloc(arg);
2199 new->next = daemon->if_prefix;
2200 daemon->if_prefix = new;
2201 }
2202 else
2203 daemon->tftp_prefix = opt_string_alloc(arg);
2204 break;
2205
2206 case LOPT_TFTPPORTS: /* --tftp-port-range */
2207 if (!(comma = split(arg)) ||
2208 !atoi_check16(arg, &daemon->start_tftp_port) ||
2209 !atoi_check16(comma, &daemon->end_tftp_port))
2210 ret_err(_("bad port range"));
2211
2212 if (daemon->start_tftp_port > daemon->end_tftp_port)
2213 {
2214 int tmp = daemon->start_tftp_port;
2215 daemon->start_tftp_port = daemon->end_tftp_port;
2216 daemon->end_tftp_port = tmp;
2217 }
2218
2219 break;
2220 #endif
2221
2222 case LOPT_BRIDGE: /* --bridge-interface */
2223 {
2224 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2225 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2226 ret_err(_("bad bridge-interface"));
2227
2228 strcpy(new->iface, arg);
2229 new->alias = NULL;
2230 new->next = daemon->bridges;
2231 daemon->bridges = new;
2232
2233 do {
2234 arg = comma;
2235 comma = split(arg);
2236 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2237 {
2238 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2239 b->next = new->alias;
2240 new->alias = b;
2241 strcpy(b->iface, arg);
2242 }
2243 } while (comma);
2244
2245 break;
2246 }
2247
2248 #ifdef HAVE_DHCP
2249 case 'F': /* --dhcp-range */
2250 {
2251 int k, leasepos = 2;
2252 char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2253 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2254
2255 memset (new, 0, sizeof(*new));
2256 new->lease_time = DEFLEASE;
2257
2258 if (!arg)
2259 {
2260 option = '?';
2261 break;
2262 }
2263
2264 while(1)
2265 {
2266 for (cp = arg; *cp; cp++)
2267 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2268 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2269 (*cp >='0' && *cp <= '9')))
2270 break;
2271
2272 if (*cp != ',' && (comma = split(arg)))
2273 {
2274 if (is_tag_prefix(arg))
2275 {
2276 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2277 tt->net = opt_string_alloc(arg+4);
2278 tt->next = new->filter;
2279 new->filter = tt;
2280 }
2281 else
2282 {
2283 if (new->netid.net)
2284 ret_err(_("only one tag allowed"));
2285 else if (strstr(arg, "set:") == arg)
2286 new->netid.net = opt_string_alloc(arg+4);
2287 else
2288 new->netid.net = opt_string_alloc(arg);
2289 }
2290 arg = comma;
2291 }
2292 else
2293 {
2294 a[0] = arg;
2295 break;
2296 }
2297 }
2298
2299 for (k = 1; k < 8; k++)
2300 if (!(a[k] = split(a[k-1])))
2301 break;
2302
2303 if (k < 2)
2304 ret_err(_("bad dhcp-range"));
2305
2306 if (inet_pton(AF_INET, a[0], &new->start))
2307 {
2308 new->next = daemon->dhcp;
2309 daemon->dhcp = new;
2310 new->end = new->start;
2311 if (strcmp(a[1], "static") == 0)
2312 new->flags |= CONTEXT_STATIC;
2313 else if (strcmp(a[1], "proxy") == 0)
2314 new->flags |= CONTEXT_PROXY;
2315 else if (!inet_pton(AF_INET, a[1], &new->end))
2316 ret_err(_("bad dhcp-range"));
2317
2318 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2319 {
2320 struct in_addr tmp = new->start;
2321 new->start = new->end;
2322 new->end = tmp;
2323 }
2324
2325 if (k >= 3 && strchr(a[2], '.') &&
2326 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
2327 {
2328 new->flags |= CONTEXT_NETMASK;
2329 leasepos = 3;
2330 if (!is_same_net(new->start, new->end, new->netmask))
2331 ret_err(_("inconsistent DHCP range"));
2332 }
2333
2334 if (k >= 4 && strchr(a[3], '.') &&
2335 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
2336 {
2337 new->flags |= CONTEXT_BRDCAST;
2338 leasepos = 4;
2339 }
2340 }
2341 #ifdef HAVE_DHCP6
2342 else if (inet_pton(AF_INET6, a[0], &new->start6))
2343 {
2344 new->prefix = 64; /* default */
2345 new->end6 = new->start6;
2346
2347 /* dhcp-range=:: enables DHCP stateless on any interface */
2348 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6))
2349 new->prefix = 0;
2350
2351 for (leasepos = 1; leasepos < k; leasepos++)
2352 {
2353 if (strcmp(a[leasepos], "static") == 0)
2354 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2355 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2356 new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
2357 else if (strcmp(a[leasepos], "ra-names") == 0)
2358 new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
2359 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2360 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
2361 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2362 new->flags |= CONTEXT_DHCP;
2363 else if (strstr(a[leasepos], "constructor:") == a[leasepos])
2364 {
2365 if (a[leasepos][strlen(a[leasepos])-1] == '*')
2366 {
2367 a[leasepos][strlen(a[leasepos])-1] = 0;
2368 new->flags |= CONTEXT_WILDCARD;
2369 }
2370 new->template_interface = opt_string_alloc(a[leasepos] + 12);
2371 new->flags |= CONTEXT_TEMPLATE;
2372 }
2373 else
2374 break;
2375 }
2376
2377 new->next = daemon->dhcp6;
2378 daemon->dhcp6 = new;
2379
2380 /* bare integer < 128 is prefix value */
2381 if (leasepos < k)
2382 {
2383 int pref;
2384 for (cp = a[leasepos]; *cp; cp++)
2385 if (!(*cp >= '0' && *cp <= '9'))
2386 break;
2387 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
2388 {
2389 new->prefix = pref;
2390 leasepos++;
2391 if (new->prefix != 64)
2392 {
2393 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
2394 ret_err(_("prefix must be exactly 64 for RA subnets"));
2395 else if (new->template_interface)
2396 ret_err(_("prefix must be exactly 64 for subnet constructors"));
2397 }
2398 if (new->prefix < 64)
2399 ret_err(_("prefix must be at least 64"));
2400 }
2401 }
2402
2403 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2404 ret_err(_("inconsistent DHCPv6 range"));
2405 if (addr6part(&new->start6) > addr6part(&new->end6))
2406 {
2407 struct in6_addr tmp = new->start6;
2408 new->start6 = new->end6;
2409 new->end6 = tmp;
2410 }
2411 }
2412 #endif
2413
2414 if (leasepos < k)
2415 {
2416 if (strcmp(a[leasepos], "infinite") == 0)
2417 new->lease_time = 0xffffffff;
2418 else if (strcmp(a[leasepos], "deprecated") == 0)
2419 new->flags |= CONTEXT_DEPRECATE;
2420 else
2421 {
2422 int fac = 1;
2423 if (strlen(a[leasepos]) > 0)
2424 {
2425 switch (a[leasepos][strlen(a[leasepos]) - 1])
2426 {
2427 case 'w':
2428 case 'W':
2429 fac *= 7;
2430 /* fall through */
2431 case 'd':
2432 case 'D':
2433 fac *= 24;
2434 /* fall though */
2435 case 'h':
2436 case 'H':
2437 fac *= 60;
2438 /* fall through */
2439 case 'm':
2440 case 'M':
2441 fac *= 60;
2442 /* fall through */
2443 case 's':
2444 case 'S':
2445 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2446 }
2447
2448 for (cp = a[leasepos]; *cp; cp++)
2449 if (!(*cp >= '0' && *cp <= '9'))
2450 break;
2451
2452 if (*cp || (leasepos+1 < k))
2453 ret_err(_("bad dhcp-range"));
2454
2455 new->lease_time = atoi(a[leasepos]) * fac;
2456 /* Leases of a minute or less confuse
2457 some clients, notably Apple's */
2458 if (new->lease_time < 120)
2459 new->lease_time = 120;
2460 }
2461 }
2462 }
2463 break;
2464 }
2465
2466 case LOPT_BANK:
2467 case 'G': /* --dhcp-host */
2468 {
2469 int j, k = 0;
2470 char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
2471 struct dhcp_config *new;
2472 struct in_addr in;
2473
2474 new = opt_malloc(sizeof(struct dhcp_config));
2475
2476 new->next = daemon->dhcp_conf;
2477 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2478 new->hwaddr = NULL;
2479 new->netid = NULL;
2480
2481 if ((a[0] = arg))
2482 for (k = 1; k < 6; k++)
2483 if (!(a[k] = split(a[k-1])))
2484 break;
2485
2486 for (j = 0; j < k; j++)
2487 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2488 {
2489 char *arg = a[j];
2490
2491 if ((arg[0] == 'i' || arg[0] == 'I') &&
2492 (arg[1] == 'd' || arg[1] == 'D') &&
2493 arg[2] == ':')
2494 {
2495 if (arg[3] == '*')
2496 new->flags |= CONFIG_NOCLID;
2497 else
2498 {
2499 int len;
2500 arg += 3; /* dump id: */
2501 if (strchr(arg, ':'))
2502 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2503 else
2504 {
2505 unhide_metas(arg);
2506 len = (int) strlen(arg);
2507 }
2508
2509 if (len == -1)
2510
2511 ret_err(_("bad hex constant"));
2512 else if ((new->clid = opt_malloc(len)))
2513 {
2514 new->flags |= CONFIG_CLID;
2515 new->clid_len = len;
2516 memcpy(new->clid, arg, len);
2517 }
2518 }
2519 }
2520 /* dhcp-host has strange backwards-compat needs. */
2521 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2522 {
2523 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2524 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2525 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2526 newlist->next = new->netid;
2527 new->netid = newlist;
2528 newlist->list = newtag;
2529 strcpy(newtag->net, arg+4);
2530 unhide_metas(newtag->net);
2531 }
2532 else if (strstr(arg, "tag:") == arg)
2533 ret_err(_("cannot match tags in --dhcp-host"));
2534 #ifdef HAVE_DHCP6
2535 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2536 {
2537 arg[strlen(arg)-1] = 0;
2538 arg++;
2539
2540 if (!inet_pton(AF_INET6, arg, &new->addr6))
2541 ret_err(_("bad IPv6 address"));
2542
2543 for (i= 0; i < 8; i++)
2544 if (new->addr6.s6_addr[i] != 0)
2545 break;
2546
2547 /* set WILDCARD if network part all zeros */
2548 if (i == 8)
2549 new->flags |= CONFIG_WILDCARD;
2550
2551 new->flags |= CONFIG_ADDR6;
2552 }
2553 #endif
2554 else
2555 {
2556 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2557 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2558 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2559 ret_err(_("bad hex constant"));
2560 else
2561 {
2562
2563 newhw->next = new->hwaddr;
2564 new->hwaddr = newhw;
2565 }
2566 }
2567 }
2568 else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
2569 {
2570 struct dhcp_config *configs;
2571
2572 new->addr = in;
2573 new->flags |= CONFIG_ADDR;
2574
2575 /* If the same IP appears in more than one host config, then DISCOVER
2576 for one of the hosts will get the address, but REQUEST will be NAKed,
2577 since the address is reserved by the other one -> protocol loop. */
2578 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2579 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2580 {
2581 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2582 return 0;
2583 }
2584 }
2585 else
2586 {
2587 char *cp, *lastp = NULL, last = 0;
2588 int fac = 1;
2589
2590 if (strlen(a[j]) > 1)
2591 {
2592 lastp = a[j] + strlen(a[j]) - 1;
2593 last = *lastp;
2594 switch (last)
2595 {
2596 case 'w':
2597 case 'W':
2598 fac *= 7;
2599 /* fall through */
2600 case 'd':
2601 case 'D':
2602 fac *= 24;
2603 /* fall through */
2604 case 'h':
2605 case 'H':
2606 fac *= 60;
2607 /* fall through */
2608 case 'm':
2609 case 'M':
2610 fac *= 60;
2611 /* fall through */
2612 case 's':
2613 case 'S':
2614 *lastp = 0;
2615 }
2616 }
2617
2618 for (cp = a[j]; *cp; cp++)
2619 if (!isdigit((unsigned char)*cp) && *cp != ' ')
2620 break;
2621
2622 if (*cp)
2623 {
2624 if (lastp)
2625 *lastp = last;
2626 if (strcmp(a[j], "infinite") == 0)
2627 {
2628 new->lease_time = 0xffffffff;
2629 new->flags |= CONFIG_TIME;
2630 }
2631 else if (strcmp(a[j], "ignore") == 0)
2632 new->flags |= CONFIG_DISABLE;
2633 else
2634 {
2635 if (!(new->hostname = canonicalise_opt(a[j])) ||
2636 !legal_hostname(new->hostname))
2637 ret_err(_("bad DHCP host name"));
2638
2639 new->flags |= CONFIG_NAME;
2640 new->domain = strip_hostname(new->hostname);
2641 }
2642 }
2643 else
2644 {
2645 new->lease_time = atoi(a[j]) * fac;
2646 /* Leases of a minute or less confuse
2647 some clients, notably Apple's */
2648 if (new->lease_time < 120)
2649 new->lease_time = 120;
2650 new->flags |= CONFIG_TIME;
2651 }
2652 }
2653
2654 daemon->dhcp_conf = new;
2655 break;
2656 }
2657
2658 case LOPT_TAG_IF: /* --tag-if */
2659 {
2660 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2661
2662 new->tag = NULL;
2663 new->set = NULL;
2664 new->next = NULL;
2665
2666 /* preserve order */
2667 if (!daemon->tag_if)
2668 daemon->tag_if = new;
2669 else
2670 {
2671 struct tag_if *tmp;
2672 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2673 tmp->next = new;
2674 }
2675
2676 while (arg)
2677 {
2678 size_t len;
2679
2680 comma = split(arg);
2681 len = strlen(arg);
2682
2683 if (len < 5)
2684 {
2685 new->set = NULL;
2686 break;
2687 }
2688 else
2689 {
2690 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2691 newtag->net = opt_malloc(len - 3);
2692 strcpy(newtag->net, arg+4);
2693 unhide_metas(newtag->net);
2694
2695 if (strstr(arg, "set:") == arg)
2696 {
2697 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2698 newlist->next = new->set;
2699 new->set = newlist;
2700 newlist->list = newtag;
2701 }
2702 else if (strstr(arg, "tag:") == arg)
2703 {
2704 newtag->next = new->tag;
2705 new->tag = newtag;
2706 }
2707 else
2708 {
2709 new->set = NULL;
2710 free(newtag);
2711 break;
2712 }
2713 }
2714
2715 arg = comma;
2716 }
2717
2718 if (!new->set)
2719 ret_err(_("bad tag-if"));
2720
2721 break;
2722 }
2723
2724
2725 case 'O': /* --dhcp-option */
2726 case LOPT_FORCE: /* --dhcp-option-force */
2727 case LOPT_OPTS:
2728 case LOPT_MATCH: /* --dhcp-match */
2729 return parse_dhcp_opt(errstr, arg,
2730 option == LOPT_FORCE ? DHOPT_FORCE :
2731 (option == LOPT_MATCH ? DHOPT_MATCH :
2732 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2733
2734 case 'M': /* --dhcp-boot */
2735 {
2736 struct dhcp_netid *id = NULL;
2737 while (is_tag_prefix(arg))
2738 {
2739 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2740 newid->next = id;
2741 id = newid;
2742 comma = split(arg);
2743 newid->net = opt_string_alloc(arg+4);
2744 arg = comma;
2745 };
2746
2747 if (!arg)
2748 ret_err(gen_err);
2749 else
2750 {
2751 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2752 struct in_addr dhcp_next_server;
2753 struct dhcp_boot *new;
2754 comma = split(arg);
2755 dhcp_file = opt_string_alloc(arg);
2756 dhcp_next_server.s_addr = 0;
2757 if (comma)
2758 {
2759 arg = comma;
2760 comma = split(arg);
2761 dhcp_sname = opt_string_alloc(arg);
2762 if (comma)
2763 {
2764 unhide_metas(comma);
2765 if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) {
2766
2767 /*
2768 * The user may have specified the tftp hostname here.
2769 * save it so that it can be resolved/looked up during
2770 * actual dhcp_reply().
2771 */
2772
2773 tftp_sname = opt_string_alloc(comma);
2774 dhcp_next_server.s_addr = 0;
2775 }
2776 }
2777 }
2778
2779 new = opt_malloc(sizeof(struct dhcp_boot));
2780 new->file = dhcp_file;
2781 new->sname = dhcp_sname;
2782 new->tftp_sname = tftp_sname;
2783 new->next_server = dhcp_next_server;
2784 new->netid = id;
2785 new->next = daemon->boot_config;
2786 daemon->boot_config = new;
2787 }
2788
2789 break;
2790 }
2791
2792 case LOPT_PXE_PROMT: /* --pxe-prompt */
2793 {
2794 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2795 int timeout;
2796
2797 new->netid = NULL;
2798 new->opt = 10; /* PXE_MENU_PROMPT */
2799
2800 while (is_tag_prefix(arg))
2801 {
2802 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2803 comma = split(arg);
2804 nn->next = new->netid;
2805 new->netid = nn;
2806 nn->net = opt_string_alloc(arg+4);
2807 arg = comma;
2808 }
2809
2810 if (!arg)
2811 ret_err(gen_err);
2812 else
2813 {
2814 comma = split(arg);
2815 unhide_metas(arg);
2816 new->len = strlen(arg) + 1;
2817 new->val = opt_malloc(new->len);
2818 memcpy(new->val + 1, arg, new->len - 1);
2819
2820 new->u.vendor_class = (unsigned char *)"PXEClient";
2821 new->flags = DHOPT_VENDOR;
2822
2823 if (comma && atoi_check(comma, &timeout))
2824 *(new->val) = timeout;
2825 else
2826 *(new->val) = 255;
2827
2828 new->next = daemon->dhcp_opts;
2829 daemon->dhcp_opts = new;
2830 daemon->enable_pxe = 1;
2831 }
2832
2833 break;
2834 }
2835
2836 case LOPT_PXE_SERV: /* --pxe-service */
2837 {
2838 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2839 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2840 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2841 static int boottype = 32768;
2842
2843 new->netid = NULL;
2844 new->sname = NULL;
2845 new->server.s_addr = 0;
2846
2847 while (is_tag_prefix(arg))
2848 {
2849 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2850 comma = split(arg);
2851 nn->next = new->netid;
2852 new->netid = nn;
2853 nn->net = opt_string_alloc(arg+4);
2854 arg = comma;
2855 }
2856
2857 if (arg && (comma = split(arg)))
2858 {
2859 for (i = 0; CSA[i]; i++)
2860 if (strcasecmp(CSA[i], arg) == 0)
2861 break;
2862
2863 if (CSA[i] || atoi_check(arg, &i))
2864 {
2865 arg = comma;
2866 comma = split(arg);
2867
2868 new->CSA = i;
2869 new->menu = opt_string_alloc(arg);
2870
2871 if (!comma)
2872 {
2873 new->type = 0; /* local boot */
2874 new->basename = NULL;
2875 }
2876 else
2877 {
2878 arg = comma;
2879 comma = split(arg);
2880 if (atoi_check(arg, &i))
2881 {
2882 new->type = i;
2883 new->basename = NULL;
2884 }
2885 else
2886 {
2887 new->type = boottype++;
2888 new->basename = opt_string_alloc(arg);
2889 }
2890
2891 if (comma)
2892 {
2893 if (!inet_pton(AF_INET, comma, &new->server))
2894 {
2895 new->server.s_addr = 0;
2896 new->sname = opt_string_alloc(comma);
2897 }
2898
2899 }
2900 }
2901
2902 /* Order matters */
2903 new->next = NULL;
2904 if (!daemon->pxe_services)
2905 daemon->pxe_services = new;
2906 else
2907 {
2908 struct pxe_service *s;
2909 for (s = daemon->pxe_services; s->next; s = s->next);
2910 s->next = new;
2911 }
2912
2913 daemon->enable_pxe = 1;
2914 break;
2915
2916 }
2917 }
2918
2919 ret_err(gen_err);
2920 }
2921
2922 case '4': /* --dhcp-mac */
2923 {
2924 if (!(comma = split(arg)))
2925 ret_err(gen_err);
2926 else
2927 {
2928 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2929 new->netid.net = opt_string_alloc(set_prefix(arg));
2930 unhide_metas(comma);
2931 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2932 if (new->hwaddr_len == -1)
2933 ret_err(gen_err);
2934 else
2935 {
2936 new->next = daemon->dhcp_macs;
2937 daemon->dhcp_macs = new;
2938 }
2939 }
2940 }
2941 break;
2942
2943 case 'U': /* --dhcp-vendorclass */
2944 case 'j': /* --dhcp-userclass */
2945 case LOPT_CIRCUIT: /* --dhcp-circuitid */
2946 case LOPT_REMOTE: /* --dhcp-remoteid */
2947 case LOPT_SUBSCR: /* --dhcp-subscrid */
2948 {
2949 unsigned char *p;
2950 int dig = 0;
2951 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2952
2953 if (!(comma = split(arg)))
2954 ret_err(gen_err);
2955
2956 new->netid.net = opt_string_alloc(set_prefix(arg));
2957 /* check for hex string - must digits may include : must not have nothing else,
2958 only allowed for agent-options. */
2959
2960 arg = comma;
2961 if ((comma = split(arg)))
2962 {
2963 if (option != 'U' || strstr(arg, "enterprise:") != arg)
2964 ret_err(gen_err);
2965 else
2966 new->enterprise = atoi(arg+11);
2967 }
2968 else
2969 comma = arg;
2970
2971 for (p = (unsigned char *)comma; *p; p++)
2972 if (isxdigit(*p))
2973 dig = 1;
2974 else if (*p != ':')
2975 break;
2976 unhide_metas(comma);
2977 if (option == 'U' || option == 'j' || *p || !dig)
2978 {
2979 new->len = strlen(comma);
2980 new->data = opt_malloc(new->len);
2981 memcpy(new->data, comma, new->len);
2982 }
2983 else
2984 {
2985 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2986 new->data = opt_malloc(new->len);
2987 memcpy(new->data, comma, new->len);
2988 }
2989
2990 switch (option)
2991 {
2992 case 'j':
2993 new->match_type = MATCH_USER;
2994 break;
2995 case 'U':
2996 new->match_type = MATCH_VENDOR;
2997 break;
2998 case LOPT_CIRCUIT:
2999 new->match_type = MATCH_CIRCUIT;
3000 break;
3001 case LOPT_REMOTE:
3002 new->match_type = MATCH_REMOTE;
3003 break;
3004 case LOPT_SUBSCR:
3005 new->match_type = MATCH_SUBSCRIBER;
3006 break;
3007 }
3008 new->next = daemon->dhcp_vendors;
3009 daemon->dhcp_vendors = new;
3010
3011 break;
3012 }
3013
3014 case LOPT_ALTPORT: /* --dhcp-alternate-port */
3015 if (!arg)
3016 {
3017 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
3018 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
3019 }
3020 else
3021 {
3022 comma = split(arg);
3023 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
3024 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
3025 ret_err(_("invalid port number"));
3026 if (!comma)
3027 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
3028 }
3029 break;
3030
3031 case 'J': /* --dhcp-ignore */
3032 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
3033 case LOPT_BROADCAST: /* --dhcp-broadcast */
3034 case '3': /* --bootp-dynamic */
3035 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
3036 {
3037 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
3038 struct dhcp_netid *list = NULL;
3039 if (option == 'J')
3040 {
3041 new->next = daemon->dhcp_ignore;
3042 daemon->dhcp_ignore = new;
3043 }
3044 else if (option == LOPT_BROADCAST)
3045 {
3046 new->next = daemon->force_broadcast;
3047 daemon->force_broadcast = new;
3048 }
3049 else if (option == '3')
3050 {
3051 new->next = daemon->bootp_dynamic;
3052 daemon->bootp_dynamic = new;
3053 }
3054 else if (option == LOPT_GEN_NAMES)
3055 {
3056 new->next = daemon->dhcp_gen_names;
3057 daemon->dhcp_gen_names = new;
3058 }
3059 else
3060 {
3061 new->next = daemon->dhcp_ignore_names;
3062 daemon->dhcp_ignore_names = new;
3063 }
3064
3065 while (arg) {
3066 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3067 comma = split(arg);
3068 member->next = list;
3069 list = member;
3070 if (is_tag_prefix(arg))
3071 member->net = opt_string_alloc(arg+4);
3072 else
3073 member->net = opt_string_alloc(arg);
3074 arg = comma;
3075 }
3076
3077 new->list = list;
3078 break;
3079 }
3080
3081 case LOPT_PROXY: /* --dhcp-proxy */
3082 daemon->override = 1;
3083 while (arg) {
3084 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3085 comma = split(arg);
3086 if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
3087 ret_err(_("bad dhcp-proxy address"));
3088 new->next = daemon->override_relays;
3089 daemon->override_relays = new;
3090 arg = comma;
3091 }
3092 break;
3093 #endif
3094
3095 #ifdef HAVE_DHCP6
3096 case LOPT_DUID: /* --dhcp-duid */
3097 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
3098 ret_err(_("bad DUID"));
3099 else
3100 {
3101 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
3102 daemon->duid_config = opt_malloc(daemon->duid_config_len);
3103 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
3104 }
3105 break;
3106 #endif
3107
3108 case 'V': /* --alias */
3109 {
3110 char *dash, *a[3] = { NULL, NULL, NULL };
3111 int k = 0;
3112 struct doctor *new = opt_malloc(sizeof(struct doctor));
3113 new->next = daemon->doctors;
3114 daemon->doctors = new;
3115 new->mask.s_addr = 0xffffffff;
3116 new->end.s_addr = 0;
3117
3118 if ((a[0] = arg))
3119 for (k = 1; k < 3; k++)
3120 {
3121 if (!(a[k] = split(a[k-1])))
3122 break;
3123 unhide_metas(a[k]);
3124 }
3125
3126 dash = split_chr(a[0], '-');
3127
3128 if ((k < 2) ||
3129 ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
3130 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
3131 option = '?';
3132
3133 if (k == 3)
3134 new->mask.s_addr = inet_addr(a[2]);
3135
3136 if (dash &&
3137 ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
3138 !is_same_net(new->in, new->end, new->mask) ||
3139 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3140 ret_err(_("invalid alias range"));
3141
3142 break;
3143 }
3144
3145 case LOPT_INTNAME: /* --interface-name */
3146 {
3147 struct interface_name *new, **up;
3148 char *domain = NULL;
3149
3150 comma = split(arg);
3151
3152 if (!comma || !(domain = canonicalise_opt(arg)))
3153 ret_err(_("bad interface name"));
3154
3155 new = opt_malloc(sizeof(struct interface_name));
3156 new->next = NULL;
3157 /* Add to the end of the list, so that first name
3158 of an interface is used for PTR lookups. */
3159 for (up = &daemon->int_names; *up; up = &((*up)->next));
3160 *up = new;
3161 new->name = domain;
3162 new->intr = opt_string_alloc(comma);
3163 break;
3164 }
3165
3166 case LOPT_CNAME: /* --cname */
3167 {
3168 struct cname *new;
3169 char *alias;
3170 char *target;
3171
3172 if (!(comma = split(arg)))
3173 ret_err(gen_err);
3174
3175 alias = canonicalise_opt(arg);
3176 target = canonicalise_opt(comma);
3177
3178 if (!alias || !target)
3179 ret_err(_("bad CNAME"));
3180 else
3181 {
3182 for (new = daemon->cnames; new; new = new->next)
3183 if (hostname_isequal(new->alias, arg))
3184 ret_err(_("duplicate CNAME"));
3185 new = opt_malloc(sizeof(struct cname));
3186 new->next = daemon->cnames;
3187 daemon->cnames = new;
3188 new->alias = alias;
3189 new->target = target;
3190 }
3191
3192 break;
3193 }
3194
3195 case LOPT_PTR: /* --ptr-record */
3196 {
3197 struct ptr_record *new;
3198 char *dom, *target = NULL;
3199
3200 comma = split(arg);
3201
3202 if (!(dom = canonicalise_opt(arg)) ||
3203 (comma && !(target = canonicalise_opt(comma))))
3204 ret_err(_("bad PTR record"));
3205 else
3206 {
3207 new = opt_malloc(sizeof(struct ptr_record));
3208 new->next = daemon->ptr;
3209 daemon->ptr = new;
3210 new->name = dom;
3211 new->ptr = target;
3212 }
3213 break;
3214 }
3215
3216 case LOPT_NAPTR: /* --naptr-record */
3217 {
3218 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3219 int k = 0;
3220 struct naptr *new;
3221 int order, pref;
3222 char *name, *replace = NULL;
3223
3224 if ((a[0] = arg))
3225 for (k = 1; k < 7; k++)
3226 if (!(a[k] = split(a[k-1])))
3227 break;
3228
3229
3230 if (k < 6 ||
3231 !(name = canonicalise_opt(a[0])) ||
3232 !atoi_check16(a[1], &order) ||
3233 !atoi_check16(a[2], &pref) ||
3234 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3235 ret_err(_("bad NAPTR record"));
3236 else
3237 {
3238 new = opt_malloc(sizeof(struct naptr));
3239 new->next = daemon->naptr;
3240 daemon->naptr = new;
3241 new->name = name;
3242 new->flags = opt_string_alloc(a[3]);
3243 new->services = opt_string_alloc(a[4]);
3244 new->regexp = opt_string_alloc(a[5]);
3245 new->replace = replace;
3246 new->order = order;
3247 new->pref = pref;
3248 }
3249 break;
3250 }
3251
3252 case LOPT_RR: /* dns-rr */
3253 {
3254 struct txt_record *new;
3255 size_t len;
3256 char *data;
3257 int val;
3258
3259 comma = split(arg);
3260 data = split(comma);
3261
3262 new = opt_malloc(sizeof(struct txt_record));
3263 new->next = daemon->rr;
3264 daemon->rr = new;
3265
3266 if (!atoi_check(comma, &val) ||
3267 !(new->name = canonicalise_opt(arg)) ||
3268 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
3269 ret_err(_("bad RR record"));
3270
3271 new->class = val;
3272 new->len = 0;
3273
3274 if (data)
3275 {
3276 new->txt=opt_malloc(len);
3277 new->len = len;
3278 memcpy(new->txt, data, len);
3279 }
3280
3281 break;
3282 }
3283
3284 case 'Y': /* --txt-record */
3285 {
3286 struct txt_record *new;
3287 unsigned char *p, *cnt;
3288 size_t len;
3289
3290 comma = split(arg);
3291
3292 new = opt_malloc(sizeof(struct txt_record));
3293 new->next = daemon->txt;
3294 daemon->txt = new;
3295 new->class = C_IN;
3296
3297 if (!(new->name = canonicalise_opt(arg)))
3298 ret_err(_("bad TXT record"));
3299
3300 len = comma ? strlen(comma) : 0;
3301 len += (len/255) + 1; /* room for extra counts */
3302 new->txt = p = opt_malloc(len);
3303
3304 cnt = p++;
3305 *cnt = 0;
3306
3307 while (comma && *comma)
3308 {
3309 unsigned char c = (unsigned char)*comma++;
3310
3311 if (c == ',' || *cnt == 255)
3312 {
3313 if (c != ',')
3314 comma--;
3315 cnt = p++;
3316 *cnt = 0;
3317 }
3318 else
3319 {
3320 *p++ = unhide_meta(c);
3321 (*cnt)++;
3322 }
3323 }
3324
3325 new->len = p - new->txt;
3326
3327 break;
3328 }
3329
3330 case 'W': /* --srv-host */
3331 {
3332 int port = 1, priority = 0, weight = 0;
3333 char *name, *target = NULL;
3334 struct mx_srv_record *new;
3335
3336 comma = split(arg);
3337
3338 if (!(name = canonicalise_opt(arg)))
3339 ret_err(_("bad SRV record"));
3340
3341 if (comma)
3342 {
3343 arg = comma;
3344 comma = split(arg);
3345 if (!(target = canonicalise_opt(arg)))
3346 ret_err(_("bad SRV target"));
3347
3348 if (comma)
3349 {
3350 arg = comma;
3351 comma = split(arg);
3352 if (!atoi_check16(arg, &port))
3353 ret_err(_("invalid port number"));
3354
3355 if (comma)
3356 {
3357 arg = comma;
3358 comma = split(arg);
3359 if (!atoi_check16(arg, &priority))
3360 ret_err(_("invalid priority"));
3361
3362 if (comma)
3363 {
3364 arg = comma;
3365 comma = split(arg);
3366 if (!atoi_check16(arg, &weight))
3367 ret_err(_("invalid weight"));
3368 }
3369 }
3370 }
3371 }
3372
3373 new = opt_malloc(sizeof(struct mx_srv_record));
3374 new->next = daemon->mxnames;
3375 daemon->mxnames = new;
3376 new->issrv = 1;
3377 new->name = name;
3378 new->target = target;
3379 new->srvport = port;
3380 new->priority = priority;
3381 new->weight = weight;
3382 break;
3383 }
3384
3385 case LOPT_HOST_REC: /* --host-record */
3386 {
3387 struct host_record *new = opt_malloc(sizeof(struct host_record));
3388 memset(new, 0, sizeof(struct host_record));
3389
3390 if (!arg || !(comma = split(arg)))
3391 ret_err(_("Bad host-record"));
3392
3393 while (arg)
3394 {
3395 struct all_addr addr;
3396 if (inet_pton(AF_INET, arg, &addr))
3397 new->addr = addr.addr.addr4;
3398 #ifdef HAVE_IPV6
3399 else if (inet_pton(AF_INET6, arg, &addr))
3400 new->addr6 = addr.addr.addr6;
3401 #endif
3402 else
3403 {
3404 int nomem;
3405 char *canon = canonicalise(arg, &nomem);
3406 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3407 if (!canon)
3408 ret_err(_("Bad name in host-record"));
3409
3410 nl->name = canon;
3411 /* keep order, so that PTR record goes to first name */
3412 nl->next = NULL;
3413 if (!new->names)
3414 new->names = nl;
3415 else
3416 {
3417 struct name_list *tmp;
3418 for (tmp = new->names; tmp->next; tmp = tmp->next);
3419 tmp->next = nl;
3420 }
3421 }
3422
3423 arg = comma;
3424 comma = split(arg);
3425 }
3426
3427 /* Keep list order */
3428 if (!daemon->host_records_tail)
3429 daemon->host_records = new;
3430 else
3431 daemon->host_records_tail->next = new;
3432 new->next = NULL;
3433 daemon->host_records_tail = new;
3434 break;
3435 }
3436
3437 default:
3438 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3439
3440 }
3441
3442 return 1;
3443 }
3444
3445 static void read_file(char *file, FILE *f, int hard_opt)
3446 {
3447 volatile int lineno = 0;
3448 char *buff = daemon->namebuff;
3449
3450 while (fgets(buff, MAXDNAME, f))
3451 {
3452 int white, i, option = hard_opt;
3453 char *errmess, *p, *arg = NULL, *start;
3454 size_t len;
3455
3456 /* Memory allocation failure longjmps here if mem_recover == 1 */
3457 if (option != 0)
3458 {
3459 if (setjmp(mem_jmp))
3460 continue;
3461 mem_recover = 1;
3462 }
3463
3464 lineno++;
3465 errmess = NULL;
3466
3467 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3468 metacharacters get hidden also strip comments */
3469 for (white = 1, p = buff; *p; p++)
3470 {
3471 if (*p == '"')
3472 {
3473 memmove(p, p+1, strlen(p+1)+1);
3474
3475 for(; *p && *p != '"'; p++)
3476 {
3477 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3478 {
3479 if (p[1] == 't')
3480 p[1] = '\t';
3481 else if (p[1] == 'n')
3482 p[1] = '\n';
3483 else if (p[1] == 'b')
3484 p[1] = '\b';
3485 else if (p[1] == 'r')
3486 p[1] = '\r';
3487 else if (p[1] == 'e') /* escape */
3488 p[1] = '\033';
3489 memmove(p, p+1, strlen(p+1)+1);
3490 }
3491 *p = hide_meta(*p);
3492 }
3493
3494 if (*p == 0)
3495 {
3496 errmess = _("missing \"");
3497 goto oops;
3498 }
3499
3500 memmove(p, p+1, strlen(p+1)+1);
3501 }
3502
3503 if (isspace(*p))
3504 {
3505 *p = ' ';
3506 white = 1;
3507 }
3508 else
3509 {
3510 if (white && *p == '#')
3511 {
3512 *p = 0;
3513 break;
3514 }
3515 white = 0;
3516 }
3517 }
3518
3519
3520 /* strip leading spaces */
3521 for (start = buff; *start && *start == ' '; start++);
3522
3523 /* strip trailing spaces */
3524 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3525
3526 if (len == 0)
3527 continue;
3528 else
3529 start[len] = 0;
3530
3531 if (option != 0)
3532 arg = start;
3533 else if ((p=strchr(start, '=')))
3534 {
3535 /* allow spaces around "=" */
3536 for (arg = p+1; *arg == ' '; arg++);
3537 for (; p >= start && (*p == ' ' || *p == '='); p--)
3538 *p = 0;
3539 }
3540 else
3541 arg = NULL;
3542
3543 if (option == 0)
3544 {
3545 for (option = 0, i = 0; opts[i].name; i++)
3546 if (strcmp(opts[i].name, start) == 0)
3547 {
3548 option = opts[i].val;
3549 break;
3550 }
3551
3552 if (!option)
3553 errmess = _("bad option");
3554 else if (opts[i].has_arg == 0 && arg)
3555 errmess = _("extraneous parameter");
3556 else if (opts[i].has_arg == 1 && !arg)
3557 errmess = _("missing parameter");
3558 }
3559
3560 oops:
3561 if (errmess)
3562 strcpy(daemon->namebuff, errmess);
3563
3564 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
3565 {
3566 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
3567 if (hard_opt != 0)
3568 my_syslog(LOG_ERR, "%s", daemon->namebuff);
3569 else
3570 die("%s", daemon->namebuff, EC_BADCONF);
3571 }
3572 }
3573
3574 mem_recover = 0;
3575 fclose(f);
3576 }
3577
3578 static int one_file(char *file, int hard_opt)
3579 {
3580 FILE *f;
3581 int nofile_ok = 0;
3582 static int read_stdin = 0;
3583 static struct fileread {
3584 dev_t dev;
3585 ino_t ino;
3586 struct fileread *next;
3587 } *filesread = NULL;
3588
3589 if (hard_opt == '7')
3590 {
3591 /* default conf-file reading */
3592 hard_opt = 0;
3593 nofile_ok = 1;
3594 }
3595
3596 if (hard_opt == 0 && strcmp(file, "-") == 0)
3597 {
3598 if (read_stdin == 1)
3599 return 1;
3600 read_stdin = 1;
3601 file = "stdin";
3602 f = stdin;
3603 }
3604 else
3605 {
3606 /* ignore repeated files. */
3607 struct stat statbuf;
3608
3609 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3610 {
3611 struct fileread *r;
3612
3613 for (r = filesread; r; r = r->next)
3614 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3615 return 1;
3616
3617 r = safe_malloc(sizeof(struct fileread));
3618 r->next = filesread;
3619 filesread = r;
3620 r->dev = statbuf.st_dev;
3621 r->ino = statbuf.st_ino;
3622 }
3623
3624 if (!(f = fopen(file, "r")))
3625 {
3626 if (errno == ENOENT && nofile_ok)
3627 return 1; /* No conffile, all done. */
3628 else
3629 {
3630 char *str = _("cannot read %s: %s");
3631 if (hard_opt != 0)
3632 {
3633 my_syslog(LOG_ERR, str, file, strerror(errno));
3634 return 0;
3635 }
3636 else
3637 die(str, file, EC_FILE);
3638 }
3639 }
3640 }
3641
3642 read_file(file, f, hard_opt);
3643 return 1;
3644 }
3645
3646 /* expand any name which is a directory */
3647 struct hostsfile *expand_filelist(struct hostsfile *list)
3648 {
3649 int i;
3650 struct hostsfile *ah;
3651
3652 for (i = 0, ah = list; ah; ah = ah->next)
3653 {
3654 if (i <= ah->index)
3655 i = ah->index + 1;
3656
3657 if (ah->flags & AH_DIR)
3658 ah->flags |= AH_INACTIVE;
3659 else
3660 ah->flags &= ~AH_INACTIVE;
3661 }
3662
3663 for (ah = list; ah; ah = ah->next)
3664 if (!(ah->flags & AH_INACTIVE))
3665 {
3666 struct stat buf;
3667 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3668 {
3669 DIR *dir_stream;
3670 struct dirent *ent;
3671
3672 /* don't read this as a file */
3673 ah->flags |= AH_INACTIVE;
3674
3675 if (!(dir_stream = opendir(ah->fname)))
3676 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3677 ah->fname, strerror(errno));
3678 else
3679 {
3680 while ((ent = readdir(dir_stream)))
3681 {
3682 size_t lendir = strlen(ah->fname);
3683 size_t lenfile = strlen(ent->d_name);
3684 struct hostsfile *ah1;
3685 char *path;
3686
3687 /* ignore emacs backups and dotfiles */
3688 if (lenfile == 0 ||
3689 ent->d_name[lenfile - 1] == '~' ||
3690 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3691 ent->d_name[0] == '.')
3692 continue;
3693
3694 /* see if we have an existing record.
3695 dir is ah->fname
3696 file is ent->d_name
3697 path to match is ah1->fname */
3698
3699 for (ah1 = list; ah1; ah1 = ah1->next)
3700 {
3701 if (lendir < strlen(ah1->fname) &&
3702 strstr(ah1->fname, ah->fname) == ah1->fname &&
3703 ah1->fname[lendir] == '/' &&
3704 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3705 {
3706 ah1->flags &= ~AH_INACTIVE;
3707 break;
3708 }
3709 }
3710
3711 /* make new record */
3712 if (!ah1)
3713 {
3714 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3715 continue;
3716
3717 if (!(path = whine_malloc(lendir + lenfile + 2)))
3718 {
3719 free(ah1);
3720 continue;
3721 }
3722
3723 strcpy(path, ah->fname);
3724 strcat(path, "/");
3725 strcat(path, ent->d_name);
3726 ah1->fname = path;
3727 ah1->index = i++;
3728 ah1->flags = AH_DIR;
3729 ah1->next = list;
3730 list = ah1;
3731 }
3732
3733 /* inactivate record if not regular file */
3734 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3735 ah1->flags |= AH_INACTIVE;
3736
3737 }
3738 closedir(dir_stream);
3739 }
3740 }
3741 }
3742
3743 return list;
3744 }
3745
3746
3747 #ifdef HAVE_DHCP
3748 void reread_dhcp(void)
3749 {
3750 struct hostsfile *hf;
3751
3752 if (daemon->dhcp_hosts_file)
3753 {
3754 struct dhcp_config *configs, *cp, **up;
3755
3756 /* remove existing... */
3757 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3758 {
3759 cp = configs->next;
3760
3761 if (configs->flags & CONFIG_BANK)
3762 {
3763 struct hwaddr_config *mac, *tmp;
3764 struct dhcp_netid_list *list, *tmplist;
3765
3766 for (mac = configs->hwaddr; mac; mac = tmp)
3767 {
3768 tmp = mac->next;
3769 free(mac);
3770 }
3771
3772 if (configs->flags & CONFIG_CLID)
3773 free(configs->clid);
3774
3775 for (list = configs->netid; list; list = tmplist)
3776 {
3777 free(list->list);
3778 tmplist = list->next;
3779 free(list);
3780 }
3781
3782 if (configs->flags & CONFIG_NAME)
3783 free(configs->hostname);
3784
3785 *up = configs->next;
3786 free(configs);
3787 }
3788 else
3789 up = &configs->next;
3790 }
3791
3792 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3793 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3794 if (!(hf->flags & AH_INACTIVE))
3795 {
3796 if (one_file(hf->fname, LOPT_BANK))
3797 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3798 }
3799 }
3800
3801 if (daemon->dhcp_opts_file)
3802 {
3803 struct dhcp_opt *opts, *cp, **up;
3804 struct dhcp_netid *id, *next;
3805
3806 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3807 {
3808 cp = opts->next;
3809
3810 if (opts->flags & DHOPT_BANK)
3811 {
3812 if ((opts->flags & DHOPT_VENDOR))
3813 free(opts->u.vendor_class);
3814 free(opts->val);
3815 for (id = opts->netid; id; id = next)
3816 {
3817 next = id->next;
3818 free(id->net);
3819 free(id);
3820 }
3821 *up = opts->next;
3822 free(opts);
3823 }
3824 else
3825 up = &opts->next;
3826 }
3827
3828 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3829 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3830 if (!(hf->flags & AH_INACTIVE))
3831 {
3832 if (one_file(hf->fname, LOPT_OPTS))
3833 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3834 }
3835 }
3836 }
3837 #endif
3838
3839 void read_opts(int argc, char **argv, char *compile_opts)
3840 {
3841 char *buff = opt_malloc(MAXDNAME);
3842 int option, conffile_opt = '7', testmode = 0;
3843 char *arg, *conffile = CONFFILE;
3844
3845 opterr = 0;
3846
3847 daemon = opt_malloc(sizeof(struct daemon));
3848 memset(daemon, 0, sizeof(struct daemon));
3849 daemon->namebuff = buff;
3850
3851 /* Set defaults - everything else is zero or NULL */
3852 daemon->cachesize = CACHESIZ;
3853 daemon->ftabsize = FTABSIZ;
3854 daemon->port = NAMESERVER_PORT;
3855 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3856 daemon->dhcp_server_port = DHCP_SERVER_PORT;
3857 daemon->default_resolv.is_default = 1;
3858 daemon->default_resolv.name = RESOLVFILE;
3859 daemon->resolv_files = &daemon->default_resolv;
3860 daemon->username = CHUSER;
3861 daemon->runfile = RUNFILE;
3862 daemon->dhcp_max = MAXLEASES;
3863 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
3864 daemon->edns_pktsz = EDNS_PKTSZ;
3865 daemon->log_fac = -1;
3866 daemon->auth_ttl = AUTH_TTL;
3867 daemon->soa_refresh = SOA_REFRESH;
3868 daemon->soa_retry = SOA_RETRY;
3869 daemon->soa_expiry = SOA_EXPIRY;
3870 add_txt("version.bind", "dnsmasq-" VERSION );
3871 add_txt("authors.bind", "Simon Kelley");
3872 add_txt("copyright.bind", COPYRIGHT);
3873
3874 while (1)
3875 {
3876 #ifdef HAVE_GETOPT_LONG
3877 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
3878 #else
3879 option = getopt(argc, argv, OPTSTRING);
3880 #endif
3881
3882 if (option == -1)
3883 {
3884 for (; optind < argc; optind++)
3885 {
3886 unsigned char *c = (unsigned char *)argv[optind];
3887 for (; *c != 0; c++)
3888 if (!isspace(*c))
3889 die(_("junk found in command line"), NULL, EC_BADCONF);
3890 }
3891 break;
3892 }
3893
3894 /* Copy optarg so that argv doesn't get changed */
3895 if (optarg)
3896 {
3897 strncpy(buff, optarg, MAXDNAME);
3898 buff[MAXDNAME-1] = 0;
3899 arg = buff;
3900 }
3901 else
3902 arg = NULL;
3903
3904 /* command-line only stuff */
3905 if (option == LOPT_TEST)
3906 testmode = 1;
3907 else if (option == 'w')
3908 {
3909 #ifdef HAVE_DHCP
3910 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
3911 display_opts();
3912 #ifdef HAVE_DHCP6
3913 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
3914 display_opts6();
3915 #endif
3916 else
3917 #endif
3918 do_usage();
3919
3920 exit(0);
3921 }
3922 else if (option == 'v')
3923 {
3924 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
3925 printf(_("Compile time options: %s\n\n"), compile_opts);
3926 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
3927 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
3928 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
3929 exit(0);
3930 }
3931 else if (option == 'C')
3932 {
3933 conffile_opt = 0; /* file must exist */
3934 conffile = opt_string_alloc(arg);
3935 }
3936 else
3937 {
3938 #ifdef HAVE_GETOPT_LONG
3939 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
3940 #else
3941 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
3942 #endif
3943 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
3944 }
3945 }
3946
3947 if (conffile)
3948 one_file(conffile, conffile_opt);
3949
3950 /* port might not be known when the address is parsed - fill in here */
3951 if (daemon->servers)
3952 {
3953 struct server *tmp;
3954 for (tmp = daemon->servers; tmp; tmp = tmp->next)
3955 if (!(tmp->flags & SERV_HAS_SOURCE))
3956 {
3957 if (tmp->source_addr.sa.sa_family == AF_INET)
3958 tmp->source_addr.in.sin_port = htons(daemon->query_port);
3959 #ifdef HAVE_IPV6
3960 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3961 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
3962 #endif
3963 }
3964 }
3965
3966 if (daemon->if_addrs)
3967 {
3968 struct iname *tmp;
3969 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
3970 if (tmp->addr.sa.sa_family == AF_INET)
3971 tmp->addr.in.sin_port = htons(daemon->port);
3972 #ifdef HAVE_IPV6
3973 else if (tmp->addr.sa.sa_family == AF_INET6)
3974 tmp->addr.in6.sin6_port = htons(daemon->port);
3975 #endif /* IPv6 */
3976 }
3977
3978 /* create default, if not specified */
3979 if (daemon->authserver && !daemon->hostmaster)
3980 {
3981 strcpy(buff, "hostmaster.");
3982 strcat(buff, daemon->authserver);
3983 daemon->hostmaster = opt_string_alloc(buff);
3984 }
3985
3986 /* only one of these need be specified: the other defaults to the host-name */
3987 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
3988 {
3989 struct mx_srv_record *mx;
3990
3991 if (gethostname(buff, MAXDNAME) == -1)
3992 die(_("cannot get host-name: %s"), NULL, EC_MISC);
3993
3994 for (mx = daemon->mxnames; mx; mx = mx->next)
3995 if (!mx->issrv && hostname_isequal(mx->name, buff))
3996 break;
3997
3998 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
3999 {
4000 mx = opt_malloc(sizeof(struct mx_srv_record));
4001 mx->next = daemon->mxnames;
4002 mx->issrv = 0;
4003 mx->target = NULL;
4004 mx->name = opt_string_alloc(buff);
4005 daemon->mxnames = mx;
4006 }
4007
4008 if (!daemon->mxtarget)
4009 daemon->mxtarget = opt_string_alloc(buff);
4010
4011 for (mx = daemon->mxnames; mx; mx = mx->next)
4012 if (!mx->issrv && !mx->target)
4013 mx->target = daemon->mxtarget;
4014 }
4015
4016 if (!option_bool(OPT_NO_RESOLV) &&
4017 daemon->resolv_files &&
4018 daemon->resolv_files->next &&
4019 option_bool(OPT_NO_POLL))
4020 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
4021
4022 if (option_bool(OPT_RESOLV_DOMAIN))
4023 {
4024 char *line;
4025 FILE *f;
4026
4027 if (option_bool(OPT_NO_RESOLV) ||
4028 !daemon->resolv_files ||
4029 (daemon->resolv_files)->next)
4030 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
4031
4032 if (!(f = fopen((daemon->resolv_files)->name, "r")))
4033 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
4034
4035 while ((line = fgets(buff, MAXDNAME, f)))
4036 {
4037 char *token = strtok(line, " \t\n\r");
4038
4039 if (!token || strcmp(token, "search") != 0)
4040 continue;
4041
4042 if ((token = strtok(NULL, " \t\n\r")) &&
4043 (daemon->domain_suffix = canonicalise_opt(token)))
4044 break;
4045 }
4046
4047 fclose(f);
4048
4049 if (!daemon->domain_suffix)
4050 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
4051 }
4052
4053 if (daemon->domain_suffix)
4054 {
4055 /* add domain for any srv record without one. */
4056 struct mx_srv_record *srv;
4057
4058 for (srv = daemon->mxnames; srv; srv = srv->next)
4059 if (srv->issrv &&
4060 strchr(srv->name, '.') &&
4061 strchr(srv->name, '.') == strrchr(srv->name, '.'))
4062 {
4063 strcpy(buff, srv->name);
4064 strcat(buff, ".");
4065 strcat(buff, daemon->domain_suffix);
4066 free(srv->name);
4067 srv->name = opt_string_alloc(buff);
4068 }
4069 }
4070 else if (option_bool(OPT_DHCP_FQDN))
4071 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
4072
4073 if (testmode)
4074 {
4075 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
4076 exit(0);
4077 }
4078 }