1 /* dnsmasq is Copyright (c) 2000-2009 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 void one_file(char *file, int nest, 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_LISTNMARK 294
106
107 #ifdef HAVE_GETOPT_LONG
108 static const struct option opts[] =
109 #else
110 static const struct myoption opts[] =
111 #endif
112 {
113 { "version", 0, 0, 'v' },
114 { "no-hosts", 0, 0, 'h' },
115 { "no-poll", 0, 0, 'n' },
116 { "help", 0, 0, 'w' },
117 { "no-daemon", 0, 0, 'd' },
118 { "log-queries", 0, 0, 'q' },
119 { "user", 2, 0, 'u' },
120 { "group", 2, 0, 'g' },
121 { "resolv-file", 2, 0, 'r' },
122 { "mx-host", 1, 0, 'm' },
123 { "mx-target", 1, 0, 't' },
124 { "cache-size", 2, 0, 'c' },
125 { "port", 1, 0, 'p' },
126 { "dhcp-leasefile", 2, 0, 'l' },
127 { "dhcp-lease", 1, 0, 'l' },
128 { "dhcp-host", 1, 0, 'G' },
129 { "dhcp-range", 1, 0, 'F' },
130 { "dhcp-option", 1, 0, 'O' },
131 { "dhcp-boot", 1, 0, 'M' },
132 { "domain", 1, 0, 's' },
133 { "domain-suffix", 1, 0, 's' },
134 { "interface", 1, 0, 'i' },
135 { "listen-address", 1, 0, 'a' },
136 { "bogus-priv", 0, 0, 'b' },
137 { "bogus-nxdomain", 1, 0, 'B' },
138 { "selfmx", 0, 0, 'e' },
139 { "filterwin2k", 0, 0, 'f' },
140 { "pid-file", 2, 0, 'x' },
141 { "strict-order", 0, 0, 'o' },
142 { "server", 1, 0, 'S' },
143 { "local", 1, 0, LOPT_LOCAL },
144 { "address", 1, 0, 'A' },
145 { "conf-file", 2, 0, 'C' },
146 { "no-resolv", 0, 0, 'R' },
147 { "expand-hosts", 0, 0, 'E' },
148 { "localmx", 0, 0, 'L' },
149 { "local-ttl", 1, 0, 'T' },
150 { "no-negcache", 0, 0, 'N' },
151 { "addn-hosts", 1, 0, 'H' },
152 { "query-port", 1, 0, 'Q' },
153 { "except-interface", 1, 0, 'I' },
154 { "no-dhcp-interface", 1, 0, '2' },
155 { "domain-needed", 0, 0, 'D' },
156 { "dhcp-lease-max", 1, 0, 'X' },
157 { "bind-interfaces", 0, 0, 'z' },
158 { "read-ethers", 0, 0, 'Z' },
159 { "alias", 1, 0, 'V' },
160 { "dhcp-vendorclass", 1, 0, 'U' },
161 { "dhcp-userclass", 1, 0, 'j' },
162 { "dhcp-ignore", 1, 0, 'J' },
163 { "edns-packet-max", 1, 0, 'P' },
164 { "keep-in-foreground", 0, 0, 'k' },
165 { "dhcp-authoritative", 0, 0, 'K' },
166 { "srv-host", 1, 0, 'W' },
167 { "localise-queries", 0, 0, 'y' },
168 { "txt-record", 1, 0, 'Y' },
169 { "enable-dbus", 0, 0, '1' },
170 { "bootp-dynamic", 2, 0, '3' },
171 { "dhcp-mac", 1, 0, '4' },
172 { "no-ping", 0, 0, '5' },
173 { "dhcp-script", 1, 0, '6' },
174 { "conf-dir", 1, 0, '7' },
175 { "log-facility", 1, 0 ,'8' },
176 { "leasefile-ro", 0, 0, '9' },
177 { "dns-forward-max", 1, 0, '0' },
178 { "clear-on-reload", 0, 0, LOPT_RELOAD },
179 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
180 { "enable-tftp", 0, 0, LOPT_TFTP },
181 { "tftp-secure", 0, 0, LOPT_SECURE },
182 { "tftp-unique-root", 0, 0, LOPT_APREF },
183 { "tftp-root", 1, 0, LOPT_PREFIX },
184 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
185 { "ptr-record", 1, 0, LOPT_PTR },
186 { "naptr-record", 1, 0, LOPT_NAPTR },
187 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
188 { "dhcp-option-force", 1, 0, LOPT_FORCE },
189 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
190 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
191 { "log-async", 2, 0, LOPT_MAX_LOGS },
192 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
193 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
194 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
195 { "interface-name", 1, 0, LOPT_INTNAME },
196 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
197 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
198 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
199 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
200 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
201 { "all-servers", 0, 0, LOPT_NOLAST },
202 { "dhcp-match", 1, 0, LOPT_MATCH },
203 { "dhcp-broadcast", 1, 0, LOPT_BROADCAST },
204 { "neg-ttl", 1, 0, LOPT_NEGTTL },
205 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
206 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
207 { "min-port", 1, 0, LOPT_MINPORT },
208 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
209 { "cname", 1, 0, LOPT_CNAME },
210 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
211 { "pxe-service", 1, 0, LOPT_PXE_SERV },
212 #ifdef __ANDROID__
213 { "listen-mark", 1, 0, LOPT_LISTNMARK },
214 #endif /* __ANDROID__ */
215 { "test", 0, 0, LOPT_TEST },
216 { NULL, 0, 0, 0 }
217 };
218
219 /* These must have more the one '1' bit */
220 #define ARG_DUP 3
221 #define ARG_ONE 5
222 #define ARG_USED_CL 7
223 #define ARG_USED_FILE 9
224
225 static struct {
226 int opt;
227 unsigned int rept;
228 char * const flagdesc;
229 char * const desc;
230 char * const arg;
231 } usage[] = {
232 { 'a', ARG_DUP, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL },
233 { 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
234 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
235 { 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
236 { 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
237 { 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
238 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
239 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
240 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
241 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
242 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
243 { 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
244 { 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
245 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
246 { LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
247 { LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL },
248 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
249 { 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
250 { 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
251 { 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
252 { 'j', ARG_DUP, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
253 { LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
254 { LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
255 { LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
256 { 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
257 { LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
258 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
259 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
260 { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
261 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
262 { 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
263 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
264 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
265 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
266 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
267 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
268 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
269 { 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
270 { 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
271 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
272 { 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
273 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
274 { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
275 { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
276 { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
277 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
278 { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
279 { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
280 { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
281 { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
282 { 'U', ARG_DUP, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
283 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
284 { 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
285 { 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
286 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
287 { 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
288 { 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
289 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
290 { 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
291 { LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL },
292 { LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
293 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
294 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
295 { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
296 { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
297 { '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
298 { '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
299 { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
300 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
301 { '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
302 { '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
303 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
304 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
305 { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
306 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
307 { LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
308 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
309 { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
310 { LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
311 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
312 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
313 { LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
314 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
315 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
316 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
317 { LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
318 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
319 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
320 { LOPT_MATCH, ARG_DUP, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
321 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
322 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
323 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
324 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
325 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
326 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
327 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
328 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
329 { LOPT_LISTNMARK, ARG_ONE, NULL, gettext_noop("Socket mark to use for listen sockets."), NULL },
330 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
331 { 0, 0, NULL, NULL, NULL }
332 };
333
334 #ifdef HAVE_DHCP
335 /* makes options which take a list of addresses */
336 #define OT_ADDR_LIST 0x80
337 /* DHCP-internal options, for logging. not valid in config file */
338 #define OT_INTERNAL 0x40
339 #define OT_NAME 0x20
340
341 static const struct {
342 char *name;
343 unsigned char val, size;
344 } opttab[] = {
345 { "netmask", 1, OT_ADDR_LIST },
346 { "time-offset", 2, 4 },
347 { "router", 3, OT_ADDR_LIST },
348 { "dns-server", 6, OT_ADDR_LIST },
349 { "log-server", 7, OT_ADDR_LIST },
350 { "lpr-server", 9, OT_ADDR_LIST },
351 { "hostname", 12, OT_INTERNAL | OT_NAME },
352 { "boot-file-size", 13, 2 },
353 { "domain-name", 15, OT_NAME },
354 { "swap-server", 16, OT_ADDR_LIST },
355 { "root-path", 17, 0 },
356 { "extension-path", 18, 0 },
357 { "ip-forward-enable", 19, 1 },
358 { "non-local-source-routing", 20, 1 },
359 { "policy-filter", 21, OT_ADDR_LIST },
360 { "max-datagram-reassembly", 22, 2 },
361 { "default-ttl", 23, 1 },
362 { "mtu", 26, 2 },
363 { "all-subnets-local", 27, 1 },
364 { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
365 { "router-discovery", 31, 1 },
366 { "router-solicitation", 32, OT_ADDR_LIST },
367 { "static-route", 33, OT_ADDR_LIST },
368 { "trailer-encapsulation", 34, 1 },
369 { "arp-timeout", 35, 4 },
370 { "ethernet-encap", 36, 1 },
371 { "tcp-ttl", 37, 1 },
372 { "tcp-keepalive", 38, 4 },
373 { "nis-domain", 40, 0 },
374 { "nis-server", 41, OT_ADDR_LIST },
375 { "ntp-server", 42, OT_ADDR_LIST },
376 { "vendor-encap", 43, OT_INTERNAL },
377 { "netbios-ns", 44, OT_ADDR_LIST },
378 { "netbios-dd", 45, OT_ADDR_LIST },
379 { "netbios-nodetype", 46, 1 },
380 { "netbios-scope", 47, 0 },
381 { "x-windows-fs", 48, OT_ADDR_LIST },
382 { "x-windows-dm", 49, OT_ADDR_LIST },
383 { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
384 { "lease-time", 51, OT_INTERNAL },
385 { "option-overload", 52, OT_INTERNAL },
386 { "message-type", 53, OT_INTERNAL, },
387 { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
388 { "parameter-request", 55, OT_INTERNAL },
389 { "message", 56, OT_INTERNAL },
390 { "max-message-size", 57, OT_INTERNAL },
391 { "T1", 58, OT_INTERNAL },
392 { "T2", 59, OT_INTERNAL },
393 { "vendor-class", 60, 0 },
394 { "client-id", 61,OT_INTERNAL },
395 { "nis+-domain", 64, 0 },
396 { "nis+-server", 65, OT_ADDR_LIST },
397 { "tftp-server", 66, 0 },
398 { "bootfile-name", 67, 0 },
399 { "mobile-ip-home", 68, OT_ADDR_LIST },
400 { "smtp-server", 69, OT_ADDR_LIST },
401 { "pop3-server", 70, OT_ADDR_LIST },
402 { "nntp-server", 71, OT_ADDR_LIST },
403 { "irc-server", 74, OT_ADDR_LIST },
404 { "user-class", 77, 0 },
405 { "FQDN", 81, OT_INTERNAL },
406 { "agent-id", 82, OT_INTERNAL },
407 { "client-arch", 93, 2 },
408 { "client-interface-id", 94, 0 },
409 { "client-machine-id", 97, 0 },
410 { "subnet-select", 118, OT_INTERNAL },
411 { "domain-search", 119, 0 },
412 { "sip-server", 120, 0 },
413 { "classless-static-route", 121, 0 },
414 { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
415 { NULL, 0, 0 }
416 };
417
option_string(unsigned char opt,int * is_ip,int * is_name)418 char *option_string(unsigned char opt, int *is_ip, int *is_name)
419 {
420 int i;
421
422 for (i = 0; opttab[i].name; i++)
423 if (opttab[i].val == opt)
424 {
425 if (is_ip)
426 *is_ip = !!(opttab[i].size & OT_ADDR_LIST);
427 if (is_name)
428 *is_name = !!(opttab[i].size & OT_NAME);
429 return opttab[i].name;
430 }
431
432 return NULL;
433 }
434
435 #endif
436
437 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
438 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
439 following sequence so that they map to themselves: it is therefore possible to call
440 unhide_metas repeatedly on string without breaking things.
441 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
442 couple of other places.
443 Note that space is included here so that
444 --dhcp-option=3, string
445 has five characters, whilst
446 --dhcp-option=3," string"
447 has six.
448 */
449
450 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
451
hide_meta(char c)452 static char hide_meta(char c)
453 {
454 unsigned int i;
455
456 for (i = 0; i < (sizeof(meta) - 1); i++)
457 if (c == meta[i])
458 return (char)i;
459
460 return c;
461 }
462
unhide_meta(char cr)463 static char unhide_meta(char cr)
464 {
465 unsigned int c = cr;
466
467 if (c < (sizeof(meta) - 1))
468 cr = meta[c];
469
470 return cr;
471 }
472
unhide_metas(char * cp)473 static void unhide_metas(char *cp)
474 {
475 if (cp)
476 for(; *cp; cp++)
477 *cp = unhide_meta(*cp);
478 }
479
opt_malloc(size_t size)480 static void *opt_malloc(size_t size)
481 {
482 void *ret;
483
484 if (mem_recover)
485 {
486 ret = whine_malloc(size);
487 if (!ret)
488 longjmp(mem_jmp, 1);
489 }
490 else
491 ret = safe_malloc(size);
492
493 return ret;
494 }
495
opt_string_alloc(char * cp)496 static char *opt_string_alloc(char *cp)
497 {
498 char *ret = NULL;
499
500 if (cp && strlen(cp) != 0)
501 {
502 ret = opt_malloc(strlen(cp)+1);
503 strcpy(ret, cp);
504
505 /* restore hidden metachars */
506 unhide_metas(ret);
507 }
508
509 return ret;
510 }
511
512
513 /* find next comma, split string with zero and eliminate spaces.
514 return start of string following comma */
515
split_chr(char * s,char c)516 static char *split_chr(char *s, char c)
517 {
518 char *comma, *p;
519
520 if (!s || !(comma = strchr(s, c)))
521 return NULL;
522
523 p = comma;
524 *comma = ' ';
525
526 for (; isspace((int)*comma); comma++);
527
528 for (; (p >= s) && isspace((int)*p); p--)
529 *p = 0;
530
531 return comma;
532 }
533
split(char * s)534 static char *split(char *s)
535 {
536 return split_chr(s, ',');
537 }
538
canonicalise_opt(char * s)539 static char *canonicalise_opt(char *s)
540 {
541 char *ret;
542 int nomem;
543
544 if (!s)
545 return 0;
546
547 unhide_metas(s);
548 if (!(ret = canonicalise(s, &nomem)) && nomem)
549 {
550 if (mem_recover)
551 longjmp(mem_jmp, 1);
552 else
553 die(_("could not get memory"), NULL, EC_NOMEM);
554 }
555
556 return ret;
557 }
558
atoi_check(char * a,int * res)559 static int atoi_check(char *a, int *res)
560 {
561 char *p;
562
563 if (!a)
564 return 0;
565
566 unhide_metas(a);
567
568 for (p = a; *p; p++)
569 if (*p < '0' || *p > '9')
570 return 0;
571
572 *res = atoi(a);
573 return 1;
574 }
575
atoi_check16(char * a,int * res)576 static int atoi_check16(char *a, int *res)
577 {
578 if (!(atoi_check(a, res)) ||
579 *res < 0 ||
580 *res > 0xffff)
581 return 0;
582
583 return 1;
584 }
585
add_txt(char * name,char * txt)586 static void add_txt(char *name, char *txt)
587 {
588 size_t len = strlen(txt);
589 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
590
591 r->name = opt_string_alloc(name);
592 r->next = daemon->txt;
593 daemon->txt = r;
594 r->class = C_CHAOS;
595 r->txt = opt_malloc(len+1);
596 r->len = len+1;
597 *(r->txt) = len;
598 memcpy((r->txt)+1, txt, len);
599 }
600
do_usage(void)601 static void do_usage(void)
602 {
603 char buff[100];
604 int i, j;
605
606 struct {
607 char handle;
608 int val;
609 } tab[] = {
610 { '$', CACHESIZ },
611 { '*', EDNS_PKTSZ },
612 { '&', MAXLEASES },
613 { '!', FTABSIZ },
614 { '#', TFTP_MAX_CONNECTIONS },
615 { '\0', 0 }
616 };
617
618 printf(_("Usage: dnsmasq [options]\n\n"));
619 #ifndef HAVE_GETOPT_LONG
620 printf(_("Use short options only on the command line.\n"));
621 #endif
622 printf(_("Valid options are:\n"));
623
624 for (i = 0; usage[i].opt != 0; i++)
625 {
626 char *desc = usage[i].flagdesc;
627 char *eq = "=";
628
629 if (!desc || *desc == '[')
630 eq = "";
631
632 if (!desc)
633 desc = "";
634
635 for ( j = 0; opts[j].name; j++)
636 if (opts[j].val == usage[i].opt)
637 break;
638 if (usage[i].opt < 256)
639 sprintf(buff, "-%c, ", usage[i].opt);
640 else
641 sprintf(buff, " ");
642
643 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
644 printf("%-36.36s", buff);
645
646 if (usage[i].arg)
647 {
648 strcpy(buff, usage[i].arg);
649 for (j = 0; tab[j].handle; j++)
650 if (tab[j].handle == *(usage[i].arg))
651 sprintf(buff, "%d", tab[j].val);
652 }
653 printf(_(usage[i].desc), buff);
654 printf("\n");
655 }
656 }
657
658 #ifdef HAVE_DHCP
display_opts(void)659 static void display_opts(void)
660 {
661 int i;
662
663 printf(_("Known DHCP options:\n"));
664
665 for (i = 0; opttab[i].name; i++)
666 if (!(opttab[i].size & OT_INTERNAL))
667 printf("%3d %s\n", opttab[i].val, opttab[i].name);
668 }
669
670 /* This is too insanely large to keep in-line in the switch */
parse_dhcp_opt(char * arg,int flags)671 static char *parse_dhcp_opt(char *arg, int flags)
672 {
673 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
674 char lenchar = 0, *cp;
675 int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
676 char *comma = NULL, *problem = NULL;
677 struct dhcp_netid *np = NULL;
678 unsigned char opt_len = 0;
679
680 new->len = 0;
681 new->flags = flags;
682 new->netid = NULL;
683 new->val = NULL;
684 new->opt = 0;
685
686 while (arg)
687 {
688 comma = split(arg);
689
690 for (cp = arg; *cp; cp++)
691 if (*cp < '0' || *cp > '9')
692 break;
693
694 if (!*cp)
695 {
696 new->opt = atoi(arg);
697 opt_len = 0;
698 break;
699 }
700
701 if (strstr(arg, "option:") == arg)
702 {
703 for (i = 0; opttab[i].name; i++)
704 if (!(opttab[i].size & OT_INTERNAL) &&
705 strcasecmp(opttab[i].name, arg+7) == 0)
706 {
707 new->opt = opttab[i].val;
708 opt_len = opttab[i].size;
709 break;
710 }
711 /* option:<optname> must follow tag and vendor string. */
712 break;
713 }
714 else if (strstr(arg, "vendor:") == arg)
715 {
716 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
717 new->flags |= DHOPT_VENDOR;
718 }
719 else if (strstr(arg, "encap:") == arg)
720 {
721 new->u.encap = atoi(arg+6);
722 new->flags |= DHOPT_ENCAPSULATE;
723 }
724 else
725 {
726 new->netid = opt_malloc(sizeof (struct dhcp_netid));
727 /* allow optional "net:" for consistency */
728 if (strstr(arg, "net:") == arg)
729 new->netid->net = opt_string_alloc(arg+4);
730 else
731 new->netid->net = opt_string_alloc(arg);
732 new->netid->next = np;
733 np = new->netid;
734 }
735
736 arg = comma;
737 }
738
739 if (new->opt == 0)
740 problem = _("bad dhcp-option");
741 else if (comma)
742 {
743 /* characterise the value */
744 char c;
745 is_addr = is_hex = is_dec = is_string = 1;
746 addrs = digs = 1;
747 dots = 0;
748 for (cp = comma; (c = *cp); cp++)
749 if (c == ',')
750 {
751 addrs++;
752 is_dec = is_hex = 0;
753 }
754 else if (c == ':')
755 {
756 digs++;
757 is_dec = is_addr = 0;
758 }
759 else if (c == '/')
760 {
761 is_dec = is_hex = 0;
762 if (cp == comma) /* leading / means a pathname */
763 is_addr = 0;
764 }
765 else if (c == '.')
766 {
767 is_dec = is_hex = 0;
768 dots++;
769 }
770 else if (c == '-')
771 is_hex = is_addr = 0;
772 else if (c == ' ')
773 is_dec = is_hex = 0;
774 else if (!(c >='0' && c <= '9'))
775 {
776 is_addr = 0;
777 if (cp[1] == 0 && is_dec &&
778 (c == 'b' || c == 's' || c == 'i'))
779 {
780 lenchar = c;
781 *cp = 0;
782 }
783 else
784 is_dec = 0;
785 if (!((c >='A' && c <= 'F') ||
786 (c >='a' && c <= 'f') ||
787 (c == '*' && (flags & DHOPT_MATCH))))
788 is_hex = 0;
789 }
790
791 /* We know that some options take addresses */
792
793 if (opt_len & OT_ADDR_LIST)
794 {
795 is_string = is_dec = is_hex = 0;
796 if (!is_addr || dots == 0)
797 problem = _("bad IP address");
798 }
799
800 if (is_hex && digs > 1)
801 {
802 new->len = digs;
803 new->val = opt_malloc(new->len);
804 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
805 new->flags |= DHOPT_HEX;
806 }
807 else if (is_dec)
808 {
809 int i, val = atoi(comma);
810 /* assume numeric arg is 1 byte except for
811 options where it is known otherwise.
812 For vendor class option, we have to hack. */
813 if (opt_len != 0)
814 new->len = opt_len;
815 else if (val & 0xffff0000)
816 new->len = 4;
817 else if (val & 0xff00)
818 new->len = 2;
819 else
820 new->len = 1;
821
822 if (lenchar == 'b')
823 new->len = 1;
824 else if (lenchar == 's')
825 new->len = 2;
826 else if (lenchar == 'i')
827 new->len = 4;
828
829 new->val = opt_malloc(new->len);
830 for (i=0; i<new->len; i++)
831 new->val[i] = val>>((new->len - i - 1)*8);
832 }
833 else if (is_addr)
834 {
835 struct in_addr in;
836 unsigned char *op;
837 char *slash;
838 /* max length of address/subnet descriptor is five bytes,
839 add one for the option 120 enc byte too */
840 new->val = op = opt_malloc((5 * addrs) + 1);
841 new->flags |= DHOPT_ADDR;
842
843 if (!(new->flags & DHOPT_ENCAPSULATE) && new->opt == 120)
844 {
845 *(op++) = 1; /* RFC 3361 "enc byte" */
846 new->flags &= ~DHOPT_ADDR;
847 }
848 while (addrs--)
849 {
850 cp = comma;
851 comma = split(cp);
852 slash = split_chr(cp, '/');
853 in.s_addr = inet_addr(cp);
854 if (!slash)
855 {
856 memcpy(op, &in, INADDRSZ);
857 op += INADDRSZ;
858 }
859 else
860 {
861 unsigned char *p = (unsigned char *)∈
862 int netsize = atoi(slash);
863 *op++ = netsize;
864 if (netsize > 0)
865 *op++ = *p++;
866 if (netsize > 8)
867 *op++ = *p++;
868 if (netsize > 16)
869 *op++ = *p++;
870 if (netsize > 24)
871 *op++ = *p++;
872 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
873 }
874 }
875 new->len = op - new->val;
876 }
877 else if (is_string)
878 {
879 /* text arg */
880 if ((new->opt == 119 || new->opt == 120) && !(new->flags & DHOPT_ENCAPSULATE))
881 {
882 /* dns search, RFC 3397, or SIP, RFC 3361 */
883 unsigned char *q, *r, *tail;
884 unsigned char *p, *m = NULL, *newp;
885 size_t newlen, len = 0;
886 int header_size = (new->opt == 119) ? 0 : 1;
887
888 arg = comma;
889 comma = split(arg);
890
891 while (arg && *arg)
892 {
893 char *dom;
894 if (!(dom = arg = canonicalise_opt(arg)))
895 {
896 problem = _("bad domain in dhcp-option");
897 break;
898 }
899
900 newp = opt_malloc(len + strlen(arg) + 2 + header_size);
901 if (m)
902 memcpy(newp, m, header_size + len);
903 m = newp;
904 p = m + header_size;
905 q = p + len;
906
907 /* add string on the end in RFC1035 format */
908 while (*arg)
909 {
910 unsigned char *cp = q++;
911 int j;
912 for (j = 0; *arg && (*arg != '.'); arg++, j++)
913 *q++ = *arg;
914 *cp = j;
915 if (*arg)
916 arg++;
917 }
918 *q++ = 0;
919 free(dom);
920
921 /* Now tail-compress using earlier names. */
922 newlen = q - p;
923 for (tail = p + len; *tail; tail += (*tail) + 1)
924 for (r = p; r - p < (int)len; r += (*r) + 1)
925 if (strcmp((char *)r, (char *)tail) == 0)
926 {
927 PUTSHORT((r - p) | 0xc000, tail);
928 newlen = tail - p;
929 goto end;
930 }
931 end:
932 len = newlen;
933
934 arg = comma;
935 comma = split(arg);
936 }
937
938 /* RFC 3361, enc byte is zero for names */
939 if (new->opt == 120)
940 m[0] = 0;
941 new->len = (int) len + header_size;
942 new->val = m;
943 }
944 else
945 {
946 new->len = strlen(comma);
947 /* keep terminating zero on string */
948 new->val = (unsigned char *)opt_string_alloc(comma);
949 new->flags |= DHOPT_STRING;
950 }
951 }
952 }
953
954 if ((new->len > 255) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
955 problem = _("dhcp-option too long");
956
957 if (!problem)
958 {
959 if (flags == DHOPT_MATCH)
960 {
961 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
962 !new->netid ||
963 new->netid->next)
964 problem = _("illegal dhcp-match");
965 else
966 {
967 new->next = daemon->dhcp_match;
968 daemon->dhcp_match = new;
969 }
970 }
971 else
972 {
973 new->next = daemon->dhcp_opts;
974 daemon->dhcp_opts = new;
975 }
976 }
977
978 return problem;
979 }
980
981 #endif
982
one_opt(int option,char * arg,char * gen_prob,int nest)983 static char *one_opt(int option, char *arg, char *gen_prob, int nest)
984 {
985 int i;
986 char *comma, *problem = NULL;;
987
988 if (option == '?')
989 return gen_prob;
990
991 for (i=0; usage[i].opt != 0; i++)
992 if (usage[i].opt == option)
993 {
994 int rept = usage[i].rept;
995
996 if (nest == 0)
997 {
998 /* command line */
999 if (rept == ARG_USED_CL)
1000 return _("illegal repeated flag");
1001 if (rept == ARG_ONE)
1002 usage[i].rept = ARG_USED_CL;
1003 }
1004 else
1005 {
1006 /* allow file to override command line */
1007 if (rept == ARG_USED_FILE)
1008 return _("illegal repeated keyword");
1009 if (rept == ARG_USED_CL || rept == ARG_ONE)
1010 usage[i].rept = ARG_USED_FILE;
1011 }
1012
1013 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1014 {
1015 daemon->options |= rept;
1016 return NULL;
1017 }
1018
1019 break;
1020 }
1021
1022 switch (option)
1023 {
1024 case 'C': /* --conf-file */
1025 {
1026 char *file = opt_string_alloc(arg);
1027 if (file)
1028 {
1029 one_file(file, nest, 0);
1030 free(file);
1031 }
1032 break;
1033 }
1034
1035 case '7': /* --conf-dir */
1036 {
1037 DIR *dir_stream;
1038 struct dirent *ent;
1039 char *directory, *path;
1040 struct list {
1041 char *suffix;
1042 struct list *next;
1043 } *ignore_suffix = NULL, *li;
1044
1045 comma = split(arg);
1046 if (!(directory = opt_string_alloc(arg)))
1047 break;
1048
1049 for (arg = comma; arg; arg = comma)
1050 {
1051 comma = split(arg);
1052 li = opt_malloc(sizeof(struct list));
1053 li->next = ignore_suffix;
1054 ignore_suffix = li;
1055 /* Have to copy: buffer is overwritten */
1056 li->suffix = opt_string_alloc(arg);
1057 };
1058
1059 if (!(dir_stream = opendir(directory)))
1060 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1061
1062 while ((ent = readdir(dir_stream)))
1063 {
1064 size_t len = strlen(ent->d_name);
1065 struct stat buf;
1066
1067 /* ignore emacs backups and dotfiles */
1068 if (len == 0 ||
1069 ent->d_name[len - 1] == '~' ||
1070 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1071 ent->d_name[0] == '.')
1072 continue;
1073
1074 for (li = ignore_suffix; li; li = li->next)
1075 {
1076 /* check for proscribed suffices */
1077 size_t ls = strlen(li->suffix);
1078 if (len > ls &&
1079 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1080 break;
1081 }
1082 if (li)
1083 continue;
1084
1085 path = opt_malloc(strlen(directory) + len + 2);
1086 strcpy(path, directory);
1087 strcat(path, "/");
1088 strcat(path, ent->d_name);
1089
1090 if (stat(path, &buf) == -1)
1091 die(_("cannot access %s: %s"), path, EC_FILE);
1092 /* only reg files allowed. */
1093 if (!S_ISREG(buf.st_mode))
1094 continue;
1095
1096 /* dir is one level, so files must be readable */
1097 one_file(path, nest + 1, 0);
1098 free(path);
1099 }
1100
1101 closedir(dir_stream);
1102 free(directory);
1103 for(; ignore_suffix; ignore_suffix = li)
1104 {
1105 li = ignore_suffix->next;
1106 free(ignore_suffix->suffix);
1107 free(ignore_suffix);
1108 }
1109
1110 break;
1111 }
1112
1113 case '8': /* --log-facility */
1114 /* may be a filename */
1115 if (strchr(arg, '/'))
1116 daemon->log_file = opt_string_alloc(arg);
1117 else
1118 {
1119 #ifdef __ANDROID__
1120 problem = "Android does not support log facilities";
1121 #else
1122 for (i = 0; facilitynames[i].c_name; i++)
1123 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1124 break;
1125
1126 if (facilitynames[i].c_name)
1127 daemon->log_fac = facilitynames[i].c_val;
1128 else
1129 problem = "bad log facility";
1130 #endif
1131 }
1132 break;
1133
1134 case 'x': /* --pid-file */
1135 daemon->runfile = opt_string_alloc(arg);
1136 break;
1137
1138 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1139 if (daemon->dhcp_hosts_file)
1140 problem = _("only one dhcp-hostsfile allowed");
1141 else
1142 daemon->dhcp_hosts_file = opt_string_alloc(arg);
1143 break;
1144
1145 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1146 if (daemon->dhcp_opts_file)
1147 problem = _("only one dhcp-optsfile allowed");
1148 else
1149 daemon->dhcp_opts_file = opt_string_alloc(arg);
1150 break;
1151
1152 case 'r': /* --resolv-file */
1153 {
1154 char *name = opt_string_alloc(arg);
1155 struct resolvc *new, *list = daemon->resolv_files;
1156
1157 if (list && list->is_default)
1158 {
1159 /* replace default resolv file - possibly with nothing */
1160 if (name)
1161 {
1162 list->is_default = 0;
1163 list->name = name;
1164 }
1165 else
1166 list = NULL;
1167 }
1168 else if (name)
1169 {
1170 new = opt_malloc(sizeof(struct resolvc));
1171 new->next = list;
1172 new->name = name;
1173 new->is_default = 0;
1174 new->mtime = 0;
1175 new->logged = 0;
1176 list = new;
1177 }
1178 daemon->resolv_files = list;
1179 break;
1180 }
1181
1182 case 'm': /* --mx-host */
1183 {
1184 int pref = 1;
1185 struct mx_srv_record *new;
1186 char *name, *target = NULL;
1187
1188 if ((comma = split(arg)))
1189 {
1190 char *prefstr;
1191 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1192 problem = _("bad MX preference");
1193 }
1194
1195 if (!(name = canonicalise_opt(arg)) ||
1196 (comma && !(target = canonicalise_opt(comma))))
1197 problem = _("bad MX name");
1198
1199 new = opt_malloc(sizeof(struct mx_srv_record));
1200 new->next = daemon->mxnames;
1201 daemon->mxnames = new;
1202 new->issrv = 0;
1203 new->name = name;
1204 new->target = target; /* may be NULL */
1205 new->weight = pref;
1206 break;
1207 }
1208
1209 case 't': /* --mx-target */
1210 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1211 problem = _("bad MX target");
1212 break;
1213
1214 #ifdef HAVE_DHCP
1215 case 'l': /* --dhcp-leasefile */
1216 daemon->lease_file = opt_string_alloc(arg);
1217 break;
1218
1219 case '6': /* --dhcp-script */
1220 # if defined(NO_FORK)
1221 problem = _("cannot run scripts under uClinux");
1222 # elif !defined(HAVE_SCRIPT)
1223 problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1224 # else
1225 daemon->lease_change_command = opt_string_alloc(arg);
1226 # endif
1227 break;
1228 #endif
1229
1230 case 'H': /* --addn-hosts */
1231 {
1232 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1233 static int hosts_index = 1;
1234 new->fname = opt_string_alloc(arg);
1235 new->index = hosts_index++;
1236 new->flags = 0;
1237 new->next = daemon->addn_hosts;
1238 daemon->addn_hosts = new;
1239 break;
1240 }
1241
1242 case 's': /* --domain */
1243 if (strcmp (arg, "#") == 0)
1244 daemon->options |= OPT_RESOLV_DOMAIN;
1245 else
1246 {
1247 char *d;
1248 comma = split(arg);
1249 if (!(d = canonicalise_opt(arg)))
1250 option = '?';
1251 else
1252 {
1253 if (comma)
1254 {
1255 struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
1256 unhide_metas(comma);
1257 if ((arg = split_chr(comma, '/')))
1258 {
1259 int mask;
1260 if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1261 !atoi_check(arg, &mask))
1262 option = '?';
1263 else
1264 {
1265 mask = (1 << (32 - mask)) - 1;
1266 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1267 new->end.s_addr = new->start.s_addr | htonl(mask);
1268 }
1269 }
1270 else if ((arg = split(comma)))
1271 {
1272 if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1273 (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
1274 option = '?';
1275 }
1276 else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1277 option = '?';
1278
1279 new->domain = d;
1280 new->next = daemon->cond_domain;
1281 daemon->cond_domain = new;
1282 }
1283 else
1284 daemon->domain_suffix = d;
1285 }
1286 }
1287 break;
1288
1289 case 'u': /* --user */
1290 daemon->username = opt_string_alloc(arg);
1291 break;
1292
1293 case 'g': /* --group */
1294 daemon->groupname = opt_string_alloc(arg);
1295 daemon->group_set = 1;
1296 break;
1297
1298 #ifdef HAVE_DHCP
1299 case LOPT_SCRIPTUSR: /* --scriptuser */
1300 daemon->scriptuser = opt_string_alloc(arg);
1301 break;
1302 #endif
1303
1304 case 'i': /* --interface */
1305 do {
1306 struct iname *new = opt_malloc(sizeof(struct iname));
1307 comma = split(arg);
1308 new->next = daemon->if_names;
1309 daemon->if_names = new;
1310 /* new->name may be NULL if someone does
1311 "interface=" to disable all interfaces except loop. */
1312 new->name = opt_string_alloc(arg);
1313 new->isloop = new->used = 0;
1314 arg = comma;
1315 } while (arg);
1316 break;
1317
1318 case 'I': /* --except-interface */
1319 case '2': /* --no-dhcp-interface */
1320 do {
1321 struct iname *new = opt_malloc(sizeof(struct iname));
1322 comma = split(arg);
1323 new->name = opt_string_alloc(arg);
1324 if (option == 'I')
1325 {
1326 new->next = daemon->if_except;
1327 daemon->if_except = new;
1328 }
1329 else
1330 {
1331 new->next = daemon->dhcp_except;
1332 daemon->dhcp_except = new;
1333 }
1334 arg = comma;
1335 } while (arg);
1336 break;
1337
1338 case 'B': /* --bogus-nxdomain */
1339 {
1340 struct in_addr addr;
1341 unhide_metas(arg);
1342 if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1343 {
1344 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1345 baddr->next = daemon->bogus_addr;
1346 daemon->bogus_addr = baddr;
1347 baddr->addr = addr;
1348 }
1349 else
1350 option = '?'; /* error */
1351 break;
1352 }
1353
1354 case 'a': /* --listen-address */
1355 do {
1356 struct iname *new = opt_malloc(sizeof(struct iname));
1357 comma = split(arg);
1358 unhide_metas(arg);
1359 new->next = daemon->if_addrs;
1360 if (arg &&
1361 parse_addr(AF_INET, arg, &new->addr) != 0 &&
1362 parse_addr(AF_INET6, arg, &new->addr) != 0)
1363 {
1364 option = '?'; /* error */
1365 break;
1366 }
1367
1368 daemon->if_addrs = new;
1369 arg = comma;
1370 } while (arg);
1371 break;
1372
1373 case 'S': /* --server */
1374 case LOPT_LOCAL: /* --local */
1375 case 'A': /* --address */
1376 {
1377 struct server *serv, *newlist = NULL;
1378
1379 unhide_metas(arg);
1380
1381 if (arg && *arg == '/')
1382 {
1383 char *end;
1384 arg++;
1385 while ((end = split_chr(arg, '/')))
1386 {
1387 char *domain = NULL;
1388 /* # matches everything and becomes a zero length domain string */
1389 if (strcmp(arg, "#") == 0)
1390 domain = "";
1391 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1392 option = '?';
1393 serv = opt_malloc(sizeof(struct server));
1394 memset(serv, 0, sizeof(struct server));
1395 serv->next = newlist;
1396 newlist = serv;
1397 serv->domain = domain;
1398 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1399 arg = end;
1400 }
1401 if (!newlist)
1402 {
1403 option = '?';
1404 break;
1405 }
1406
1407 }
1408 else
1409 {
1410 newlist = opt_malloc(sizeof(struct server));
1411 memset(newlist, 0, sizeof(struct server));
1412 }
1413
1414 if (option == 'A')
1415 {
1416 newlist->flags |= SERV_LITERAL_ADDRESS;
1417 if (!(newlist->flags & SERV_TYPE))
1418 option = '?';
1419 }
1420
1421 if (!arg || !*arg)
1422 {
1423 newlist->flags |= SERV_NO_ADDR; /* no server */
1424 if (newlist->flags & SERV_LITERAL_ADDRESS)
1425 option = '?';
1426 }
1427 else
1428 {
1429 int source_port = 0, serv_port = NAMESERVER_PORT;
1430 char *portno, *source;
1431
1432 if ((source = split_chr(arg, '@')) && /* is there a source. */
1433 (portno = split_chr(source, '#')) &&
1434 !atoi_check16(portno, &source_port))
1435 problem = _("bad port");
1436
1437 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1438 !atoi_check16(portno, &serv_port))
1439 problem = _("bad port");
1440
1441 if (parse_addr(AF_INET, arg, &newlist->addr) == 0)
1442 {
1443 newlist->addr.in.sin_port = htons(serv_port);
1444 #ifdef HAVE_SOCKADDR_SA_LEN
1445 newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
1446 #endif
1447 if (source)
1448 {
1449 newlist->flags |= SERV_HAS_SOURCE;
1450 if (parse_addr(AF_INET, source, &newlist->addr) != 0)
1451 {
1452 #if defined(SO_BINDTODEVICE)
1453 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1454 strncpy(newlist->interface, source, IF_NAMESIZE);
1455 #else
1456 problem = _("interface binding not supported");
1457 #endif
1458 }
1459 }
1460 else
1461 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1462
1463 newlist->source_addr.in.sin_port = htons(source_port);
1464 newlist->source_addr.sa.sa_family = AF_INET;
1465 }
1466 #ifdef HAVE_IPV6
1467 else if (parse_addr(AF_INET6, arg, &newlist->addr) == 0)
1468 {
1469 newlist->addr.in6.sin6_port = htons(serv_port);
1470 if (source)
1471 {
1472 newlist->flags |= SERV_HAS_SOURCE;
1473 if (parse_addr(AF_INET6, source, &newlist->source_addr) != 0)
1474 {
1475 #if defined(SO_BINDTODEVICE)
1476 newlist->source_addr.in6.sin6_addr = in6addr_any;
1477 strncpy(newlist->interface, source, IF_NAMESIZE);
1478 #else
1479 problem = _("interface binding not supported");
1480 #endif
1481 }
1482 }
1483 else
1484 newlist->source_addr.in6.sin6_addr = in6addr_any;
1485
1486 newlist->source_addr.in6.sin6_port = htons(source_port);
1487 newlist->source_addr.sa.sa_family = AF_INET6;
1488 }
1489 #endif
1490 else
1491 option = '?'; /* error */
1492
1493 }
1494
1495 serv = newlist;
1496 while (serv->next)
1497 {
1498 serv->next->flags = serv->flags;
1499 serv->next->addr = serv->addr;
1500 serv->next->source_addr = serv->source_addr;
1501 serv = serv->next;
1502 }
1503 serv->next = daemon->servers;
1504 daemon->servers = newlist;
1505 break;
1506 }
1507
1508 case 'c': /* --cache-size */
1509 {
1510 int size;
1511
1512 if (!atoi_check(arg, &size))
1513 option = '?';
1514 else
1515 {
1516 /* zero is OK, and means no caching. */
1517
1518 if (size < 0)
1519 size = 0;
1520 else if (size > 10000)
1521 size = 10000;
1522
1523 daemon->cachesize = size;
1524 }
1525 break;
1526 }
1527
1528 case 'p': /* --port */
1529 if (!atoi_check16(arg, &daemon->port))
1530 option = '?';
1531 break;
1532
1533 case LOPT_MINPORT: /* --min-port */
1534 if (!atoi_check16(arg, &daemon->min_port))
1535 option = '?';
1536 break;
1537
1538 case '0': /* --dns-forward-max */
1539 if (!atoi_check(arg, &daemon->ftabsize))
1540 option = '?';
1541 break;
1542
1543 case LOPT_MAX_LOGS: /* --log-async */
1544 daemon->max_logs = LOG_MAX; /* default */
1545 if (arg && !atoi_check(arg, &daemon->max_logs))
1546 option = '?';
1547 else if (daemon->max_logs > 100)
1548 daemon->max_logs = 100;
1549 break;
1550
1551 case 'P': /* --edns-packet-max */
1552 {
1553 int i;
1554 if (!atoi_check(arg, &i))
1555 option = '?';
1556 daemon->edns_pktsz = (unsigned short)i;
1557 break;
1558 }
1559
1560 case 'Q': /* --query-port */
1561 if (!atoi_check16(arg, &daemon->query_port))
1562 option = '?';
1563 /* if explicitly set to zero, use single OS ephemeral port
1564 and disable random ports */
1565 if (daemon->query_port == 0)
1566 daemon->osport = 1;
1567 break;
1568
1569 case 'T': /* --local-ttl */
1570 case LOPT_NEGTTL: /* --neg-ttl */
1571 {
1572 int ttl;
1573 if (!atoi_check(arg, &ttl))
1574 option = '?';
1575 else if (option == LOPT_NEGTTL)
1576 daemon->neg_ttl = (unsigned long)ttl;
1577 else
1578 daemon->local_ttl = (unsigned long)ttl;
1579 break;
1580 }
1581
1582 #ifdef HAVE_DHCP
1583 case 'X': /* --dhcp-lease-max */
1584 if (!atoi_check(arg, &daemon->dhcp_max))
1585 option = '?';
1586 break;
1587 #endif
1588
1589 #ifdef HAVE_TFTP
1590 case LOPT_TFTP_MAX: /* --tftp-max */
1591 if (!atoi_check(arg, &daemon->tftp_max))
1592 option = '?';
1593 break;
1594
1595 case LOPT_PREFIX: /* --tftp-prefix */
1596 daemon->tftp_prefix = opt_string_alloc(arg);
1597 break;
1598
1599 case LOPT_TFTPPORTS: /* --tftp-port-range */
1600 if (!(comma = split(arg)) ||
1601 !atoi_check16(arg, &daemon->start_tftp_port) ||
1602 !atoi_check16(comma, &daemon->end_tftp_port))
1603 problem = _("bad port range");
1604
1605 if (daemon->start_tftp_port > daemon->end_tftp_port)
1606 {
1607 int tmp = daemon->start_tftp_port;
1608 daemon->start_tftp_port = daemon->end_tftp_port;
1609 daemon->end_tftp_port = tmp;
1610 }
1611
1612 break;
1613 #endif
1614
1615 case LOPT_BRIDGE: /* --bridge-interface */
1616 {
1617 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
1618 if (!(comma = split(arg)))
1619 {
1620 problem = _("bad bridge-interface");
1621 break;
1622 }
1623
1624 strncpy(new->iface, arg, IF_NAMESIZE);
1625 new->alias = NULL;
1626 new->next = daemon->bridges;
1627 daemon->bridges = new;
1628
1629 do {
1630 arg = comma;
1631 comma = split(arg);
1632 if (strlen(arg) != 0)
1633 {
1634 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
1635 b->next = new->alias;
1636 new->alias = b;
1637 strncpy(b->iface, arg, IF_NAMESIZE);
1638 }
1639 } while (comma);
1640
1641 break;
1642 }
1643
1644 #ifdef HAVE_DHCP
1645 case 'F': /* --dhcp-range */
1646 {
1647 int k, leasepos = 2;
1648 char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
1649 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
1650
1651 new->next = daemon->dhcp;
1652 new->lease_time = DEFLEASE;
1653 new->addr_epoch = 0;
1654 new->netmask.s_addr = 0;
1655 new->broadcast.s_addr = 0;
1656 new->router.s_addr = 0;
1657 new->netid.net = NULL;
1658 new->filter = NULL;
1659 new->flags = 0;
1660
1661 gen_prob = _("bad dhcp-range");
1662
1663 if (!arg)
1664 {
1665 option = '?';
1666 break;
1667 }
1668
1669 while(1)
1670 {
1671 for (cp = arg; *cp; cp++)
1672 if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
1673 break;
1674
1675 if (*cp != ',' && (comma = split(arg)))
1676 {
1677 if (strstr(arg, "net:") == arg)
1678 {
1679 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
1680 tt->net = opt_string_alloc(arg+4);
1681 tt->next = new->filter;
1682 new->filter = tt;
1683 }
1684 else
1685 {
1686 if (new->netid.net)
1687 problem = _("only one netid tag allowed");
1688 else
1689 new->netid.net = opt_string_alloc(arg);
1690 }
1691 arg = comma;
1692 }
1693 else
1694 {
1695 a[0] = arg;
1696 break;
1697 }
1698 }
1699
1700 for (k = 1; k < 5; k++)
1701 if (!(a[k] = split(a[k-1])))
1702 break;
1703
1704 if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
1705 option = '?';
1706 else if (strcmp(a[1], "static") == 0)
1707 {
1708 new->end = new->start;
1709 new->flags |= CONTEXT_STATIC;
1710 }
1711 else if (strcmp(a[1], "proxy") == 0)
1712 {
1713 new->end = new->start;
1714 new->flags |= CONTEXT_PROXY;
1715 }
1716 else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
1717 option = '?';
1718
1719 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
1720 {
1721 struct in_addr tmp = new->start;
1722 new->start = new->end;
1723 new->end = tmp;
1724 }
1725
1726 if (option != '?' && k >= 3 && strchr(a[2], '.') &&
1727 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
1728 {
1729 new->flags |= CONTEXT_NETMASK;
1730 leasepos = 3;
1731 if (!is_same_net(new->start, new->end, new->netmask))
1732 problem = _("inconsistent DHCP range");
1733 }
1734 daemon->dhcp = new;
1735
1736 if (k >= 4 && strchr(a[3], '.') &&
1737 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
1738 {
1739 new->flags |= CONTEXT_BRDCAST;
1740 leasepos = 4;
1741 }
1742
1743 if (k >= leasepos+1)
1744 {
1745 if (strcmp(a[leasepos], "infinite") == 0)
1746 new->lease_time = 0xffffffff;
1747 else
1748 {
1749 int fac = 1;
1750 if (strlen(a[leasepos]) > 0)
1751 {
1752 switch (a[leasepos][strlen(a[leasepos]) - 1])
1753 {
1754 case 'd':
1755 case 'D':
1756 fac *= 24;
1757 /* fall though */
1758 case 'h':
1759 case 'H':
1760 fac *= 60;
1761 /* fall through */
1762 case 'm':
1763 case 'M':
1764 fac *= 60;
1765 /* fall through */
1766 case 's':
1767 case 'S':
1768 a[leasepos][strlen(a[leasepos]) - 1] = 0;
1769 }
1770
1771 new->lease_time = atoi(a[leasepos]) * fac;
1772 /* Leases of a minute or less confuse
1773 some clients, notably Apple's */
1774 if (new->lease_time < 120)
1775 new->lease_time = 120;
1776 }
1777 }
1778 }
1779 break;
1780 }
1781
1782 case LOPT_BANK:
1783 case 'G': /* --dhcp-host */
1784 {
1785 int j, k = 0;
1786 char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
1787 struct dhcp_config *new;
1788 struct in_addr in;
1789
1790 new = opt_malloc(sizeof(struct dhcp_config));
1791
1792 new->next = daemon->dhcp_conf;
1793 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
1794 new->hwaddr = NULL;
1795
1796 if ((a[0] = arg))
1797 for (k = 1; k < 6; k++)
1798 if (!(a[k] = split(a[k-1])))
1799 break;
1800
1801 for (j = 0; j < k; j++)
1802 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
1803 {
1804 char *arg = a[j];
1805
1806 if ((arg[0] == 'i' || arg[0] == 'I') &&
1807 (arg[1] == 'd' || arg[1] == 'D') &&
1808 arg[2] == ':')
1809 {
1810 if (arg[3] == '*')
1811 new->flags |= CONFIG_NOCLID;
1812 else
1813 {
1814 int len;
1815 arg += 3; /* dump id: */
1816 if (strchr(arg, ':'))
1817 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
1818 else
1819 {
1820 unhide_metas(arg);
1821 len = (int) strlen(arg);
1822 }
1823
1824 if ((new->clid = opt_malloc(len)))
1825 {
1826 new->flags |= CONFIG_CLID;
1827 new->clid_len = len;
1828 memcpy(new->clid, arg, len);
1829 }
1830 }
1831 }
1832 else if (strstr(arg, "net:") == arg)
1833 {
1834 int len = strlen(arg + 4) + 1;
1835 if ((new->netid.net = opt_malloc(len)))
1836 {
1837 new->flags |= CONFIG_NETID;
1838 strcpy(new->netid.net, arg+4);
1839 unhide_metas(new->netid.net);
1840 }
1841 }
1842 else
1843 {
1844 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
1845 newhw->next = new->hwaddr;
1846 new->hwaddr = newhw;
1847 newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
1848 &newhw->wildcard_mask, &newhw->hwaddr_type);
1849 }
1850 }
1851 else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
1852 {
1853 new->addr = in;
1854 new->flags |= CONFIG_ADDR;
1855 }
1856 else
1857 {
1858 char *cp, *lastp = NULL, last = 0;
1859 int fac = 1;
1860
1861 if (strlen(a[j]) > 1)
1862 {
1863 lastp = a[j] + strlen(a[j]) - 1;
1864 last = *lastp;
1865 switch (last)
1866 {
1867 case 'd':
1868 case 'D':
1869 fac *= 24;
1870 /* fall through */
1871 case 'h':
1872 case 'H':
1873 fac *= 60;
1874 /* fall through */
1875 case 'm':
1876 case 'M':
1877 fac *= 60;
1878 /* fall through */
1879 case 's':
1880 case 'S':
1881 *lastp = 0;
1882 }
1883 }
1884
1885 for (cp = a[j]; *cp; cp++)
1886 if (!isdigit((int)*cp) && *cp != ' ')
1887 break;
1888
1889 if (*cp)
1890 {
1891 if (lastp)
1892 *lastp = last;
1893 if (strcmp(a[j], "infinite") == 0)
1894 {
1895 new->lease_time = 0xffffffff;
1896 new->flags |= CONFIG_TIME;
1897 }
1898 else if (strcmp(a[j], "ignore") == 0)
1899 new->flags |= CONFIG_DISABLE;
1900 else
1901 {
1902 if (!(new->hostname = canonicalise_opt(a[j])) ||
1903 !legal_hostname(new->hostname))
1904 problem = _("bad DHCP host name");
1905 else
1906 new->flags |= CONFIG_NAME;
1907 new->domain = NULL;
1908 }
1909 }
1910 else
1911 {
1912 new->lease_time = atoi(a[j]) * fac;
1913 /* Leases of a minute or less confuse
1914 some clients, notably Apple's */
1915 if (new->lease_time < 120)
1916 new->lease_time = 120;
1917 new->flags |= CONFIG_TIME;
1918 }
1919 }
1920
1921 daemon->dhcp_conf = new;
1922 break;
1923 }
1924
1925 case 'O': /* --dhcp-option */
1926 case LOPT_FORCE: /* --dhcp-option-force */
1927 case LOPT_OPTS:
1928 case LOPT_MATCH: /* --dhcp-match */
1929 problem = parse_dhcp_opt(arg,
1930 option == LOPT_FORCE ? DHOPT_FORCE :
1931 (option == LOPT_MATCH ? DHOPT_MATCH :
1932 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
1933 break;
1934
1935 case 'M': /* --dhcp-boot */
1936 {
1937 struct dhcp_netid *id = NULL;
1938 while (arg && strstr(arg, "net:") == arg)
1939 {
1940 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
1941 newid->next = id;
1942 id = newid;
1943 comma = split(arg);
1944 newid->net = opt_string_alloc(arg+4);
1945 arg = comma;
1946 };
1947
1948 if (!arg)
1949 option = '?';
1950 else
1951 {
1952 char *dhcp_file, *dhcp_sname = NULL;
1953 struct in_addr dhcp_next_server;
1954 comma = split(arg);
1955 dhcp_file = opt_string_alloc(arg);
1956 dhcp_next_server.s_addr = 0;
1957 if (comma)
1958 {
1959 arg = comma;
1960 comma = split(arg);
1961 dhcp_sname = opt_string_alloc(arg);
1962 if (comma)
1963 {
1964 unhide_metas(comma);
1965 if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1966 option = '?';
1967 }
1968 }
1969 if (option != '?')
1970 {
1971 struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
1972 new->file = dhcp_file;
1973 new->sname = dhcp_sname;
1974 new->next_server = dhcp_next_server;
1975 new->netid = id;
1976 new->next = daemon->boot_config;
1977 daemon->boot_config = new;
1978 }
1979 }
1980
1981 break;
1982 }
1983
1984 case LOPT_PXE_PROMT: /* --pxe-prompt */
1985 {
1986 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
1987 int timeout;
1988
1989 new->netid = NULL;
1990 new->opt = 10; /* PXE_MENU_PROMPT */
1991
1992 while (arg && strstr(arg, "net:") == arg)
1993 {
1994 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
1995 comma = split(arg);
1996 nn->next = new->netid;
1997 new->netid = nn;
1998 nn->net = opt_string_alloc(arg+4);
1999 arg = comma;
2000 }
2001
2002 if (!arg)
2003 option = '?';
2004 else
2005 {
2006 comma = split(arg);
2007 unhide_metas(arg);
2008 new->len = strlen(arg) + 1;
2009 new->val = opt_malloc(new->len);
2010 memcpy(new->val + 1, arg, new->len - 1);
2011
2012 new->u.vendor_class = (unsigned char *)"PXEClient";
2013 new->flags = DHOPT_VENDOR;
2014
2015 if (comma && atoi_check(comma, &timeout))
2016 *(new->val) = timeout;
2017 else
2018 *(new->val) = 255;
2019
2020 new->next = daemon->dhcp_opts;
2021 daemon->dhcp_opts = new;
2022 daemon->enable_pxe = 1;
2023 }
2024
2025 break;
2026 }
2027
2028 case LOPT_PXE_SERV: /* --pxe-service */
2029 {
2030 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2031 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2032 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2033 static int boottype = 32768;
2034
2035 new->netid = NULL;
2036 new->server.s_addr = 0;
2037
2038 while (arg && strstr(arg, "net:") == arg)
2039 {
2040 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2041 comma = split(arg);
2042 nn->next = new->netid;
2043 new->netid = nn;
2044 nn->net = opt_string_alloc(arg+4);
2045 arg = comma;
2046 }
2047
2048 if (arg && (comma = split(arg)))
2049 {
2050 for (i = 0; CSA[i]; i++)
2051 if (strcasecmp(CSA[i], arg) == 0)
2052 break;
2053
2054 if (CSA[i] || atoi_check(arg, &i))
2055 {
2056 arg = comma;
2057 comma = split(arg);
2058
2059 new->CSA = i;
2060 new->menu = opt_string_alloc(arg);
2061
2062 if (comma)
2063 {
2064 arg = comma;
2065 comma = split(arg);
2066 if (atoi_check(arg, &i))
2067 {
2068 new->type = i;
2069 new->basename = NULL;
2070 }
2071 else
2072 {
2073 new->type = boottype++;
2074 new->basename = opt_string_alloc(arg);
2075 }
2076
2077 if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
2078 option = '?';
2079
2080 /* Order matters */
2081 new->next = NULL;
2082 if (!daemon->pxe_services)
2083 daemon->pxe_services = new;
2084 else
2085 {
2086 struct pxe_service *s;
2087 for (s = daemon->pxe_services; s->next; s = s->next);
2088 s->next = new;
2089 }
2090
2091 daemon->enable_pxe = 1;
2092 break;
2093 }
2094 }
2095 }
2096
2097 option = '?';
2098 break;
2099 }
2100
2101 case '4': /* --dhcp-mac */
2102 {
2103 if (!(comma = split(arg)))
2104 option = '?';
2105 else
2106 {
2107 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2108 if (strstr(arg, "net:") == arg)
2109 new->netid.net = opt_string_alloc(arg+4);
2110 else
2111 new->netid.net = opt_string_alloc(arg);
2112 unhide_metas(comma);
2113 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2114 new->next = daemon->dhcp_macs;
2115 daemon->dhcp_macs = new;
2116 }
2117 }
2118 break;
2119
2120 case 'U': /* --dhcp-vendorclass */
2121 case 'j': /* --dhcp-userclass */
2122 case LOPT_CIRCUIT: /* --dhcp-circuitid */
2123 case LOPT_REMOTE: /* --dhcp-remoteid */
2124 case LOPT_SUBSCR: /* --dhcp-subscrid */
2125 {
2126 if (!(comma = split(arg)))
2127 option = '?';
2128 else
2129 {
2130 char *p;
2131 int dig = 0;
2132 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2133 if (strstr(arg, "net:") == arg)
2134 new->netid.net = opt_string_alloc(arg+4);
2135 else
2136 new->netid.net = opt_string_alloc(arg);
2137 /* check for hex string - must digits may include : must not have nothing else,
2138 only allowed for agent-options. */
2139 for (p = comma; *p; p++)
2140 if (isxdigit((int)*p))
2141 dig = 1;
2142 else if (*p != ':')
2143 break;
2144 unhide_metas(comma);
2145 if (option == 'U' || option == 'j' || *p || !dig)
2146 {
2147 new->len = strlen(comma);
2148 new->data = opt_malloc(new->len);
2149 memcpy(new->data, comma, new->len);
2150 }
2151 else
2152 {
2153 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2154 new->data = opt_malloc(new->len);
2155 memcpy(new->data, comma, new->len);
2156 }
2157
2158 switch (option)
2159 {
2160 case 'j':
2161 new->match_type = MATCH_USER;
2162 break;
2163 case 'U':
2164 new->match_type = MATCH_VENDOR;
2165 break;
2166 case LOPT_CIRCUIT:
2167 new->match_type = MATCH_CIRCUIT;
2168 break;
2169 case LOPT_REMOTE:
2170 new->match_type = MATCH_REMOTE;
2171 break;
2172 case LOPT_SUBSCR:
2173 new->match_type = MATCH_SUBSCRIBER;
2174 break;
2175 }
2176 new->next = daemon->dhcp_vendors;
2177 daemon->dhcp_vendors = new;
2178 }
2179 break;
2180 }
2181
2182 case LOPT_ALTPORT: /* --dhcp-alternate-port */
2183 if (!arg)
2184 {
2185 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2186 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2187 }
2188 else
2189 {
2190 comma = split(arg);
2191 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2192 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
2193 problem = _("invalid port number");
2194 if (!comma)
2195 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2196 }
2197 break;
2198
2199 case 'J': /* --dhcp-ignore */
2200 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
2201 case LOPT_BROADCAST: /* --dhcp-broadcast */
2202 case '3': /* --bootp-dynamic */
2203 {
2204 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
2205 struct dhcp_netid *list = NULL;
2206 if (option == 'J')
2207 {
2208 new->next = daemon->dhcp_ignore;
2209 daemon->dhcp_ignore = new;
2210 }
2211 else if (option == LOPT_BROADCAST)
2212 {
2213 new->next = daemon->force_broadcast;
2214 daemon->force_broadcast = new;
2215 }
2216 else if (option == '3')
2217 {
2218 new->next = daemon->bootp_dynamic;
2219 daemon->bootp_dynamic = new;
2220 }
2221 else
2222 {
2223 new->next = daemon->dhcp_ignore_names;
2224 daemon->dhcp_ignore_names = new;
2225 }
2226
2227 while (arg) {
2228 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
2229 comma = split(arg);
2230 member->next = list;
2231 list = member;
2232 if (strstr(arg, "net:") == arg)
2233 member->net = opt_string_alloc(arg+4);
2234 else
2235 member->net = opt_string_alloc(arg);
2236 arg = comma;
2237 }
2238
2239 new->list = list;
2240 break;
2241 }
2242 #endif
2243
2244 case 'V': /* --alias */
2245 {
2246 char *dash, *a[3] = { NULL, NULL, NULL };
2247 int k = 0;
2248 struct doctor *new = opt_malloc(sizeof(struct doctor));
2249 new->next = daemon->doctors;
2250 daemon->doctors = new;
2251 new->mask.s_addr = 0xffffffff;
2252 new->end.s_addr = 0;
2253
2254 if ((a[0] = arg))
2255 for (k = 1; k < 3; k++)
2256 {
2257 if (!(a[k] = split(a[k-1])))
2258 break;
2259 unhide_metas(a[k]);
2260 }
2261
2262 dash = split_chr(a[0], '-');
2263
2264 if ((k < 2) ||
2265 ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
2266 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
2267 option = '?';
2268
2269 if (k == 3)
2270 new->mask.s_addr = inet_addr(a[2]);
2271
2272 if (dash &&
2273 ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
2274 !is_same_net(new->in, new->end, new->mask) ||
2275 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
2276 problem = _("invalid alias range");
2277
2278 break;
2279 }
2280
2281 case LOPT_INTNAME: /* --interface-name */
2282 {
2283 struct interface_name *new, **up;
2284 char *domain = NULL;
2285
2286 comma = split(arg);
2287
2288 if (!comma || !(domain = canonicalise_opt(arg)))
2289 problem = _("bad interface name");
2290
2291 new = opt_malloc(sizeof(struct interface_name));
2292 new->next = NULL;
2293 /* Add to the end of the list, so that first name
2294 of an interface is used for PTR lookups. */
2295 for (up = &daemon->int_names; *up; up = &((*up)->next));
2296 *up = new;
2297 new->name = domain;
2298 new->intr = opt_string_alloc(comma);
2299 break;
2300 }
2301
2302 case LOPT_CNAME: /* --cname */
2303 {
2304 struct cname *new;
2305
2306 if (!(comma = split(arg)))
2307 option = '?';
2308 else
2309 {
2310 char *alias = canonicalise_opt(arg);
2311 char *target = canonicalise_opt(comma);
2312
2313 if (!alias || !target)
2314 problem = _("bad CNAME");
2315 else
2316 {
2317 for (new = daemon->cnames; new; new = new->next)
2318 if (hostname_isequal(new->alias, arg))
2319 problem = _("duplicate CNAME");
2320 new = opt_malloc(sizeof(struct cname));
2321 new->next = daemon->cnames;
2322 daemon->cnames = new;
2323 new->alias = alias;
2324 new->target = target;
2325 }
2326 }
2327 break;
2328 }
2329
2330 case LOPT_PTR: /* --ptr-record */
2331 {
2332 struct ptr_record *new;
2333 char *dom, *target = NULL;
2334
2335 comma = split(arg);
2336
2337 if (!(dom = canonicalise_opt(arg)) ||
2338 (comma && !(target = canonicalise_opt(comma))))
2339 problem = _("bad PTR record");
2340 else
2341 {
2342 new = opt_malloc(sizeof(struct ptr_record));
2343 new->next = daemon->ptr;
2344 daemon->ptr = new;
2345 new->name = dom;
2346 new->ptr = target;
2347 }
2348 break;
2349 }
2350
2351 case LOPT_NAPTR: /* --naptr-record */
2352 {
2353 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2354 int k = 0;
2355 struct naptr *new;
2356 int order, pref;
2357 char *name, *replace = NULL;
2358
2359 if ((a[0] = arg))
2360 for (k = 1; k < 7; k++)
2361 if (!(a[k] = split(a[k-1])))
2362 break;
2363
2364
2365 if (k < 6 ||
2366 !(name = canonicalise_opt(a[0])) ||
2367 !atoi_check16(a[1], &order) ||
2368 !atoi_check16(a[2], &pref) ||
2369 (k == 7 && !(replace = canonicalise_opt(a[6]))))
2370 problem = _("bad NAPTR record");
2371 else
2372 {
2373 new = opt_malloc(sizeof(struct naptr));
2374 new->next = daemon->naptr;
2375 daemon->naptr = new;
2376 new->name = name;
2377 new->flags = opt_string_alloc(a[3]);
2378 new->services = opt_string_alloc(a[4]);
2379 new->regexp = opt_string_alloc(a[5]);
2380 new->replace = replace;
2381 new->order = order;
2382 new->pref = pref;
2383 }
2384 break;
2385 }
2386
2387 case 'Y': /* --txt-record */
2388 {
2389 struct txt_record *new;
2390 unsigned char *p, *q;
2391
2392 if ((comma = split(arg)))
2393 comma--;
2394
2395 gen_prob = _("TXT record string too long");
2396
2397 if ((q = (unsigned char *)comma))
2398 while (1)
2399 {
2400 size_t len;
2401 if ((p = (unsigned char *)strchr((char*)q+1, ',')))
2402 {
2403 if ((len = p - q - 1) > 255)
2404 option = '?';
2405 *q = len;
2406 for (q = q+1; q < p; q++)
2407 *q = unhide_meta(*q);
2408 }
2409 else
2410 {
2411 if ((len = strlen((char *)q+1)) > 255)
2412 option = '?';
2413 *q = len;
2414 for (q = q+1; *q; q++)
2415 *q = unhide_meta(*q);
2416 break;
2417 }
2418 }
2419
2420 new = opt_malloc(sizeof(struct txt_record));
2421 new->next = daemon->txt;
2422 daemon->txt = new;
2423 new->class = C_IN;
2424 if (comma)
2425 {
2426 new->len = q - ((unsigned char *)comma);
2427 new->txt = opt_malloc(new->len);
2428 memcpy(new->txt, comma, new->len);
2429 }
2430 else
2431 {
2432 static char empty[] = "";
2433 new->len = 1;
2434 new->txt = empty;
2435 }
2436
2437 /* ensure arg is terminated */
2438 if (comma)
2439 *comma = 0;
2440
2441 if (!(new->name = canonicalise_opt(arg)))
2442 {
2443 problem = _("bad TXT record");
2444 break;
2445 }
2446
2447 break;
2448 }
2449
2450 case 'W': /* --srv-host */
2451 {
2452 int port = 1, priority = 0, weight = 0;
2453 char *name, *target = NULL;
2454 struct mx_srv_record *new;
2455
2456 comma = split(arg);
2457
2458 if (!(name = canonicalise_opt(arg)))
2459 problem = _("bad SRV record");
2460
2461 if (comma)
2462 {
2463 arg = comma;
2464 comma = split(arg);
2465 if (!(target = canonicalise_opt(arg))
2466 ) problem = _("bad SRV target");
2467
2468 if (comma)
2469 {
2470 arg = comma;
2471 comma = split(arg);
2472 if (!atoi_check16(arg, &port))
2473 problem = _("invalid port number");
2474
2475 if (comma)
2476 {
2477 arg = comma;
2478 comma = split(arg);
2479 if (!atoi_check16(arg, &priority))
2480 problem = _("invalid priority");
2481
2482 if (comma)
2483 {
2484 arg = comma;
2485 comma = split(arg);
2486 if (!atoi_check16(arg, &weight))
2487 problem = _("invalid weight");
2488 }
2489 }
2490 }
2491 }
2492
2493 new = opt_malloc(sizeof(struct mx_srv_record));
2494 new->next = daemon->mxnames;
2495 daemon->mxnames = new;
2496 new->issrv = 1;
2497 new->name = name;
2498 new->target = target;
2499 new->srvport = port;
2500 new->priority = priority;
2501 new->weight = weight;
2502 break;
2503 }
2504
2505 case LOPT_LISTNMARK: /* --listen-mark */
2506 {
2507 char *endptr;
2508 uint32_t mark = strtoul(arg, &endptr, 0);
2509 my_syslog(LOG_WARNING, "passed-in mark: %s", arg);
2510 if (!*endptr)
2511 daemon->listen_mark = mark;
2512 else
2513 problem = _("invalid mark");
2514 my_syslog(LOG_WARNING, "daemon->listen_mark: 0x%x, *endptr=%d", daemon->listen_mark, *endptr);
2515 break;
2516 }
2517
2518 default:
2519 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2520
2521 }
2522
2523 if (problem)
2524 return problem;
2525
2526 if (option == '?')
2527 return gen_prob;
2528
2529 return NULL;
2530 }
2531
one_file(char * file,int nest,int hard_opt)2532 static void one_file(char *file, int nest, int hard_opt)
2533 {
2534 volatile int lineno = 0;
2535 int i, option;
2536 FILE *f;
2537 char *p, *arg, *start, *buff = daemon->namebuff;
2538 static struct fileread {
2539 dev_t dev;
2540 ino_t ino;
2541 struct fileread *next;
2542 } *filesread = NULL;
2543 struct stat statbuf;
2544
2545 /* ignore repeated files. */
2546 if (hard_opt == 0 && stat(file, &statbuf) == 0)
2547 {
2548 struct fileread *r;
2549
2550 for (r = filesread; r; r = r->next)
2551 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
2552 return;
2553
2554 r = safe_malloc(sizeof(struct fileread));
2555 r->next = filesread;
2556 filesread = r;
2557 r->dev = statbuf.st_dev;
2558 r->ino = statbuf.st_ino;
2559 }
2560
2561 if (nest > 20)
2562 die(_("files nested too deep in %s"), file, EC_BADCONF);
2563
2564 if (!(f = fopen(file, "r")))
2565 {
2566 if (errno == ENOENT && nest == 0)
2567 return; /* No conffile, all done. */
2568 else
2569 {
2570 char *str = _("cannot read %s: %s");
2571 if (hard_opt != 0)
2572 {
2573 my_syslog(LOG_ERR, str, file, strerror(errno));
2574 return;
2575 }
2576 else
2577 die(str, file, EC_FILE);
2578 }
2579 }
2580
2581 while (fgets(buff, MAXDNAME, f))
2582 {
2583 int white;
2584 unsigned int lastquote;
2585 char *errmess;
2586
2587 /* Memory allocation failure longjmps here if mem_recover == 1 */
2588 if (hard_opt)
2589 {
2590 if (setjmp(mem_jmp))
2591 continue;
2592 mem_recover = 1;
2593 }
2594
2595 lineno++;
2596 errmess = NULL;
2597
2598 /* Implement quotes, inside quotes we allow \\ \" \n and \t
2599 metacharacters get hidden also strip comments */
2600
2601 for (white = 1, lastquote = 0, p = buff; *p; p++)
2602 {
2603 if (*p == '"')
2604 {
2605 memmove(p, p+1, strlen(p+1)+1);
2606 for(; *p && *p != '"'; p++)
2607 {
2608 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
2609 {
2610 if (p[1] == 't')
2611 p[1] = '\t';
2612 else if (p[1] == 'n')
2613 p[1] = '\n';
2614 else if (p[1] == 'b')
2615 p[1] = '\b';
2616 else if (p[1] == 'r')
2617 p[1] = '\r';
2618 else if (p[1] == 'e') /* escape */
2619 p[1] = '\033';
2620 memmove(p, p+1, strlen(p+1)+1);
2621 }
2622 *p = hide_meta(*p);
2623 }
2624 if (*p == '"')
2625 {
2626 memmove(p, p+1, strlen(p+1)+1);
2627 lastquote = p - buff;
2628 }
2629 else
2630 {
2631 errmess = _("missing \"");
2632 goto oops;
2633 }
2634 }
2635
2636 if (white && *p == '#')
2637 {
2638 *p = 0;
2639 break;
2640 }
2641 white = isspace((int)unhide_meta(*p));
2642 }
2643
2644 /* fgets gets end of line char too. */
2645 while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1])))
2646 buff[strlen(buff)-1] = 0;
2647
2648 if (*buff == 0)
2649 continue;
2650
2651 if (hard_opt != 0)
2652 arg = buff;
2653 else if ((p=strchr(buff, '=')))
2654 {
2655 /* allow spaces around "=" */
2656 arg = p+1;
2657 for (; p >= buff && (isspace((int)*p) || *p == '='); p--)
2658 *p = 0;
2659 }
2660 else
2661 arg = NULL;
2662
2663 if (hard_opt != 0)
2664 option = hard_opt;
2665 else
2666 {
2667 /* skip leading space */
2668 for (start = buff; *start && isspace((int)*start); start++);
2669
2670 for (option = 0, i = 0; opts[i].name; i++)
2671 if (strcmp(opts[i].name, start) == 0)
2672 {
2673 option = opts[i].val;
2674 break;
2675 }
2676
2677 if (!option)
2678 errmess = _("bad option");
2679 else if (opts[i].has_arg == 0 && arg)
2680 errmess = _("extraneous parameter");
2681 else if (opts[i].has_arg == 1 && !arg)
2682 errmess = _("missing parameter");
2683 }
2684
2685 if (!errmess)
2686 {
2687 if (arg)
2688 for (; isspace((int)*arg); arg++);
2689
2690 errmess = one_opt(option, arg, _("error"), nest + 1);
2691 }
2692
2693 if (errmess)
2694 {
2695 oops:
2696 sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
2697 if (hard_opt != 0)
2698 my_syslog(LOG_ERR, buff, file);
2699 else
2700 die(buff, file, EC_BADCONF);
2701 }
2702 }
2703
2704 mem_recover = 1;
2705 fclose(f);
2706 }
2707
2708 #ifdef HAVE_DHCP
reread_dhcp(void)2709 void reread_dhcp(void)
2710 {
2711 if (daemon->dhcp_hosts_file)
2712 {
2713 struct dhcp_config *configs, *cp, **up;
2714
2715 /* remove existing... */
2716 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
2717 {
2718 cp = configs->next;
2719
2720 if (configs->flags & CONFIG_BANK)
2721 {
2722 struct hwaddr_config *mac, *tmp;
2723
2724 for (mac = configs->hwaddr; mac; mac = tmp)
2725 {
2726 tmp = mac->next;
2727 free(mac);
2728 }
2729 if (configs->flags & CONFIG_CLID)
2730 free(configs->clid);
2731 if (configs->flags & CONFIG_NETID)
2732 free(configs->netid.net);
2733 if (configs->flags & CONFIG_NAME)
2734 free(configs->hostname);
2735
2736
2737 *up = configs->next;
2738 free(configs);
2739 }
2740 else
2741 up = &configs->next;
2742 }
2743
2744 one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
2745 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
2746 }
2747
2748 if (daemon->dhcp_opts_file)
2749 {
2750 struct dhcp_opt *opts, *cp, **up;
2751 struct dhcp_netid *id, *next;
2752
2753 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
2754 {
2755 cp = opts->next;
2756
2757 if (opts->flags & DHOPT_BANK)
2758 {
2759 if ((opts->flags & DHOPT_VENDOR))
2760 free(opts->u.vendor_class);
2761 free(opts->val);
2762 for (id = opts->netid; id; id = next)
2763 {
2764 next = id->next;
2765 free(id->net);
2766 free(id);
2767 }
2768 *up = opts->next;
2769 free(opts);
2770 }
2771 else
2772 up = &opts->next;
2773 }
2774
2775 one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
2776 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
2777 }
2778 }
2779 #endif
2780
read_opts(int argc,char ** argv,char * compile_opts)2781 void read_opts(int argc, char **argv, char *compile_opts)
2782 {
2783 char *buff = opt_malloc(MAXDNAME);
2784 int option, nest = 0, testmode = 0;
2785 char *errmess, *arg, *conffile = CONFFILE;
2786
2787 opterr = 0;
2788
2789 daemon = opt_malloc(sizeof(struct daemon));
2790 memset(daemon, 0, sizeof(struct daemon));
2791 daemon->namebuff = buff;
2792
2793 /* Set defaults - everything else is zero or NULL */
2794 daemon->cachesize = CACHESIZ;
2795 daemon->ftabsize = FTABSIZ;
2796 daemon->port = NAMESERVER_PORT;
2797 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
2798 daemon->dhcp_server_port = DHCP_SERVER_PORT;
2799 daemon->default_resolv.is_default = 1;
2800 daemon->default_resolv.name = RESOLVFILE;
2801 daemon->resolv_files = &daemon->default_resolv;
2802 daemon->username = CHUSER;
2803 daemon->runfile = RUNFILE;
2804 daemon->dhcp_max = MAXLEASES;
2805 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
2806 daemon->edns_pktsz = EDNS_PKTSZ;
2807 daemon->log_fac = -1;
2808 add_txt("version.bind", "dnsmasq-" VERSION );
2809 add_txt("authors.bind", "Simon Kelley");
2810 add_txt("copyright.bind", COPYRIGHT);
2811
2812 while (1)
2813 {
2814 #ifdef HAVE_GETOPT_LONG
2815 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
2816 #else
2817 option = getopt(argc, argv, OPTSTRING);
2818 #endif
2819
2820 if (option == -1)
2821 break;
2822
2823 /* Copy optarg so that argv doesn't get changed */
2824 if (optarg)
2825 {
2826 strncpy(buff, optarg, MAXDNAME);
2827 buff[MAXDNAME-1] = 0;
2828 arg = buff;
2829 }
2830 else
2831 arg = NULL;
2832
2833 /* command-line only stuff */
2834 if (option == LOPT_TEST)
2835 testmode = 1;
2836 else if (option == 'w')
2837 {
2838 if (argc != 3 || strcmp(argv[2], "dhcp") != 0)
2839 do_usage();
2840 #ifdef HAVE_DHCP
2841 else
2842 display_opts();
2843 #endif
2844 exit(0);
2845 }
2846 else if (option == 'v')
2847 {
2848 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
2849 printf(_("Compile time options %s\n\n"), compile_opts);
2850 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
2851 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
2852 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
2853 exit(0);
2854 }
2855 else if (option == 'C')
2856 {
2857 conffile = opt_string_alloc(arg);
2858 nest++;
2859 }
2860 else
2861 {
2862 #ifdef HAVE_GETOPT_LONG
2863 errmess = one_opt(option, arg, _("try --help"), 0);
2864 #else
2865 errmess = one_opt(option, arg, _("try -w"), 0);
2866 #endif
2867 if (errmess)
2868 die(_("bad command line options: %s"), errmess, EC_BADCONF);
2869 }
2870 }
2871
2872 if (conffile)
2873 one_file(conffile, nest, 0);
2874
2875 /* port might not be known when the address is parsed - fill in here */
2876 if (daemon->servers)
2877 {
2878 struct server *tmp;
2879 for (tmp = daemon->servers; tmp; tmp = tmp->next)
2880 if (!(tmp->flags & SERV_HAS_SOURCE))
2881 {
2882 if (tmp->source_addr.sa.sa_family == AF_INET)
2883 tmp->source_addr.in.sin_port = htons(daemon->query_port);
2884 #ifdef HAVE_IPV6
2885 else if (tmp->source_addr.sa.sa_family == AF_INET6)
2886 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
2887 #endif
2888 }
2889 }
2890
2891 if (daemon->if_addrs)
2892 {
2893 struct iname *tmp;
2894 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
2895 if (tmp->addr.sa.sa_family == AF_INET)
2896 tmp->addr.in.sin_port = htons(daemon->port);
2897 #ifdef HAVE_IPV6
2898 else if (tmp->addr.sa.sa_family == AF_INET6)
2899 tmp->addr.in6.sin6_port = htons(daemon->port);
2900 #endif /* IPv6 */
2901 }
2902
2903 /* only one of these need be specified: the other defaults to the host-name */
2904 if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
2905 {
2906 struct mx_srv_record *mx;
2907
2908 if (gethostname(buff, MAXDNAME) == -1)
2909 die(_("cannot get host-name: %s"), NULL, EC_MISC);
2910
2911 for (mx = daemon->mxnames; mx; mx = mx->next)
2912 if (!mx->issrv && hostname_isequal(mx->name, buff))
2913 break;
2914
2915 if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
2916 {
2917 mx = opt_malloc(sizeof(struct mx_srv_record));
2918 mx->next = daemon->mxnames;
2919 mx->issrv = 0;
2920 mx->target = NULL;
2921 mx->name = opt_string_alloc(buff);
2922 daemon->mxnames = mx;
2923 }
2924
2925 if (!daemon->mxtarget)
2926 daemon->mxtarget = opt_string_alloc(buff);
2927
2928 for (mx = daemon->mxnames; mx; mx = mx->next)
2929 if (!mx->issrv && !mx->target)
2930 mx->target = daemon->mxtarget;
2931 }
2932
2933 if (!(daemon->options & OPT_NO_RESOLV) &&
2934 daemon->resolv_files &&
2935 daemon->resolv_files->next &&
2936 (daemon->options & OPT_NO_POLL))
2937 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
2938
2939 if (daemon->options & OPT_RESOLV_DOMAIN)
2940 {
2941 char *line;
2942 FILE *f;
2943
2944 if ((daemon->options & OPT_NO_RESOLV) ||
2945 !daemon->resolv_files ||
2946 (daemon->resolv_files)->next)
2947 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
2948
2949 if (!(f = fopen((daemon->resolv_files)->name, "r")))
2950 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
2951
2952 while ((line = fgets(buff, MAXDNAME, f)))
2953 {
2954 char *token = strtok(line, " \t\n\r");
2955
2956 if (!token || strcmp(token, "search") != 0)
2957 continue;
2958
2959 if ((token = strtok(NULL, " \t\n\r")) &&
2960 (daemon->domain_suffix = canonicalise_opt(token)))
2961 break;
2962 }
2963
2964 fclose(f);
2965
2966 if (!daemon->domain_suffix)
2967 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
2968 }
2969
2970 if (daemon->domain_suffix)
2971 {
2972 /* add domain for any srv record without one. */
2973 struct mx_srv_record *srv;
2974
2975 for (srv = daemon->mxnames; srv; srv = srv->next)
2976 if (srv->issrv &&
2977 strchr(srv->name, '.') &&
2978 strchr(srv->name, '.') == strrchr(srv->name, '.'))
2979 {
2980 strcpy(buff, srv->name);
2981 strcat(buff, ".");
2982 strcat(buff, daemon->domain_suffix);
2983 free(srv->name);
2984 srv->name = opt_string_alloc(buff);
2985 }
2986 }
2987 else if (daemon->options & OPT_DHCP_FQDN)
2988 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
2989
2990 if (testmode)
2991 {
2992 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
2993 exit(0);
2994 }
2995 }
2996