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