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