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