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