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