Dnsmasq: 2.60 update
[tomato.git] / release / src / router / dnsmasq / src / option.c
blobee7989a136d350f94f448cc62d820a90087cb4db
1 /* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
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.
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.
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/>.
17 /* define this to get facilitynames */
18 #define SYSLOG_NAMES
19 #include "dnsmasq.h"
20 #include <setjmp.h>
22 static volatile int mem_recover = 0;
23 static jmp_buf mem_jmp;
24 static void one_file(char *file, int hard_opt);
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 }
53 #endif
55 #ifndef HAVE_GETOPT_LONG
56 struct myoption {
57 const char *name;
58 int has_arg;
59 int *flag;
60 int val;
62 #endif
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:"
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 #define LOPT_RA 306
119 #ifdef HAVE_GETOPT_LONG
120 static const struct option opts[] =
121 #else
122 static const struct myoption opts[] =
123 #endif
125 { "version", 0, 0, 'v' },
126 { "no-hosts", 0, 0, 'h' },
127 { "no-poll", 0, 0, 'n' },
128 { "help", 0, 0, 'w' },
129 { "no-daemon", 0, 0, 'd' },
130 { "log-queries", 0, 0, 'q' },
131 { "user", 2, 0, 'u' },
132 { "group", 2, 0, 'g' },
133 { "resolv-file", 2, 0, 'r' },
134 { "mx-host", 1, 0, 'm' },
135 { "mx-target", 1, 0, 't' },
136 { "cache-size", 2, 0, 'c' },
137 { "port", 1, 0, 'p' },
138 { "dhcp-leasefile", 2, 0, 'l' },
139 { "dhcp-lease", 1, 0, 'l' },
140 { "dhcp-host", 1, 0, 'G' },
141 { "dhcp-range", 1, 0, 'F' },
142 { "dhcp-option", 1, 0, 'O' },
143 { "dhcp-boot", 1, 0, 'M' },
144 { "domain", 1, 0, 's' },
145 { "domain-suffix", 1, 0, 's' },
146 { "interface", 1, 0, 'i' },
147 { "listen-address", 1, 0, 'a' },
148 { "bogus-priv", 0, 0, 'b' },
149 { "bogus-nxdomain", 1, 0, 'B' },
150 { "selfmx", 0, 0, 'e' },
151 { "filterwin2k", 0, 0, 'f' },
152 { "pid-file", 2, 0, 'x' },
153 { "strict-order", 0, 0, 'o' },
154 { "server", 1, 0, 'S' },
155 { "local", 1, 0, LOPT_LOCAL },
156 { "address", 1, 0, 'A' },
157 { "conf-file", 2, 0, 'C' },
158 { "no-resolv", 0, 0, 'R' },
159 { "expand-hosts", 0, 0, 'E' },
160 { "localmx", 0, 0, 'L' },
161 { "local-ttl", 1, 0, 'T' },
162 { "no-negcache", 0, 0, 'N' },
163 { "addn-hosts", 1, 0, 'H' },
164 { "query-port", 1, 0, 'Q' },
165 { "except-interface", 1, 0, 'I' },
166 { "no-dhcp-interface", 1, 0, '2' },
167 { "domain-needed", 0, 0, 'D' },
168 { "dhcp-lease-max", 1, 0, 'X' },
169 { "bind-interfaces", 0, 0, 'z' },
170 { "read-ethers", 0, 0, 'Z' },
171 { "alias", 1, 0, 'V' },
172 { "dhcp-vendorclass", 1, 0, 'U' },
173 { "dhcp-userclass", 1, 0, 'j' },
174 { "dhcp-ignore", 1, 0, 'J' },
175 { "edns-packet-max", 1, 0, 'P' },
176 { "keep-in-foreground", 0, 0, 'k' },
177 { "dhcp-authoritative", 0, 0, 'K' },
178 { "srv-host", 1, 0, 'W' },
179 { "localise-queries", 0, 0, 'y' },
180 { "txt-record", 1, 0, 'Y' },
181 { "enable-dbus", 0, 0, '1' },
182 { "bootp-dynamic", 2, 0, '3' },
183 { "dhcp-mac", 1, 0, '4' },
184 { "no-ping", 0, 0, '5' },
185 { "dhcp-script", 1, 0, '6' },
186 { "conf-dir", 1, 0, '7' },
187 { "log-facility", 1, 0 ,'8' },
188 { "leasefile-ro", 0, 0, '9' },
189 { "dns-forward-max", 1, 0, '0' },
190 { "clear-on-reload", 0, 0, LOPT_RELOAD },
191 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
192 { "enable-tftp", 2, 0, LOPT_TFTP },
193 { "tftp-secure", 0, 0, LOPT_SECURE },
194 { "tftp-unique-root", 0, 0, LOPT_APREF },
195 { "tftp-root", 1, 0, LOPT_PREFIX },
196 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
197 { "ptr-record", 1, 0, LOPT_PTR },
198 { "naptr-record", 1, 0, LOPT_NAPTR },
199 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
200 { "dhcp-option-force", 1, 0, LOPT_FORCE },
201 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
202 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
203 { "log-async", 2, 0, LOPT_MAX_LOGS },
204 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
205 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
206 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
207 { "interface-name", 1, 0, LOPT_INTNAME },
208 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
209 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
210 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
211 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
212 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
213 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
214 { "all-servers", 0, 0, LOPT_NOLAST },
215 { "dhcp-match", 1, 0, LOPT_MATCH },
216 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
217 { "neg-ttl", 1, 0, LOPT_NEGTTL },
218 { "max-ttl", 1, 0, LOPT_MAXTTL },
219 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
220 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
221 { "min-port", 1, 0, LOPT_MINPORT },
222 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
223 { "cname", 1, 0, LOPT_CNAME },
224 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
225 { "pxe-service", 1, 0, LOPT_PXE_SERV },
226 { "test", 0, 0, LOPT_TEST },
227 { "tag-if", 1, 0, LOPT_TAG_IF },
228 { "dhcp-proxy", 2, 0, LOPT_PROXY },
229 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
230 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
231 { "add-mac", 0, 0, LOPT_ADD_MAC },
232 { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
233 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
234 { "conntrack", 0, 0, LOPT_CONNTRACK },
235 { "dhcp-client-update", 0, 0, LOPT_FQDN },
236 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
237 { "enable-ra", 0, 0, LOPT_RA },
238 { NULL, 0, 0, 0 }
242 #define ARG_DUP OPT_LAST
243 #define ARG_ONE OPT_LAST + 1
244 #define ARG_USED_CL OPT_LAST + 2
245 #define ARG_USED_FILE OPT_LAST + 3
247 static struct {
248 int opt;
249 unsigned int rept;
250 char * const flagdesc;
251 char * const desc;
252 char * const arg;
253 } usage[] = {
254 { 'a', ARG_DUP, "<ipaddr>", gettext_noop("Specify local address(es) to listen on."), NULL },
255 { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
256 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
257 { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
258 { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
259 { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
260 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
261 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
262 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
263 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
264 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
265 { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
266 { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
267 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
268 { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
269 { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
270 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
271 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
272 { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
273 { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
274 { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
275 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
276 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
277 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
278 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
279 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
280 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
281 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
282 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
283 { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
284 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
285 { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
286 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
287 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
288 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
289 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
290 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
291 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
292 { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
293 { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
294 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
295 { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
296 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
297 { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
298 { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
299 { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
300 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
301 { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
302 { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
303 { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
304 { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
305 { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
306 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
307 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
308 { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
309 { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
310 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
311 { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
312 { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
313 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
314 { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
315 { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
316 { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
317 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
318 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
319 { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
320 { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
321 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
322 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
323 { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
324 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
325 { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
326 { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
327 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
328 { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
329 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
330 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
331 { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
332 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
333 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
334 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
335 { LOPT_TFTP, ARG_DUP, "[=<interface>]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
336 { LOPT_PREFIX, ARG_ONE, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
337 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
338 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
339 { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
340 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
341 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
342 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
343 { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
344 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
345 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
346 { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
347 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
348 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
349 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
350 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
351 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
352 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
353 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
354 { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
355 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
356 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
357 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
358 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
359 { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
360 { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
361 { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
362 { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
363 { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
364 { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
365 { 0, 0, NULL, NULL, NULL }
368 #ifdef HAVE_DHCP
370 #define OT_ADDR_LIST 0x8000
371 #define OT_RFC1035_NAME 0x4000
372 #define OT_INTERNAL 0x2000
373 #define OT_NAME 0x1000
374 #define OT_CSTRING 0x0800
376 static const struct opttab_t {
377 char *name;
378 u16 val, size;
379 } opttab[] = {
380 { "netmask", 1, OT_ADDR_LIST },
381 { "time-offset", 2, 4 },
382 { "router", 3, OT_ADDR_LIST },
383 { "dns-server", 6, OT_ADDR_LIST },
384 { "log-server", 7, OT_ADDR_LIST },
385 { "lpr-server", 9, OT_ADDR_LIST },
386 { "hostname", 12, OT_INTERNAL | OT_NAME },
387 { "boot-file-size", 13, 2 },
388 { "domain-name", 15, OT_NAME },
389 { "swap-server", 16, OT_ADDR_LIST },
390 { "root-path", 17, OT_NAME },
391 { "extension-path", 18, OT_NAME },
392 { "ip-forward-enable", 19, 1 },
393 { "non-local-source-routing", 20, 1 },
394 { "policy-filter", 21, OT_ADDR_LIST },
395 { "max-datagram-reassembly", 22, 2 },
396 { "default-ttl", 23, 1 },
397 { "mtu", 26, 2 },
398 { "all-subnets-local", 27, 1 },
399 { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
400 { "router-discovery", 31, 1 },
401 { "router-solicitation", 32, OT_ADDR_LIST },
402 { "static-route", 33, OT_ADDR_LIST },
403 { "trailer-encapsulation", 34, 1 },
404 { "arp-timeout", 35, 4 },
405 { "ethernet-encap", 36, 1 },
406 { "tcp-ttl", 37, 1 },
407 { "tcp-keepalive", 38, 4 },
408 { "nis-domain", 40, OT_NAME },
409 { "nis-server", 41, OT_ADDR_LIST },
410 { "ntp-server", 42, OT_ADDR_LIST },
411 { "vendor-encap", 43, OT_INTERNAL },
412 { "netbios-ns", 44, OT_ADDR_LIST },
413 { "netbios-dd", 45, OT_ADDR_LIST },
414 { "netbios-nodetype", 46, 1 },
415 { "netbios-scope", 47, 0 },
416 { "x-windows-fs", 48, OT_ADDR_LIST },
417 { "x-windows-dm", 49, OT_ADDR_LIST },
418 { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
419 { "lease-time", 51, OT_INTERNAL },
420 { "option-overload", 52, OT_INTERNAL },
421 { "message-type", 53, OT_INTERNAL, },
422 { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
423 { "parameter-request", 55, OT_INTERNAL },
424 { "message", 56, OT_INTERNAL },
425 { "max-message-size", 57, OT_INTERNAL },
426 { "T1", 58, OT_INTERNAL },
427 { "T2", 59, OT_INTERNAL },
428 { "vendor-class", 60, 0 },
429 { "client-id", 61, OT_INTERNAL },
430 { "nis+-domain", 64, OT_NAME },
431 { "nis+-server", 65, OT_ADDR_LIST },
432 { "tftp-server", 66, OT_NAME },
433 { "bootfile-name", 67, OT_NAME },
434 { "mobile-ip-home", 68, OT_ADDR_LIST },
435 { "smtp-server", 69, OT_ADDR_LIST },
436 { "pop3-server", 70, OT_ADDR_LIST },
437 { "nntp-server", 71, OT_ADDR_LIST },
438 { "irc-server", 74, OT_ADDR_LIST },
439 { "user-class", 77, 0 },
440 { "FQDN", 81, OT_INTERNAL },
441 { "agent-id", 82, OT_INTERNAL },
442 { "client-arch", 93, 2 },
443 { "client-interface-id", 94, 0 },
444 { "client-machine-id", 97, 0 },
445 { "subnet-select", 118, OT_INTERNAL },
446 { "domain-search", 119, OT_RFC1035_NAME },
447 { "sip-server", 120, 0 },
448 { "classless-static-route", 121, 0 },
449 { "vendor-id-encap", 125, 0 },
450 { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
451 { NULL, 0, 0 }
454 #ifdef HAVE_DHCP6
455 static const struct opttab_t opttab6[] = {
456 { "client-id", 1, OT_INTERNAL },
457 { "server-id", 2, OT_INTERNAL },
458 { "ia-na", 3, OT_INTERNAL },
459 { "ia-ta", 4, OT_INTERNAL },
460 { "iaaddr", 5, OT_INTERNAL },
461 { "oro", 6, OT_INTERNAL },
462 { "preference", 7, OT_INTERNAL },
463 { "unicast", 12, OT_INTERNAL },
464 { "status-code", 13, OT_INTERNAL },
465 { "rapid-commit", 14, OT_INTERNAL },
466 { "user-class", 15, OT_INTERNAL | OT_CSTRING },
467 { "vendor-class", 16, OT_INTERNAL | OT_CSTRING },
468 { "vendor-opts", 17, OT_INTERNAL },
469 { "sip-server-domain", 21, OT_RFC1035_NAME },
470 { "sip-server", 22, OT_ADDR_LIST },
471 { "dns-server", 23, OT_ADDR_LIST },
472 { "domain-search", 24, OT_RFC1035_NAME },
473 { "nis-server", 27, OT_ADDR_LIST },
474 { "nis+-server", 28, OT_ADDR_LIST },
475 { "nis-domain", 29, OT_RFC1035_NAME },
476 { "nis+-domain", 30, OT_RFC1035_NAME },
477 { "sntp-server", 31, OT_ADDR_LIST },
478 { "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
479 { "ntp-server", 56, OT_ADDR_LIST },
480 { "bootfile-url", 59, OT_NAME },
481 { "bootfile-param", 60, OT_CSTRING },
482 { NULL, 0, 0 }
484 #endif
487 char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len)
489 int o, i, j, nodecode = 0;
490 const struct opttab_t *ot = opttab;
492 #ifdef HAVE_DHCP6
493 if (prot == AF_INET6)
494 ot = opttab6;
495 #endif
497 for (o = 0; ot[o].name; o++)
498 if (ot[o].val == opt)
500 if (buf)
502 memset(buf, 0, buf_len);
504 if (ot[o].size & OT_ADDR_LIST)
506 struct all_addr addr;
507 int addr_len = INADDRSZ;
509 #ifdef HAVE_DHCP6
510 if (prot == AF_INET6)
511 addr_len = IN6ADDRSZ;
512 #endif
513 for (buf[0]= 0, i = 0; i <= opt_len - addr_len; i += addr_len)
515 if (i != 0)
516 strncat(buf, ", ", buf_len - strlen(buf));
517 /* align */
518 memcpy(&addr, &val[i], addr_len);
519 inet_ntop(prot, &val[i], daemon->addrbuff, ADDRSTRLEN);
520 strncat(buf, daemon->addrbuff, buf_len - strlen(buf));
523 else if (ot[o].size & OT_NAME)
524 for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
526 char c = val[i];
527 if (isprint((int)c))
528 buf[j++] = c;
530 #ifdef HAVE_DHCP6
531 /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
532 else if ((ot[o].size & OT_RFC1035_NAME) && prot == AF_INET6)
534 i = 0, j = 0;
535 while (i < opt_len && val[i] != 0)
537 int k, l = i + val[i] + 1;
538 for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
540 char c = val[k];
541 if (isprint((int)c))
542 buf[j++] = c;
544 i = l;
545 if (val[i] != 0 && j < buf_len)
546 buf[j++] = '.';
549 else if ((ot[o].size & OT_CSTRING))
551 int k, len;
552 unsigned char *p;
554 i = 0, j = 0;
555 while (1)
557 p = &val[i];
558 GETSHORT(len, p);
559 for (k = 0; k < len && j < buf_len; k++)
561 char c = *p++;
562 if (isprint((int)c))
563 buf[j++] = c;
565 i += len +2;
566 if (i >= opt_len)
567 break;
569 if (j < buf_len)
570 buf[j++] = ',';
573 #endif
574 else
575 nodecode = 1;
577 break;
580 if (buf && (!ot[o].name || nodecode))
582 int trunc = 0;
583 if (opt_len > 13)
585 trunc = 1;
586 opt_len = 13;
588 print_mac(buf, val, opt_len);
589 if (trunc)
590 strncat(buf, "...", buf_len - strlen(buf));
595 return ot[o].name ? ot[o].name : "";
599 #endif
601 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
602 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
603 following sequence so that they map to themselves: it is therefore possible to call
604 unhide_metas repeatedly on string without breaking things.
605 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
606 couple of other places.
607 Note that space is included here so that
608 --dhcp-option=3, string
609 has five characters, whilst
610 --dhcp-option=3," string"
611 has six.
614 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
616 static char hide_meta(char c)
618 unsigned int i;
620 for (i = 0; i < (sizeof(meta) - 1); i++)
621 if (c == meta[i])
622 return (char)i;
624 return c;
627 static char unhide_meta(char cr)
629 unsigned int c = cr;
631 if (c < (sizeof(meta) - 1))
632 cr = meta[c];
634 return cr;
637 static void unhide_metas(char *cp)
639 if (cp)
640 for(; *cp; cp++)
641 *cp = unhide_meta(*cp);
644 static void *opt_malloc(size_t size)
646 void *ret;
648 if (mem_recover)
650 ret = whine_malloc(size);
651 if (!ret)
652 longjmp(mem_jmp, 1);
654 else
655 ret = safe_malloc(size);
657 return ret;
660 static char *opt_string_alloc(char *cp)
662 char *ret = NULL;
664 if (cp && strlen(cp) != 0)
666 ret = opt_malloc(strlen(cp)+1);
667 strcpy(ret, cp);
669 /* restore hidden metachars */
670 unhide_metas(ret);
673 return ret;
677 /* find next comma, split string with zero and eliminate spaces.
678 return start of string following comma */
680 static char *split_chr(char *s, char c)
682 char *comma, *p;
684 if (!s || !(comma = strchr(s, c)))
685 return NULL;
687 p = comma;
688 *comma = ' ';
690 for (; *comma == ' '; comma++);
692 for (; (p >= s) && *p == ' '; p--)
693 *p = 0;
695 return comma;
698 static char *split(char *s)
700 return split_chr(s, ',');
703 static char *canonicalise_opt(char *s)
705 char *ret;
706 int nomem;
708 if (!s)
709 return 0;
711 unhide_metas(s);
712 if (!(ret = canonicalise(s, &nomem)) && nomem)
714 if (mem_recover)
715 longjmp(mem_jmp, 1);
716 else
717 die(_("could not get memory"), NULL, EC_NOMEM);
720 return ret;
723 static int atoi_check(char *a, int *res)
725 char *p;
727 if (!a)
728 return 0;
730 unhide_metas(a);
732 for (p = a; *p; p++)
733 if (*p < '0' || *p > '9')
734 return 0;
736 *res = atoi(a);
737 return 1;
740 static int atoi_check16(char *a, int *res)
742 if (!(atoi_check(a, res)) ||
743 *res < 0 ||
744 *res > 0xffff)
745 return 0;
747 return 1;
750 static void add_txt(char *name, char *txt)
752 size_t len = strlen(txt);
753 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
755 r->name = opt_string_alloc(name);
756 r->next = daemon->txt;
757 daemon->txt = r;
758 r->class = C_CHAOS;
759 r->txt = opt_malloc(len+1);
760 r->len = len+1;
761 *(r->txt) = len;
762 memcpy((r->txt)+1, txt, len);
765 static void do_usage(void)
767 char buff[100];
768 int i, j;
770 struct {
771 char handle;
772 int val;
773 } tab[] = {
774 { '$', CACHESIZ },
775 { '*', EDNS_PKTSZ },
776 { '&', MAXLEASES },
777 { '!', FTABSIZ },
778 { '#', TFTP_MAX_CONNECTIONS },
779 { '\0', 0 }
782 printf(_("Usage: dnsmasq [options]\n\n"));
783 #ifndef HAVE_GETOPT_LONG
784 printf(_("Use short options only on the command line.\n"));
785 #endif
786 printf(_("Valid options are:\n"));
788 for (i = 0; usage[i].opt != 0; i++)
790 char *desc = usage[i].flagdesc;
791 char *eq = "=";
793 if (!desc || *desc == '[')
794 eq = "";
796 if (!desc)
797 desc = "";
799 for ( j = 0; opts[j].name; j++)
800 if (opts[j].val == usage[i].opt)
801 break;
802 if (usage[i].opt < 256)
803 sprintf(buff, "-%c, ", usage[i].opt);
804 else
805 sprintf(buff, " ");
807 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
808 printf("%-40.40s", buff);
810 if (usage[i].arg)
812 strcpy(buff, usage[i].arg);
813 for (j = 0; tab[j].handle; j++)
814 if (tab[j].handle == *(usage[i].arg))
815 sprintf(buff, "%d", tab[j].val);
817 printf(_(usage[i].desc), buff);
818 printf("\n");
822 #ifdef HAVE_DHCP
823 static void display_opts(void)
825 int i;
827 printf(_("Known DHCP options:\n"));
829 for (i = 0; opttab[i].name; i++)
830 if (!(opttab[i].size & OT_INTERNAL))
831 printf("%3d %s\n", opttab[i].val, opttab[i].name);
834 #ifdef HAVE_DHCP6
835 static void display_opts6(void)
837 int i;
838 printf(_("Known DHCPv6 options:\n"));
840 for (i = 0; opttab6[i].name; i++)
841 if (!(opttab6[i].size & OT_INTERNAL))
842 printf("%3d %s\n", opttab6[i].val, opttab6[i].name);
844 #endif
847 static int is_tag_prefix(char *arg)
849 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
850 return 1;
852 return 0;
855 static char *set_prefix(char *arg)
857 if (strstr(arg, "set:") == arg)
858 return arg+4;
860 return arg;
863 /* This is too insanely large to keep in-line in the switch */
864 static char *parse_dhcp_opt(char *arg, int flags)
866 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
867 char lenchar = 0, *cp;
868 int i, addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
869 char *comma = NULL, *problem = NULL;
870 struct dhcp_netid *np = NULL;
871 u16 opt_len = 0;
872 int is6 = 0;
874 new->len = 0;
875 new->flags = flags;
876 new->netid = NULL;
877 new->val = NULL;
878 new->opt = 0;
880 while (arg)
882 comma = split(arg);
884 for (cp = arg; *cp; cp++)
885 if (*cp < '0' || *cp > '9')
886 break;
888 if (!*cp)
890 new->opt = atoi(arg);
891 opt_len = 0;
892 break;
895 if (strstr(arg, "option:") == arg)
897 for (i = 0; opttab[i].name; i++)
898 if (!(opttab[i].size & OT_INTERNAL) &&
899 strcasecmp(opttab[i].name, arg+7) == 0)
901 new->opt = opttab[i].val;
902 opt_len = opttab[i].size;
903 break;
905 /* option:<optname> must follow tag and vendor string. */
906 break;
908 #ifdef HAVE_DHCP6
909 else if (strstr(arg, "option6:") == arg)
911 for (cp = arg+8; *cp; cp++)
912 if (*cp < '0' || *cp > '9')
913 break;
915 if (!*cp)
917 new->opt = atoi(arg+8);
918 opt_len = 0;
920 else
921 for (i = 0; opttab6[i].name; i++)
922 if (!(opttab6[i].size & OT_INTERNAL) &&
923 strcasecmp(opttab6[i].name, arg+8) == 0)
925 new->opt = opttab6[i].val;
926 opt_len = opttab6[i].size;
927 break;
929 /* option6:<opt>|<optname> must follow tag and vendor string. */
930 is6 = 1;
931 break;
933 #endif
934 else if (strstr(arg, "vendor:") == arg)
936 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
937 new->flags |= DHOPT_VENDOR;
939 else if (strstr(arg, "encap:") == arg)
941 new->u.encap = atoi(arg+6);
942 new->flags |= DHOPT_ENCAPSULATE;
944 else if (strstr(arg, "vi-encap:") == arg)
946 new->u.encap = atoi(arg+9);
947 new->flags |= DHOPT_RFC3925;
948 if (flags == DHOPT_MATCH)
950 new->opt = 1; /* avoid error below */
951 break;
954 else
956 new->netid = opt_malloc(sizeof (struct dhcp_netid));
957 /* allow optional "net:" or "tag:" for consistency */
958 if (is_tag_prefix(arg))
959 new->netid->net = opt_string_alloc(arg+4);
960 else
961 new->netid->net = opt_string_alloc(set_prefix(arg));
962 new->netid->next = np;
963 np = new->netid;
966 arg = comma;
969 #ifdef HAVE_DHCP6
970 if (is6)
972 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
973 problem = _("unsupported encapsulation for IPv6 option");
975 if (opt_len == 0 &&
976 !(new->flags & DHOPT_RFC3925))
977 for (i = 0; opttab6[i].name; i++)
978 if (new->opt == opttab6[i].val)
980 opt_len = opttab6[i].size;
981 if (opt_len & OT_INTERNAL)
982 opt_len = 0;
983 break;
986 else
987 #endif
988 if (opt_len == 0 &&
989 !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
990 for (i = 0; opttab[i].name; i++)
991 if (new->opt == opttab[i].val)
993 opt_len = opttab[i].size;
994 if (opt_len & OT_INTERNAL)
995 opt_len = 0;
996 break;
999 /* option may be missing with rfc3925 match */
1000 if (new->opt == 0)
1001 problem = _("bad dhcp-option");
1002 else if (comma)
1004 /* characterise the value */
1005 char c;
1006 int found_dig = 0;
1007 is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
1008 addrs = digs = 1;
1009 dots = 0;
1010 for (cp = comma; (c = *cp); cp++)
1011 if (c == ',')
1013 addrs++;
1014 is_dec = is_hex = 0;
1016 else if (c == ':')
1018 digs++;
1019 is_dec = is_addr = 0;
1021 else if (c == '/')
1023 is_addr6 = is_dec = is_hex = 0;
1024 if (cp == comma) /* leading / means a pathname */
1025 is_addr = 0;
1027 else if (c == '.')
1029 is_addr6 =is_dec = is_hex = 0;
1030 dots++;
1032 else if (c == '-')
1033 is_hex = is_addr = is_addr6 = 0;
1034 else if (c == ' ')
1035 is_dec = is_hex = 0;
1036 else if (!(c >='0' && c <= '9'))
1038 is_addr = 0;
1039 if (cp[1] == 0 && is_dec &&
1040 (c == 'b' || c == 's' || c == 'i'))
1042 lenchar = c;
1043 *cp = 0;
1045 else
1046 is_dec = 0;
1047 if (!((c >='A' && c <= 'F') ||
1048 (c >='a' && c <= 'f') ||
1049 (c == '*' && (flags & DHOPT_MATCH))))
1051 is_hex = 0;
1052 if (c != '[' && c != ']')
1053 is_addr6 = 0;
1056 else
1057 found_dig = 1;
1059 if (!found_dig)
1060 is_dec = is_addr = 0;
1062 /* We know that some options take addresses */
1063 if (opt_len & OT_ADDR_LIST)
1065 is_string = is_dec = is_hex = 0;
1067 if (!is6 && (!is_addr || dots == 0))
1068 problem = _("bad IP address");
1070 if (is6 && !is_addr6)
1071 problem = _("bad IPv6 address");
1073 /* or names */
1074 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
1075 is_addr6 = is_addr = is_dec = is_hex = 0;
1077 if (is_hex && digs > 1)
1079 new->len = digs;
1080 new->val = opt_malloc(new->len);
1081 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
1082 new->flags |= DHOPT_HEX;
1084 else if (is_dec)
1086 int i, val = atoi(comma);
1087 /* assume numeric arg is 1 byte except for
1088 options where it is known otherwise.
1089 For vendor class option, we have to hack. */
1090 if (opt_len != 0)
1091 new->len = opt_len;
1092 else if (val & 0xffff0000)
1093 new->len = 4;
1094 else if (val & 0xff00)
1095 new->len = 2;
1096 else
1097 new->len = 1;
1099 if (lenchar == 'b')
1100 new->len = 1;
1101 else if (lenchar == 's')
1102 new->len = 2;
1103 else if (lenchar == 'i')
1104 new->len = 4;
1106 new->val = opt_malloc(new->len);
1107 for (i=0; i<new->len; i++)
1108 new->val[i] = val>>((new->len - i - 1)*8);
1110 else if (is_addr && !is6)
1112 struct in_addr in;
1113 unsigned char *op;
1114 char *slash;
1115 /* max length of address/subnet descriptor is five bytes,
1116 add one for the option 120 enc byte too */
1117 new->val = op = opt_malloc((5 * addrs) + 1);
1118 new->flags |= DHOPT_ADDR;
1120 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
1121 new->opt == OPTION_SIP_SERVER)
1123 *(op++) = 1; /* RFC 3361 "enc byte" */
1124 new->flags &= ~DHOPT_ADDR;
1126 while (addrs--)
1128 cp = comma;
1129 comma = split(cp);
1130 slash = split_chr(cp, '/');
1131 in.s_addr = inet_addr(cp);
1132 if (!slash)
1134 memcpy(op, &in, INADDRSZ);
1135 op += INADDRSZ;
1137 else
1139 unsigned char *p = (unsigned char *)&in;
1140 int netsize = atoi(slash);
1141 *op++ = netsize;
1142 if (netsize > 0)
1143 *op++ = *p++;
1144 if (netsize > 8)
1145 *op++ = *p++;
1146 if (netsize > 16)
1147 *op++ = *p++;
1148 if (netsize > 24)
1149 *op++ = *p++;
1150 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
1153 new->len = op - new->val;
1155 else if (is_addr6 && is6)
1157 unsigned char *op;
1158 new->val = op = opt_malloc(16 * addrs);
1159 new->flags |= DHOPT_ADDR6;
1160 while (addrs--)
1162 cp = comma;
1163 comma = split(cp);
1165 /* check for [1234::7] */
1166 if (*cp == '[')
1167 cp++;
1168 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
1169 cp[strlen(cp)-1] = 0;
1171 if (inet_pton(AF_INET6, cp, op))
1173 op += IN6ADDRSZ;
1174 continue;
1177 problem = _("bad IPv6 address");
1179 new->len = op - new->val;
1181 else if (is_string)
1183 /* text arg */
1184 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
1185 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
1187 /* dns search, RFC 3397, or SIP, RFC 3361 */
1188 unsigned char *q, *r, *tail;
1189 unsigned char *p, *m = NULL, *newp;
1190 size_t newlen, len = 0;
1191 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
1193 arg = comma;
1194 comma = split(arg);
1196 while (arg && *arg)
1198 char *in, *dom = NULL;
1199 size_t domlen = 1;
1200 /* Allow "." as an empty domain */
1201 if (strcmp (arg, ".") != 0)
1203 if (!(dom = canonicalise_opt(arg)))
1205 problem = _("bad domain in dhcp-option");
1206 break;
1208 domlen = strlen(dom) + 2;
1211 newp = opt_malloc(len + domlen + header_size);
1212 if (m)
1214 memcpy(newp, m, header_size + len);
1215 free(m);
1217 m = newp;
1218 p = m + header_size;
1219 q = p + len;
1221 /* add string on the end in RFC1035 format */
1222 for (in = dom; in && *in;)
1224 unsigned char *cp = q++;
1225 int j;
1226 for (j = 0; *in && (*in != '.'); in++, j++)
1227 *q++ = *in;
1228 *cp = j;
1229 if (*in)
1230 in++;
1232 *q++ = 0;
1233 free(dom);
1235 /* Now tail-compress using earlier names. */
1236 newlen = q - p;
1237 for (tail = p + len; *tail; tail += (*tail) + 1)
1238 for (r = p; r - p < (int)len; r += (*r) + 1)
1239 if (strcmp((char *)r, (char *)tail) == 0)
1241 PUTSHORT((r - p) | 0xc000, tail);
1242 newlen = tail - p;
1243 goto end;
1245 end:
1246 len = newlen;
1248 arg = comma;
1249 comma = split(arg);
1252 /* RFC 3361, enc byte is zero for names */
1253 if (new->opt == OPTION_SIP_SERVER)
1254 m[0] = 0;
1255 new->len = (int) len + header_size;
1256 new->val = m;
1258 #ifdef HAVE_DHCP6
1259 else if (comma && (opt_len & OT_CSTRING))
1261 /* length fields are two bytes so need 16 bits for each string */
1262 int commas = 1;
1263 unsigned char *p, *newp;
1265 for(i = 0; comma[i]; i++)
1266 if (comma[i] == ',')
1267 commas++;
1269 newp = opt_malloc(strlen(comma)+(2*commas));
1270 p = newp;
1271 arg = comma;
1272 comma = split(arg);
1274 while (arg && *arg)
1276 u16 len = strlen(arg);
1277 PUTSHORT(len, p);
1278 memcpy(p, arg, len);
1279 p += len;
1281 arg = comma;
1282 comma = split(arg);
1285 new->val = newp;
1286 new->len = p - newp;
1288 else if (comma && (opt_len & OT_RFC1035_NAME))
1290 int commas = 1;
1291 unsigned char *p, *newp;
1293 for(i = 0; comma[i]; i++)
1294 if (comma[i] == ',')
1295 commas++;
1297 newp = opt_malloc(strlen(comma)+(2*commas));
1298 p = newp;
1299 arg = comma;
1300 comma = split(arg);
1302 while (arg && *arg)
1304 p = do_rfc1035_name(p, arg);
1305 *p++ = 0;
1307 arg = comma;
1308 comma = split(arg);
1311 new->val = newp;
1312 new->len = p - newp;
1314 #endif
1315 else
1317 new->len = strlen(comma);
1318 /* keep terminating zero on string */
1319 new->val = (unsigned char *)opt_string_alloc(comma);
1320 new->flags |= DHOPT_STRING;
1325 if (!is6 &&
1326 ((new->len > 255) ||
1327 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1328 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
1329 problem = _("dhcp-option too long");
1331 if (!problem)
1333 if (flags == DHOPT_MATCH)
1335 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1336 !new->netid ||
1337 new->netid->next)
1338 problem = _("illegal dhcp-match");
1339 else if (is6)
1341 new->next = daemon->dhcp_match6;
1342 daemon->dhcp_match6 = new;
1344 else
1346 new->next = daemon->dhcp_match;
1347 daemon->dhcp_match = new;
1350 else if (is6)
1352 new->next = daemon->dhcp_opts6;
1353 daemon->dhcp_opts6 = new;
1355 else
1357 new->next = daemon->dhcp_opts;
1358 daemon->dhcp_opts = new;
1362 return problem;
1365 #endif
1367 void set_option_bool(unsigned int opt)
1369 if (opt < 32)
1370 daemon->options |= 1u << opt;
1371 else
1372 daemon->options2 |= 1u << (opt - 32);
1375 static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
1377 int i;
1378 char *comma, *problem = NULL;;
1380 if (option == '?')
1381 return gen_prob;
1383 for (i=0; usage[i].opt != 0; i++)
1384 if (usage[i].opt == option)
1386 int rept = usage[i].rept;
1388 if (command_line)
1390 /* command line */
1391 if (rept == ARG_USED_CL)
1392 return _("illegal repeated flag");
1393 if (rept == ARG_ONE)
1394 usage[i].rept = ARG_USED_CL;
1396 else
1398 /* allow file to override command line */
1399 if (rept == ARG_USED_FILE)
1400 return _("illegal repeated keyword");
1401 if (rept == ARG_USED_CL || rept == ARG_ONE)
1402 usage[i].rept = ARG_USED_FILE;
1405 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1407 set_option_bool(rept);
1408 return NULL;
1411 break;
1414 switch (option)
1416 case 'C': /* --conf-file */
1418 char *file = opt_string_alloc(arg);
1419 if (file)
1421 one_file(file, 0);
1422 free(file);
1424 break;
1427 case '7': /* --conf-dir */
1429 DIR *dir_stream;
1430 struct dirent *ent;
1431 char *directory, *path;
1432 struct list {
1433 char *suffix;
1434 struct list *next;
1435 } *ignore_suffix = NULL, *li;
1437 comma = split(arg);
1438 if (!(directory = opt_string_alloc(arg)))
1439 break;
1441 for (arg = comma; arg; arg = comma)
1443 comma = split(arg);
1444 li = opt_malloc(sizeof(struct list));
1445 li->next = ignore_suffix;
1446 ignore_suffix = li;
1447 /* Have to copy: buffer is overwritten */
1448 li->suffix = opt_string_alloc(arg);
1451 if (!(dir_stream = opendir(directory)))
1452 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1454 while ((ent = readdir(dir_stream)))
1456 size_t len = strlen(ent->d_name);
1457 struct stat buf;
1459 /* ignore emacs backups and dotfiles */
1460 if (len == 0 ||
1461 ent->d_name[len - 1] == '~' ||
1462 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1463 ent->d_name[0] == '.')
1464 continue;
1466 for (li = ignore_suffix; li; li = li->next)
1468 /* check for proscribed suffices */
1469 size_t ls = strlen(li->suffix);
1470 if (len > ls &&
1471 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1472 break;
1474 if (li)
1475 continue;
1477 path = opt_malloc(strlen(directory) + len + 2);
1478 strcpy(path, directory);
1479 strcat(path, "/");
1480 strcat(path, ent->d_name);
1482 if (stat(path, &buf) == -1)
1483 die(_("cannot access %s: %s"), path, EC_FILE);
1484 /* only reg files allowed. */
1485 if (!S_ISREG(buf.st_mode))
1486 continue;
1488 /* files must be readable */
1489 one_file(path, 0);
1490 free(path);
1493 closedir(dir_stream);
1494 free(directory);
1495 for(; ignore_suffix; ignore_suffix = li)
1497 li = ignore_suffix->next;
1498 free(ignore_suffix->suffix);
1499 free(ignore_suffix);
1502 break;
1505 case '8': /* --log-facility */
1506 /* may be a filename */
1507 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1508 daemon->log_file = opt_string_alloc(arg);
1509 else
1511 #ifdef __ANDROID__
1512 problem = _("setting log facility is not possible under Android");
1513 #else
1514 for (i = 0; facilitynames[i].c_name; i++)
1515 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1516 break;
1518 if (facilitynames[i].c_name)
1519 daemon->log_fac = facilitynames[i].c_val;
1520 else
1521 problem = _("bad log facility");
1522 #endif
1524 break;
1526 case 'x': /* --pid-file */
1527 daemon->runfile = opt_string_alloc(arg);
1528 break;
1530 case 'r': /* --resolv-file */
1532 char *name = opt_string_alloc(arg);
1533 struct resolvc *new, *list = daemon->resolv_files;
1535 if (list && list->is_default)
1537 /* replace default resolv file - possibly with nothing */
1538 if (name)
1540 list->is_default = 0;
1541 list->name = name;
1543 else
1544 list = NULL;
1546 else if (name)
1548 new = opt_malloc(sizeof(struct resolvc));
1549 new->next = list;
1550 new->name = name;
1551 new->is_default = 0;
1552 new->mtime = 0;
1553 new->logged = 0;
1554 list = new;
1556 daemon->resolv_files = list;
1557 break;
1560 case 'm': /* --mx-host */
1562 int pref = 1;
1563 struct mx_srv_record *new;
1564 char *name, *target = NULL;
1566 if ((comma = split(arg)))
1568 char *prefstr;
1569 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1570 problem = _("bad MX preference");
1573 if (!(name = canonicalise_opt(arg)) ||
1574 (comma && !(target = canonicalise_opt(comma))))
1575 problem = _("bad MX name");
1577 new = opt_malloc(sizeof(struct mx_srv_record));
1578 new->next = daemon->mxnames;
1579 daemon->mxnames = new;
1580 new->issrv = 0;
1581 new->name = name;
1582 new->target = target; /* may be NULL */
1583 new->weight = pref;
1584 break;
1587 case 't': /* --mx-target */
1588 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1589 problem = _("bad MX target");
1590 break;
1592 #ifdef HAVE_DHCP
1593 case 'l': /* --dhcp-leasefile */
1594 daemon->lease_file = opt_string_alloc(arg);
1595 break;
1597 /* Sorry about the gross pre-processor abuse */
1598 case '6': /* --dhcp-script */
1599 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1600 # if defined(NO_FORK)
1601 problem = _("cannot run scripts under uClinux");
1602 # elif !defined(HAVE_SCRIPT)
1603 problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1604 # else
1605 if (option == LOPT_LUASCRIPT)
1606 # if !defined(HAVE_LUASCRIPT)
1607 problem = _("recompile with HAVE_LUASCRIPT defined to enable Lua scripts");
1608 # else
1609 daemon->luascript = opt_string_alloc(arg);
1610 # endif
1611 else
1612 daemon->lease_change_command = opt_string_alloc(arg);
1613 # endif
1614 break;
1615 #endif /* HAVE_DHCP */
1617 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1618 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1619 case 'H': /* --addn-hosts */
1621 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1622 static int hosts_index = 1;
1623 new->fname = opt_string_alloc(arg);
1624 new->index = hosts_index++;
1625 new->flags = 0;
1626 if (option == 'H')
1628 new->next = daemon->addn_hosts;
1629 daemon->addn_hosts = new;
1631 else if (option == LOPT_DHCP_HOST)
1633 new->next = daemon->dhcp_hosts_file;
1634 daemon->dhcp_hosts_file = new;
1636 else if (option == LOPT_DHCP_OPTS)
1638 new->next = daemon->dhcp_opts_file;
1639 daemon->dhcp_opts_file = new;
1641 break;
1644 case 's': /* --domain */
1645 if (strcmp (arg, "#") == 0)
1646 set_option_bool(OPT_RESOLV_DOMAIN);
1647 else
1649 char *d;
1650 comma = split(arg);
1651 if (!(d = canonicalise_opt(arg)))
1652 option = '?';
1653 else
1655 if (comma)
1657 struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
1658 char *netpart;
1660 unhide_metas(comma);
1661 if ((netpart = split_chr(comma, '/')))
1663 int msize;
1665 arg = split(netpart);
1666 if (!atoi_check(netpart, &msize))
1667 option = '?';
1668 else if (inet_pton(AF_INET, comma, &new->start))
1670 int mask = (1 << (32 - msize)) - 1;
1671 new->is6 = 0;
1672 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1673 new->end.s_addr = new->start.s_addr | htonl(mask);
1674 if (arg)
1676 /* generate the equivalent of
1677 local=/<domain>/
1678 local=/xxx.yyy.zzz.in-addr.arpa/ */
1680 if (strcmp(arg, "local") != 0 ||
1681 (msize != 8 && msize != 16 && msize != 24))
1682 option = '?';
1683 else
1685 struct server *serv = opt_malloc(sizeof(struct server));
1686 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1687 char *p;
1689 memset(serv, 0, sizeof(struct server));
1690 serv->domain = d;
1691 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1692 serv->next = daemon->servers;
1693 daemon->servers = serv;
1695 serv = opt_malloc(sizeof(struct server));
1696 memset(serv, 0, sizeof(struct server));
1697 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1699 if (msize == 24)
1700 p += sprintf(p, "%d.", a & 0xff);
1701 a = a >> 8;
1702 if (msize != 8)
1703 p += sprintf(p, "%d.", a & 0xff);
1704 a = a >> 8;
1705 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
1707 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1708 serv->next = daemon->servers;
1709 daemon->servers = serv;
1713 #ifdef HAVE_IPV6
1714 else if (inet_pton(AF_INET6, comma, &new->start6))
1716 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1717 u64 addrpart = addr6part(&new->start6);
1718 new->is6 = 1;
1720 /* prefix==64 overflows the mask calculation above */
1721 if (msize == 64)
1722 mask = (u64)-1LL;
1724 new->end6 = new->start6;
1725 setaddr6part(&new->start6, addrpart & ~mask);
1726 setaddr6part(&new->end6, addrpart | mask);
1728 if (msize < 64)
1729 option = '?';
1730 else if (arg)
1732 /* generate the equivalent of
1733 local=/<domain>/
1734 local=/xxx.yyy.zzz.ip6.arpa/ */
1736 if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
1737 option = '?';
1738 else
1740 struct server *serv = opt_malloc(sizeof(struct server));
1741 char *p;
1743 memset(serv, 0, sizeof(struct server));
1744 serv->domain = d;
1745 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1746 serv->next = daemon->servers;
1747 daemon->servers = serv;
1749 serv = opt_malloc(sizeof(struct server));
1750 memset(serv, 0, sizeof(struct server));
1751 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1753 for (i = msize-1; i >= 0; i -= 4)
1755 int dig = ((unsigned char *)&new->start6)[i>>3];
1756 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1758 p += sprintf(p, "ip6.arpa");
1760 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1761 serv->next = daemon->servers;
1762 daemon->servers = serv;
1766 #endif
1767 else
1768 option = '?';
1770 else
1772 arg = split(comma);
1773 if (inet_pton(AF_INET, comma, &new->start))
1775 new->is6 = 0;
1776 if (!arg)
1777 new->end.s_addr = new->start.s_addr;
1778 else if (!inet_pton(AF_INET, arg, &new->end))
1779 option = '?';
1781 #ifdef HAVE_IPV6
1782 else if (inet_pton(AF_INET6, comma, &new->start6))
1784 new->is6 = 1;
1785 if (!arg)
1786 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1787 else if (!inet_pton(AF_INET6, arg, &new->end6))
1788 option = '?';
1790 #endif
1791 else
1792 option = '?';
1795 new->domain = d;
1796 new->next = daemon->cond_domain;
1797 daemon->cond_domain = new;
1799 else
1800 daemon->domain_suffix = d;
1803 break;
1805 case 'u': /* --user */
1806 daemon->username = opt_string_alloc(arg);
1807 break;
1809 case 'g': /* --group */
1810 daemon->groupname = opt_string_alloc(arg);
1811 daemon->group_set = 1;
1812 break;
1814 #ifdef HAVE_DHCP
1815 case LOPT_SCRIPTUSR: /* --scriptuser */
1816 daemon->scriptuser = opt_string_alloc(arg);
1817 break;
1818 #endif
1820 case 'i': /* --interface */
1821 do {
1822 struct iname *new = opt_malloc(sizeof(struct iname));
1823 comma = split(arg);
1824 new->next = daemon->if_names;
1825 daemon->if_names = new;
1826 /* new->name may be NULL if someone does
1827 "interface=" to disable all interfaces except loop. */
1828 new->name = opt_string_alloc(arg);
1829 new->isloop = new->used = 0;
1830 arg = comma;
1831 } while (arg);
1832 break;
1834 case 'I': /* --except-interface */
1835 case '2': /* --no-dhcp-interface */
1836 do {
1837 struct iname *new = opt_malloc(sizeof(struct iname));
1838 comma = split(arg);
1839 new->name = opt_string_alloc(arg);
1840 if (option == 'I')
1842 new->next = daemon->if_except;
1843 daemon->if_except = new;
1845 else
1847 new->next = daemon->dhcp_except;
1848 daemon->dhcp_except = new;
1850 arg = comma;
1851 } while (arg);
1852 break;
1854 case 'B': /* --bogus-nxdomain */
1856 struct in_addr addr;
1857 unhide_metas(arg);
1858 if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1860 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1861 baddr->next = daemon->bogus_addr;
1862 daemon->bogus_addr = baddr;
1863 baddr->addr = addr;
1865 else
1866 option = '?'; /* error */
1867 break;
1870 case 'a': /* --listen-address */
1871 do {
1872 struct iname *new = opt_malloc(sizeof(struct iname));
1873 comma = split(arg);
1874 unhide_metas(arg);
1875 new->next = daemon->if_addrs;
1876 if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1878 new->addr.sa.sa_family = AF_INET;
1879 #ifdef HAVE_SOCKADDR_SA_LEN
1880 new->addr.in.sin_len = sizeof(new->addr.in);
1881 #endif
1883 #ifdef HAVE_IPV6
1884 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1886 new->addr.sa.sa_family = AF_INET6;
1887 new->addr.in6.sin6_flowinfo = 0;
1888 new->addr.in6.sin6_scope_id = 0;
1889 #ifdef HAVE_SOCKADDR_SA_LEN
1890 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1891 #endif
1893 #endif
1894 else
1896 option = '?'; /* error */
1897 break;
1900 daemon->if_addrs = new;
1901 arg = comma;
1902 } while (arg);
1903 break;
1905 case 'S': /* --server */
1906 case LOPT_LOCAL: /* --local */
1907 case 'A': /* --address */
1908 case LOPT_NO_REBIND: /* --rebind-domain-ok */
1910 struct server *serv, *newlist = NULL;
1912 unhide_metas(arg);
1914 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
1916 int rebind = !(*arg == '/');
1917 char *end = NULL;
1918 if (!rebind)
1919 arg++;
1920 while (rebind || (end = split_chr(arg, '/')))
1922 char *domain = NULL;
1923 /* elide leading dots - they are implied in the search algorithm */
1924 while (*arg == '.') arg++;
1925 /* # matches everything and becomes a zero length domain string */
1926 if (strcmp(arg, "#") == 0)
1927 domain = "";
1928 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1929 option = '?';
1930 serv = opt_malloc(sizeof(struct server));
1931 memset(serv, 0, sizeof(struct server));
1932 serv->next = newlist;
1933 newlist = serv;
1934 serv->domain = domain;
1935 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1936 arg = end;
1937 if (rebind)
1938 break;
1940 if (!newlist)
1942 option = '?';
1943 break;
1947 else
1949 newlist = opt_malloc(sizeof(struct server));
1950 memset(newlist, 0, sizeof(struct server));
1953 if (option == 'A')
1955 newlist->flags |= SERV_LITERAL_ADDRESS;
1956 if (!(newlist->flags & SERV_TYPE))
1957 option = '?';
1959 else if (option == LOPT_NO_REBIND)
1960 newlist->flags |= SERV_NO_REBIND;
1962 if (!arg || !*arg)
1964 if (!(newlist->flags & SERV_NO_REBIND))
1965 newlist->flags |= SERV_NO_ADDR; /* no server */
1966 if (newlist->flags & SERV_LITERAL_ADDRESS)
1967 option = '?';
1970 else if (strcmp(arg, "#") == 0)
1972 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
1973 if (newlist->flags & SERV_LITERAL_ADDRESS)
1974 option = '?';
1976 else
1978 int source_port = 0, serv_port = NAMESERVER_PORT;
1979 char *portno, *source;
1980 #ifdef HAVE_IPV6
1981 int scope_index = 0;
1982 char *scope_id;
1983 #endif
1985 if ((source = split_chr(arg, '@')) && /* is there a source. */
1986 (portno = split_chr(source, '#')) &&
1987 !atoi_check16(portno, &source_port))
1988 problem = _("bad port");
1990 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1991 !atoi_check16(portno, &serv_port))
1992 problem = _("bad port");
1994 #ifdef HAVE_IPV6
1995 scope_id = split_chr(arg, '%');
1996 #endif
1998 if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
2000 newlist->addr.in.sin_port = htons(serv_port);
2001 newlist->source_addr.in.sin_port = htons(source_port);
2002 newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
2003 #ifdef HAVE_SOCKADDR_SA_LEN
2004 newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
2005 #endif
2006 if (source)
2008 newlist->flags |= SERV_HAS_SOURCE;
2009 if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
2011 #if defined(SO_BINDTODEVICE)
2012 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
2013 strncpy(newlist->interface, source, IF_NAMESIZE - 1);
2014 #else
2015 problem = _("interface binding not supported");
2016 #endif
2019 else
2020 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
2022 #ifdef HAVE_IPV6
2023 else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
2025 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
2026 problem = _("bad interface name");
2028 newlist->addr.in6.sin6_port = htons(serv_port);
2029 newlist->addr.in6.sin6_scope_id = scope_index;
2030 newlist->source_addr.in6.sin6_port = htons(source_port);
2031 newlist->source_addr.in6.sin6_scope_id = 0;
2032 newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
2033 newlist->addr.in6.sin6_flowinfo = newlist->source_addr.in6.sin6_flowinfo = 0;
2034 #ifdef HAVE_SOCKADDR_SA_LEN
2035 newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
2036 #endif
2037 if (source)
2039 newlist->flags |= SERV_HAS_SOURCE;
2040 if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
2042 #if defined(SO_BINDTODEVICE)
2043 newlist->source_addr.in6.sin6_addr = in6addr_any;
2044 strncpy(newlist->interface, source, IF_NAMESIZE - 1);
2045 #else
2046 problem = _("interface binding not supported");
2047 #endif
2050 else
2051 newlist->source_addr.in6.sin6_addr = in6addr_any;
2053 #endif
2054 else
2055 option = '?'; /* error */
2058 serv = newlist;
2059 while (serv->next)
2061 serv->next->flags = serv->flags;
2062 serv->next->addr = serv->addr;
2063 serv->next->source_addr = serv->source_addr;
2064 serv = serv->next;
2066 serv->next = daemon->servers;
2067 daemon->servers = newlist;
2068 break;
2071 case 'c': /* --cache-size */
2073 int size;
2075 if (!atoi_check(arg, &size))
2076 option = '?';
2077 else
2079 /* zero is OK, and means no caching. */
2081 if (size < 0)
2082 size = 0;
2083 else if (size > 10000)
2084 size = 10000;
2086 daemon->cachesize = size;
2088 break;
2091 case 'p': /* --port */
2092 if (!atoi_check16(arg, &daemon->port))
2093 option = '?';
2094 break;
2096 case LOPT_MINPORT: /* --min-port */
2097 if (!atoi_check16(arg, &daemon->min_port))
2098 option = '?';
2099 break;
2101 case '0': /* --dns-forward-max */
2102 if (!atoi_check(arg, &daemon->ftabsize))
2103 option = '?';
2104 break;
2106 case LOPT_MAX_LOGS: /* --log-async */
2107 daemon->max_logs = LOG_MAX; /* default */
2108 if (arg && !atoi_check(arg, &daemon->max_logs))
2109 option = '?';
2110 else if (daemon->max_logs > 100)
2111 daemon->max_logs = 100;
2112 break;
2114 case 'P': /* --edns-packet-max */
2116 int i;
2117 if (!atoi_check(arg, &i))
2118 option = '?';
2119 daemon->edns_pktsz = (unsigned short)i;
2120 break;
2123 case 'Q': /* --query-port */
2124 if (!atoi_check16(arg, &daemon->query_port))
2125 option = '?';
2126 /* if explicitly set to zero, use single OS ephemeral port
2127 and disable random ports */
2128 if (daemon->query_port == 0)
2129 daemon->osport = 1;
2130 break;
2132 case 'T': /* --local-ttl */
2133 case LOPT_NEGTTL: /* --neg-ttl */
2134 case LOPT_MAXTTL: /* --max-ttl */
2136 int ttl;
2137 if (!atoi_check(arg, &ttl))
2138 option = '?';
2139 else if (option == LOPT_NEGTTL)
2140 daemon->neg_ttl = (unsigned long)ttl;
2141 else if (option == LOPT_MAXTTL)
2142 daemon->max_ttl = (unsigned long)ttl;
2143 else
2144 daemon->local_ttl = (unsigned long)ttl;
2145 break;
2148 #ifdef HAVE_DHCP
2149 case 'X': /* --dhcp-lease-max */
2150 if (!atoi_check(arg, &daemon->dhcp_max))
2151 option = '?';
2152 break;
2153 #endif
2155 #ifdef HAVE_TFTP
2156 case LOPT_TFTP: /* --enable-tftp */
2157 if (arg)
2159 struct interface_list *new = opt_malloc(sizeof(struct interface_list));
2160 new->interface = opt_string_alloc(arg);
2161 new->next = daemon->tftp_interfaces;
2162 daemon->tftp_interfaces = new;
2164 else
2165 daemon->tftp_unlimited = 1;
2166 break;
2168 case LOPT_TFTP_MAX: /* --tftp-max */
2169 if (!atoi_check(arg, &daemon->tftp_max))
2170 option = '?';
2171 break;
2173 case LOPT_PREFIX: /* --tftp-prefix */
2174 comma = split(arg);
2175 if (comma)
2177 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
2178 new->interface = opt_string_alloc(comma);
2179 new->prefix = opt_string_alloc(arg);
2180 new->next = daemon->if_prefix;
2181 daemon->if_prefix = new;
2183 else
2184 daemon->tftp_prefix = opt_string_alloc(arg);
2185 break;
2187 case LOPT_TFTPPORTS: /* --tftp-port-range */
2188 if (!(comma = split(arg)) ||
2189 !atoi_check16(arg, &daemon->start_tftp_port) ||
2190 !atoi_check16(comma, &daemon->end_tftp_port))
2191 problem = _("bad port range");
2193 if (daemon->start_tftp_port > daemon->end_tftp_port)
2195 int tmp = daemon->start_tftp_port;
2196 daemon->start_tftp_port = daemon->end_tftp_port;
2197 daemon->end_tftp_port = tmp;
2200 break;
2201 #endif
2203 case LOPT_BRIDGE: /* --bridge-interface */
2205 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
2206 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
2208 problem = _("bad bridge-interface");
2209 break;
2212 strcpy(new->iface, arg);
2213 new->alias = NULL;
2214 new->next = daemon->bridges;
2215 daemon->bridges = new;
2217 do {
2218 arg = comma;
2219 comma = split(arg);
2220 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
2222 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
2223 b->next = new->alias;
2224 new->alias = b;
2225 strcpy(b->iface, arg);
2227 } while (comma);
2229 break;
2232 #ifdef HAVE_DHCP
2233 case 'F': /* --dhcp-range */
2235 int k, leasepos = 2;
2236 char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
2237 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
2239 memset (new, 0, sizeof(*new));
2240 new->lease_time = DEFLEASE;
2242 gen_prob = _("bad dhcp-range");
2244 if (!arg)
2246 option = '?';
2247 break;
2250 while(1)
2252 for (cp = arg; *cp; cp++)
2253 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
2254 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
2255 (*cp >='0' && *cp <= '9')))
2256 break;
2258 if (*cp != ',' && (comma = split(arg)))
2260 if (strstr(arg, "interface:") == arg)
2261 new->interface = opt_string_alloc(arg+10);
2262 else if (is_tag_prefix(arg))
2264 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
2265 tt->net = opt_string_alloc(arg+4);
2266 tt->next = new->filter;
2267 new->filter = tt;
2269 else
2271 if (new->netid.net)
2272 problem = _("only one tag allowed");
2273 else if (strstr(arg, "set:") == arg)
2274 new->netid.net = opt_string_alloc(arg+4);
2275 else
2276 new->netid.net = opt_string_alloc(arg);
2278 arg = comma;
2280 else
2282 a[0] = arg;
2283 break;
2287 for (k = 1; k < 5; k++)
2288 if (!(a[k] = split(a[k-1])))
2289 break;
2291 if (k < 2)
2292 option = '?';
2293 else if (inet_pton(AF_INET, a[0], &new->start))
2295 new->next = daemon->dhcp;
2296 daemon->dhcp = new;
2297 if (strcmp(a[1], "static") == 0)
2299 new->end = new->start;
2300 new->flags |= CONTEXT_STATIC;
2302 else if (strcmp(a[1], "proxy") == 0)
2304 new->end = new->start;
2305 new->flags |= CONTEXT_PROXY;
2307 else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
2308 option = '?';
2310 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2312 struct in_addr tmp = new->start;
2313 new->start = new->end;
2314 new->end = tmp;
2317 if (option != '?' && k >= 3 && strchr(a[2], '.') &&
2318 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
2320 new->flags |= CONTEXT_NETMASK;
2321 leasepos = 3;
2322 if (!is_same_net(new->start, new->end, new->netmask))
2323 problem = _("inconsistent DHCP range");
2326 if (k >= 4 && strchr(a[3], '.') &&
2327 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
2329 new->flags |= CONTEXT_BRDCAST;
2330 leasepos = 4;
2333 #ifdef HAVE_DHCP6
2334 else if (inet_pton(AF_INET6, a[0], &new->start6))
2336 new->prefix = 64; /* default */
2338 if (strcmp(a[1], "static") == 0)
2340 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
2341 new->flags |= CONTEXT_STATIC;
2343 else if (strcmp(a[1], "ra-only") == 0)
2345 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
2346 new->flags |= CONTEXT_RA_ONLY;
2348 else if (!inet_pton(AF_INET6, a[1], &new->end6))
2349 option = '?';
2351 if (new->flags & CONTEXT_RA_ONLY)
2353 new->next = daemon->ra_contexts;
2354 daemon->ra_contexts = new;
2356 else
2358 new->next = daemon->dhcp6;
2359 daemon->dhcp6 = new;
2362 /* bare integer < 128 is prefix value */
2363 if (option != '?' && k >= 3)
2365 int pref;
2366 for (cp = a[2]; *cp; cp++)
2367 if (!(*cp >= '0' && *cp <= '9'))
2368 break;
2369 if (!*cp && (pref = atoi(a[2])) <= 128)
2371 new->prefix = pref;
2372 leasepos = 3;
2373 if (new->prefix < 64)
2374 problem = _("prefix must be at least 64");
2377 if (!problem && !is_same_net6(&new->start6, &new->end6, new->prefix))
2378 problem = _("inconsistent DHCPv6 range");
2379 else if (addr6part(&new->start6) > addr6part(&new->end6))
2381 struct in6_addr tmp = new->start6;
2382 new->start6 = new->end6;
2383 new->end6 = tmp;
2386 #endif
2388 if (k >= leasepos+1)
2390 if (strcmp(a[leasepos], "infinite") == 0)
2391 new->lease_time = 0xffffffff;
2392 else
2394 int fac = 1;
2395 if (strlen(a[leasepos]) > 0)
2397 switch (a[leasepos][strlen(a[leasepos]) - 1])
2399 case 'd':
2400 case 'D':
2401 fac *= 24;
2402 /* fall though */
2403 case 'h':
2404 case 'H':
2405 fac *= 60;
2406 /* fall through */
2407 case 'm':
2408 case 'M':
2409 fac *= 60;
2410 /* fall through */
2411 case 's':
2412 case 'S':
2413 a[leasepos][strlen(a[leasepos]) - 1] = 0;
2416 new->lease_time = atoi(a[leasepos]) * fac;
2417 /* Leases of a minute or less confuse
2418 some clients, notably Apple's */
2419 if (new->lease_time < 120)
2420 new->lease_time = 120;
2425 #ifdef HAVE_DHCP6
2426 /* lifetimes must be min 2 hrs, by RFC 2462.
2427 This gets enforced in radv.c for DHCP ranges
2428 which are legitimately less. */
2429 if ((new->flags & CONTEXT_RA_ONLY) &&
2430 new->lease_time < 7200)
2431 new->lease_time = 7200;
2432 #endif
2434 break;
2437 case LOPT_BANK:
2438 case 'G': /* --dhcp-host */
2440 int j, k = 0;
2441 char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
2442 struct dhcp_config *new;
2443 struct in_addr in;
2445 new = opt_malloc(sizeof(struct dhcp_config));
2447 new->next = daemon->dhcp_conf;
2448 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2449 new->hwaddr = NULL;
2450 new->netid = NULL;
2452 if ((a[0] = arg))
2453 for (k = 1; k < 6; k++)
2454 if (!(a[k] = split(a[k-1])))
2455 break;
2457 for (j = 0; j < k; j++)
2458 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2460 char *arg = a[j];
2462 if ((arg[0] == 'i' || arg[0] == 'I') &&
2463 (arg[1] == 'd' || arg[1] == 'D') &&
2464 arg[2] == ':')
2466 if (arg[3] == '*')
2467 new->flags |= CONFIG_NOCLID;
2468 else
2470 int len;
2471 arg += 3; /* dump id: */
2472 if (strchr(arg, ':'))
2473 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2474 else
2476 unhide_metas(arg);
2477 len = (int) strlen(arg);
2480 if (len == -1)
2481 problem = _("bad hex constant");
2482 else if ((new->clid = opt_malloc(len)))
2484 new->flags |= CONFIG_CLID;
2485 new->clid_len = len;
2486 memcpy(new->clid, arg, len);
2490 /* dhcp-host has strange backwards-compat needs. */
2491 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
2493 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2494 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2495 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2496 newlist->next = new->netid;
2497 new->netid = newlist;
2498 newlist->list = newtag;
2499 strcpy(newtag->net, arg+4);
2500 unhide_metas(newtag->net);
2502 else if (strstr(arg, "tag:") == arg)
2503 problem = _("cannot match tags in --dhcp-host");
2504 #ifdef HAVE_DHCP6
2505 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2507 arg[strlen(arg)-1] = 0;
2508 arg++;
2510 if (!inet_pton(AF_INET6, arg, &new->addr6))
2511 problem = _("bad IPv6 address");
2513 new->flags |= CONFIG_ADDR6;
2515 #endif
2516 else
2518 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
2519 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2520 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
2521 problem = _("bad hex constant");
2522 else
2525 newhw->next = new->hwaddr;
2526 new->hwaddr = newhw;
2530 else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
2532 new->addr = in;
2533 new->flags |= CONFIG_ADDR;
2535 else
2537 char *cp, *lastp = NULL, last = 0;
2538 int fac = 1;
2540 if (strlen(a[j]) > 1)
2542 lastp = a[j] + strlen(a[j]) - 1;
2543 last = *lastp;
2544 switch (last)
2546 case 'd':
2547 case 'D':
2548 fac *= 24;
2549 /* fall through */
2550 case 'h':
2551 case 'H':
2552 fac *= 60;
2553 /* fall through */
2554 case 'm':
2555 case 'M':
2556 fac *= 60;
2557 /* fall through */
2558 case 's':
2559 case 'S':
2560 *lastp = 0;
2564 for (cp = a[j]; *cp; cp++)
2565 if (!isdigit((unsigned char)*cp) && *cp != ' ')
2566 break;
2568 if (*cp)
2570 if (lastp)
2571 *lastp = last;
2572 if (strcmp(a[j], "infinite") == 0)
2574 new->lease_time = 0xffffffff;
2575 new->flags |= CONFIG_TIME;
2577 else if (strcmp(a[j], "ignore") == 0)
2578 new->flags |= CONFIG_DISABLE;
2579 else
2581 if (!(new->hostname = canonicalise_opt(a[j])) ||
2582 !legal_hostname(new->hostname))
2583 problem = _("bad DHCP host name");
2584 else
2585 new->flags |= CONFIG_NAME;
2586 new->domain = NULL;
2589 else
2591 new->lease_time = atoi(a[j]) * fac;
2592 /* Leases of a minute or less confuse
2593 some clients, notably Apple's */
2594 if (new->lease_time < 120)
2595 new->lease_time = 120;
2596 new->flags |= CONFIG_TIME;
2600 daemon->dhcp_conf = new;
2601 break;
2604 case LOPT_TAG_IF: /* --tag-if */
2606 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2608 new->tag = NULL;
2609 new->set = NULL;
2610 new->next = NULL;
2612 /* preserve order */
2613 if (!daemon->tag_if)
2614 daemon->tag_if = new;
2615 else
2617 struct tag_if *tmp;
2618 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2619 tmp->next = new;
2622 while (arg)
2624 size_t len;
2626 comma = split(arg);
2627 len = strlen(arg);
2629 if (len < 5)
2631 new->set = NULL;
2632 break;
2634 else
2636 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2637 newtag->net = opt_malloc(len - 3);
2638 strcpy(newtag->net, arg+4);
2639 unhide_metas(newtag->net);
2641 if (strstr(arg, "set:") == arg)
2643 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2644 newlist->next = new->set;
2645 new->set = newlist;
2646 newlist->list = newtag;
2648 else if (strstr(arg, "tag:") == arg)
2650 newtag->next = new->tag;
2651 new->tag = newtag;
2653 else
2655 new->set = NULL;
2656 break;
2660 arg = comma;
2663 if (!new->set)
2664 problem = _("bad tag-if");
2666 break;
2670 case 'O': /* --dhcp-option */
2671 case LOPT_FORCE: /* --dhcp-option-force */
2672 case LOPT_OPTS:
2673 case LOPT_MATCH: /* --dhcp-match */
2674 problem = parse_dhcp_opt(arg,
2675 option == LOPT_FORCE ? DHOPT_FORCE :
2676 (option == LOPT_MATCH ? DHOPT_MATCH :
2677 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2678 break;
2680 case 'M': /* --dhcp-boot */
2682 struct dhcp_netid *id = NULL;
2683 while (is_tag_prefix(arg))
2685 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2686 newid->next = id;
2687 id = newid;
2688 comma = split(arg);
2689 newid->net = opt_string_alloc(arg+4);
2690 arg = comma;
2693 if (!arg)
2694 option = '?';
2695 else
2697 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
2698 struct in_addr dhcp_next_server;
2699 comma = split(arg);
2700 dhcp_file = opt_string_alloc(arg);
2701 dhcp_next_server.s_addr = 0;
2702 if (comma)
2704 arg = comma;
2705 comma = split(arg);
2706 dhcp_sname = opt_string_alloc(arg);
2707 if (comma)
2709 unhide_metas(comma);
2710 if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) {
2713 * The user may have specified the tftp hostname here.
2714 * save it so that it can be resolved/looked up during
2715 * actual dhcp_reply().
2718 tftp_sname = opt_string_alloc(comma);
2719 dhcp_next_server.s_addr = 0;
2723 if (option != '?')
2725 struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
2726 new->file = dhcp_file;
2727 new->sname = dhcp_sname;
2728 new->tftp_sname = tftp_sname;
2729 new->next_server = dhcp_next_server;
2730 new->netid = id;
2731 new->next = daemon->boot_config;
2732 daemon->boot_config = new;
2736 break;
2739 case LOPT_PXE_PROMT: /* --pxe-prompt */
2741 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2742 int timeout;
2744 new->netid = NULL;
2745 new->opt = 10; /* PXE_MENU_PROMPT */
2747 while (is_tag_prefix(arg))
2749 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2750 comma = split(arg);
2751 nn->next = new->netid;
2752 new->netid = nn;
2753 nn->net = opt_string_alloc(arg+4);
2754 arg = comma;
2757 if (!arg)
2758 option = '?';
2759 else
2761 comma = split(arg);
2762 unhide_metas(arg);
2763 new->len = strlen(arg) + 1;
2764 new->val = opt_malloc(new->len);
2765 memcpy(new->val + 1, arg, new->len - 1);
2767 new->u.vendor_class = (unsigned char *)"PXEClient";
2768 new->flags = DHOPT_VENDOR;
2770 if (comma && atoi_check(comma, &timeout))
2771 *(new->val) = timeout;
2772 else
2773 *(new->val) = 255;
2775 new->next = daemon->dhcp_opts;
2776 daemon->dhcp_opts = new;
2777 daemon->enable_pxe = 1;
2780 break;
2783 case LOPT_PXE_SERV: /* --pxe-service */
2785 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2786 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2787 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2788 static int boottype = 32768;
2790 new->netid = NULL;
2791 new->sname = NULL;
2792 new->server.s_addr = 0;
2794 while (is_tag_prefix(arg))
2796 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2797 comma = split(arg);
2798 nn->next = new->netid;
2799 new->netid = nn;
2800 nn->net = opt_string_alloc(arg+4);
2801 arg = comma;
2804 if (arg && (comma = split(arg)))
2806 for (i = 0; CSA[i]; i++)
2807 if (strcasecmp(CSA[i], arg) == 0)
2808 break;
2810 if (CSA[i] || atoi_check(arg, &i))
2812 arg = comma;
2813 comma = split(arg);
2815 new->CSA = i;
2816 new->menu = opt_string_alloc(arg);
2818 if (!comma)
2820 new->type = 0; /* local boot */
2821 new->basename = NULL;
2823 else
2825 arg = comma;
2826 comma = split(arg);
2827 if (atoi_check(arg, &i))
2829 new->type = i;
2830 new->basename = NULL;
2832 else
2834 new->type = boottype++;
2835 new->basename = opt_string_alloc(arg);
2838 if (comma)
2840 if (!inet_pton(AF_INET, comma, &new->server))
2842 new->server.s_addr = 0;
2843 new->sname = opt_string_alloc(comma);
2849 /* Order matters */
2850 new->next = NULL;
2851 if (!daemon->pxe_services)
2852 daemon->pxe_services = new;
2853 else
2855 struct pxe_service *s;
2856 for (s = daemon->pxe_services; s->next; s = s->next);
2857 s->next = new;
2860 daemon->enable_pxe = 1;
2861 break;
2866 option = '?';
2867 break;
2870 case '4': /* --dhcp-mac */
2872 if (!(comma = split(arg)))
2873 option = '?';
2874 else
2876 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2877 new->netid.net = opt_string_alloc(set_prefix(arg));
2878 unhide_metas(comma);
2879 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2880 if (new->hwaddr_len == -1)
2881 option = '?';
2882 else
2884 new->next = daemon->dhcp_macs;
2885 daemon->dhcp_macs = new;
2889 break;
2891 case 'U': /* --dhcp-vendorclass */
2892 case 'j': /* --dhcp-userclass */
2893 case LOPT_CIRCUIT: /* --dhcp-circuitid */
2894 case LOPT_REMOTE: /* --dhcp-remoteid */
2895 case LOPT_SUBSCR: /* --dhcp-subscrid */
2897 if (!(comma = split(arg)))
2898 option = '?';
2899 else
2901 unsigned char *p;
2902 int dig = 0;
2903 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2904 new->netid.net = opt_string_alloc(set_prefix(arg));
2905 /* check for hex string - must digits may include : must not have nothing else,
2906 only allowed for agent-options. */
2908 arg = comma;
2909 if ((comma = split(arg)))
2911 if (option != 'U' || strstr(arg, "enterprise:") != arg)
2912 option = '?';
2913 else
2914 new->enterprise = atoi(arg+11);
2916 else
2917 comma = arg;
2919 for (p = (unsigned char *)comma; *p; p++)
2920 if (isxdigit(*p))
2921 dig = 1;
2922 else if (*p != ':')
2923 break;
2924 unhide_metas(comma);
2925 if (option == 'U' || option == 'j' || *p || !dig)
2927 new->len = strlen(comma);
2928 new->data = opt_malloc(new->len);
2929 memcpy(new->data, comma, new->len);
2931 else
2933 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2934 new->data = opt_malloc(new->len);
2935 memcpy(new->data, comma, new->len);
2938 switch (option)
2940 case 'j':
2941 new->match_type = MATCH_USER;
2942 break;
2943 case 'U':
2944 new->match_type = MATCH_VENDOR;
2945 break;
2946 case LOPT_CIRCUIT:
2947 new->match_type = MATCH_CIRCUIT;
2948 break;
2949 case LOPT_REMOTE:
2950 new->match_type = MATCH_REMOTE;
2951 break;
2952 case LOPT_SUBSCR:
2953 new->match_type = MATCH_SUBSCRIBER;
2954 break;
2956 new->next = daemon->dhcp_vendors;
2957 daemon->dhcp_vendors = new;
2959 break;
2962 case LOPT_ALTPORT: /* --dhcp-alternate-port */
2963 if (!arg)
2965 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2966 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2968 else
2970 comma = split(arg);
2971 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2972 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
2973 problem = _("invalid port number");
2974 if (!comma)
2975 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2977 break;
2979 case 'J': /* --dhcp-ignore */
2980 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
2981 case LOPT_BROADCAST: /* --dhcp-broadcast */
2982 case '3': /* --bootp-dynamic */
2983 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
2985 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
2986 struct dhcp_netid *list = NULL;
2987 if (option == 'J')
2989 new->next = daemon->dhcp_ignore;
2990 daemon->dhcp_ignore = new;
2992 else if (option == LOPT_BROADCAST)
2994 new->next = daemon->force_broadcast;
2995 daemon->force_broadcast = new;
2997 else if (option == '3')
2999 new->next = daemon->bootp_dynamic;
3000 daemon->bootp_dynamic = new;
3002 else if (option == LOPT_GEN_NAMES)
3004 new->next = daemon->dhcp_gen_names;
3005 daemon->dhcp_gen_names = new;
3007 else
3009 new->next = daemon->dhcp_ignore_names;
3010 daemon->dhcp_ignore_names = new;
3013 while (arg) {
3014 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
3015 comma = split(arg);
3016 member->next = list;
3017 list = member;
3018 if (is_tag_prefix(arg))
3019 member->net = opt_string_alloc(arg+4);
3020 else
3021 member->net = opt_string_alloc(arg);
3022 arg = comma;
3025 new->list = list;
3026 break;
3029 case LOPT_PROXY: /* --dhcp-proxy */
3030 daemon->override = 1;
3031 while (arg) {
3032 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
3033 comma = split(arg);
3034 if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
3035 problem = _("bad dhcp-proxy address");
3036 new->next = daemon->override_relays;
3037 daemon->override_relays = new;
3038 arg = comma;
3040 break;
3041 #endif
3043 case 'V': /* --alias */
3045 char *dash, *a[3] = { NULL, NULL, NULL };
3046 int k = 0;
3047 struct doctor *new = opt_malloc(sizeof(struct doctor));
3048 new->next = daemon->doctors;
3049 daemon->doctors = new;
3050 new->mask.s_addr = 0xffffffff;
3051 new->end.s_addr = 0;
3053 if ((a[0] = arg))
3054 for (k = 1; k < 3; k++)
3056 if (!(a[k] = split(a[k-1])))
3057 break;
3058 unhide_metas(a[k]);
3061 dash = split_chr(a[0], '-');
3063 if ((k < 2) ||
3064 ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
3065 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
3066 option = '?';
3068 if (k == 3)
3069 new->mask.s_addr = inet_addr(a[2]);
3071 if (dash &&
3072 ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
3073 !is_same_net(new->in, new->end, new->mask) ||
3074 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
3075 problem = _("invalid alias range");
3077 break;
3080 case LOPT_INTNAME: /* --interface-name */
3082 struct interface_name *new, **up;
3083 char *domain = NULL;
3085 comma = split(arg);
3087 if (!comma || !(domain = canonicalise_opt(arg)))
3088 problem = _("bad interface name");
3090 new = opt_malloc(sizeof(struct interface_name));
3091 new->next = NULL;
3092 /* Add to the end of the list, so that first name
3093 of an interface is used for PTR lookups. */
3094 for (up = &daemon->int_names; *up; up = &((*up)->next));
3095 *up = new;
3096 new->name = domain;
3097 new->intr = opt_string_alloc(comma);
3098 break;
3101 case LOPT_CNAME: /* --cname */
3103 struct cname *new;
3105 if (!(comma = split(arg)))
3106 option = '?';
3107 else
3109 char *alias = canonicalise_opt(arg);
3110 char *target = canonicalise_opt(comma);
3112 if (!alias || !target)
3113 problem = _("bad CNAME");
3114 else
3116 for (new = daemon->cnames; new; new = new->next)
3117 if (hostname_isequal(new->alias, arg))
3118 problem = _("duplicate CNAME");
3119 new = opt_malloc(sizeof(struct cname));
3120 new->next = daemon->cnames;
3121 daemon->cnames = new;
3122 new->alias = alias;
3123 new->target = target;
3126 break;
3129 case LOPT_PTR: /* --ptr-record */
3131 struct ptr_record *new;
3132 char *dom, *target = NULL;
3134 comma = split(arg);
3136 if (!(dom = canonicalise_opt(arg)) ||
3137 (comma && !(target = canonicalise_opt(comma))))
3138 problem = _("bad PTR record");
3139 else
3141 new = opt_malloc(sizeof(struct ptr_record));
3142 new->next = daemon->ptr;
3143 daemon->ptr = new;
3144 new->name = dom;
3145 new->ptr = target;
3147 break;
3150 case LOPT_NAPTR: /* --naptr-record */
3152 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3153 int k = 0;
3154 struct naptr *new;
3155 int order, pref;
3156 char *name, *replace = NULL;
3158 if ((a[0] = arg))
3159 for (k = 1; k < 7; k++)
3160 if (!(a[k] = split(a[k-1])))
3161 break;
3164 if (k < 6 ||
3165 !(name = canonicalise_opt(a[0])) ||
3166 !atoi_check16(a[1], &order) ||
3167 !atoi_check16(a[2], &pref) ||
3168 (k == 7 && !(replace = canonicalise_opt(a[6]))))
3169 problem = _("bad NAPTR record");
3170 else
3172 new = opt_malloc(sizeof(struct naptr));
3173 new->next = daemon->naptr;
3174 daemon->naptr = new;
3175 new->name = name;
3176 new->flags = opt_string_alloc(a[3]);
3177 new->services = opt_string_alloc(a[4]);
3178 new->regexp = opt_string_alloc(a[5]);
3179 new->replace = replace;
3180 new->order = order;
3181 new->pref = pref;
3183 break;
3186 case 'Y': /* --txt-record */
3188 struct txt_record *new;
3189 unsigned char *p, *cnt;
3190 size_t len;
3192 comma = split(arg);
3194 new = opt_malloc(sizeof(struct txt_record));
3195 new->next = daemon->txt;
3196 daemon->txt = new;
3197 new->class = C_IN;
3199 if (!(new->name = canonicalise_opt(arg)))
3201 problem = _("bad TXT record");
3202 break;
3205 len = comma ? strlen(comma) : 0;
3206 len += (len/255) + 1; /* room for extra counts */
3207 new->txt = p = opt_malloc(len);
3209 cnt = p++;
3210 *cnt = 0;
3212 while (comma && *comma)
3214 unsigned char c = (unsigned char)*comma++;
3216 if (c == ',' || *cnt == 255)
3218 if (c != ',')
3219 comma--;
3220 cnt = p++;
3221 *cnt = 0;
3223 else
3225 *p++ = unhide_meta(c);
3226 (*cnt)++;
3230 new->len = p - new->txt;
3232 break;
3235 case 'W': /* --srv-host */
3237 int port = 1, priority = 0, weight = 0;
3238 char *name, *target = NULL;
3239 struct mx_srv_record *new;
3241 comma = split(arg);
3243 if (!(name = canonicalise_opt(arg)))
3244 problem = _("bad SRV record");
3246 if (comma)
3248 arg = comma;
3249 comma = split(arg);
3250 if (!(target = canonicalise_opt(arg))
3251 ) problem = _("bad SRV target");
3253 if (comma)
3255 arg = comma;
3256 comma = split(arg);
3257 if (!atoi_check16(arg, &port))
3258 problem = _("invalid port number");
3260 if (comma)
3262 arg = comma;
3263 comma = split(arg);
3264 if (!atoi_check16(arg, &priority))
3265 problem = _("invalid priority");
3267 if (comma)
3269 arg = comma;
3270 comma = split(arg);
3271 if (!atoi_check16(arg, &weight))
3272 problem = _("invalid weight");
3278 new = opt_malloc(sizeof(struct mx_srv_record));
3279 new->next = daemon->mxnames;
3280 daemon->mxnames = new;
3281 new->issrv = 1;
3282 new->name = name;
3283 new->target = target;
3284 new->srvport = port;
3285 new->priority = priority;
3286 new->weight = weight;
3287 break;
3290 default:
3291 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
3295 if (problem)
3296 return problem;
3298 if (option == '?')
3299 return gen_prob;
3301 return NULL;
3304 static void read_file(char *file, FILE *f, int hard_opt)
3306 volatile int lineno = 0;
3307 char *buff = daemon->namebuff;
3309 while (fgets(buff, MAXDNAME, f))
3311 int white, i, option; ;
3312 char *errmess, *p, *arg, *start;
3313 size_t len;
3315 /* Memory allocation failure longjmps here if mem_recover == 1 */
3316 if (hard_opt)
3318 if (setjmp(mem_jmp))
3319 continue;
3320 mem_recover = 1;
3323 lineno++;
3324 errmess = NULL;
3326 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3327 metacharacters get hidden also strip comments */
3328 for (white = 1, p = buff; *p; p++)
3330 if (*p == '"')
3332 memmove(p, p+1, strlen(p+1)+1);
3334 for(; *p && *p != '"'; p++)
3336 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
3338 if (p[1] == 't')
3339 p[1] = '\t';
3340 else if (p[1] == 'n')
3341 p[1] = '\n';
3342 else if (p[1] == 'b')
3343 p[1] = '\b';
3344 else if (p[1] == 'r')
3345 p[1] = '\r';
3346 else if (p[1] == 'e') /* escape */
3347 p[1] = '\033';
3348 memmove(p, p+1, strlen(p+1)+1);
3350 *p = hide_meta(*p);
3353 if (*p == 0)
3355 errmess = _("missing \"");
3356 goto oops;
3359 memmove(p, p+1, strlen(p+1)+1);
3362 if (isspace(*p))
3364 *p = ' ';
3365 white = 1;
3367 else
3369 if (white && *p == '#')
3371 *p = 0;
3372 break;
3374 white = 0;
3379 /* strip leading spaces */
3380 for (start = buff; *start && *start == ' '; start++);
3382 /* strip trailing spaces */
3383 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3385 if (len == 0)
3386 continue;
3387 else
3388 start[len] = 0;
3390 if (hard_opt != 0)
3391 arg = start;
3392 else if ((p=strchr(start, '=')))
3394 /* allow spaces around "=" */
3395 for (arg = p+1; *arg == ' '; arg++);
3396 for (; p >= start && (*p == ' ' || *p == '='); p--)
3397 *p = 0;
3399 else
3400 arg = NULL;
3402 if (hard_opt != 0)
3403 option = hard_opt;
3404 else
3406 for (option = 0, i = 0; opts[i].name; i++)
3407 if (strcmp(opts[i].name, start) == 0)
3409 option = opts[i].val;
3410 break;
3413 if (!option)
3414 errmess = _("bad option");
3415 else if (opts[i].has_arg == 0 && arg)
3416 errmess = _("extraneous parameter");
3417 else if (opts[i].has_arg == 1 && !arg)
3418 errmess = _("missing parameter");
3421 if (!errmess)
3422 errmess = one_opt(option, arg, _("error"), 0);
3424 if (errmess)
3426 oops:
3427 sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
3428 if (hard_opt != 0)
3429 my_syslog(LOG_ERR, buff, file);
3430 else
3431 die(buff, file, EC_BADCONF);
3435 mem_recover = 0;
3436 fclose(f);
3439 static void one_file(char *file, int hard_opt)
3441 FILE *f;
3442 int nofile_ok = 0;
3443 static int read_stdin = 0;
3444 static struct fileread {
3445 dev_t dev;
3446 ino_t ino;
3447 struct fileread *next;
3448 } *filesread = NULL;
3450 if (hard_opt == '7')
3452 /* default conf-file reading */
3453 hard_opt = 0;
3454 nofile_ok = 1;
3457 if (hard_opt == 0 && strcmp(file, "-") == 0)
3459 if (read_stdin == 1)
3460 return;
3461 read_stdin = 1;
3462 file = "stdin";
3463 f = stdin;
3465 else
3467 /* ignore repeated files. */
3468 struct stat statbuf;
3470 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3472 struct fileread *r;
3474 for (r = filesread; r; r = r->next)
3475 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
3476 return;
3478 r = safe_malloc(sizeof(struct fileread));
3479 r->next = filesread;
3480 filesread = r;
3481 r->dev = statbuf.st_dev;
3482 r->ino = statbuf.st_ino;
3485 if (!(f = fopen(file, "r")))
3487 if (errno == ENOENT && nofile_ok)
3488 return; /* No conffile, all done. */
3489 else
3491 char *str = _("cannot read %s: %s");
3492 if (hard_opt != 0)
3494 my_syslog(LOG_ERR, str, file, strerror(errno));
3495 return;
3497 else
3498 die(str, file, EC_FILE);
3503 read_file(file, f, hard_opt);
3506 /* expand any name which is a directory */
3507 struct hostsfile *expand_filelist(struct hostsfile *list)
3509 int i;
3510 struct hostsfile *ah;
3512 for (i = 0, ah = list; ah; ah = ah->next)
3514 if (i <= ah->index)
3515 i = ah->index + 1;
3517 if (ah->flags & AH_DIR)
3518 ah->flags |= AH_INACTIVE;
3519 else
3520 ah->flags &= ~AH_INACTIVE;
3523 for (ah = list; ah; ah = ah->next)
3524 if (!(ah->flags & AH_INACTIVE))
3526 struct stat buf;
3527 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3529 DIR *dir_stream;
3530 struct dirent *ent;
3532 /* don't read this as a file */
3533 ah->flags |= AH_INACTIVE;
3535 if (!(dir_stream = opendir(ah->fname)))
3536 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3537 ah->fname, strerror(errno));
3538 else
3540 while ((ent = readdir(dir_stream)))
3542 size_t lendir = strlen(ah->fname);
3543 size_t lenfile = strlen(ent->d_name);
3544 struct hostsfile *ah1;
3545 char *path;
3547 /* ignore emacs backups and dotfiles */
3548 if (lenfile == 0 ||
3549 ent->d_name[lenfile - 1] == '~' ||
3550 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3551 ent->d_name[0] == '.')
3552 continue;
3554 /* see if we have an existing record.
3555 dir is ah->fname
3556 file is ent->d_name
3557 path to match is ah1->fname */
3559 for (ah1 = list; ah1; ah1 = ah1->next)
3561 if (lendir < strlen(ah1->fname) &&
3562 strstr(ah1->fname, ah->fname) == ah1->fname &&
3563 ah1->fname[lendir] == '/' &&
3564 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3566 ah1->flags &= ~AH_INACTIVE;
3567 break;
3571 /* make new record */
3572 if (!ah1)
3574 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3575 continue;
3577 if (!(path = whine_malloc(lendir + lenfile + 2)))
3579 free(ah1);
3580 continue;
3583 strcpy(path, ah->fname);
3584 strcat(path, "/");
3585 strcat(path, ent->d_name);
3586 ah1->fname = path;
3587 ah1->index = i++;
3588 ah1->flags = AH_DIR;
3589 ah1->next = list;
3590 list = ah1;
3593 /* inactivate record if not regular file */
3594 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3595 ah1->flags |= AH_INACTIVE;
3598 closedir(dir_stream);
3603 return list;
3607 #ifdef HAVE_DHCP
3608 void reread_dhcp(void)
3610 struct hostsfile *hf;
3612 if (daemon->dhcp_hosts_file)
3614 struct dhcp_config *configs, *cp, **up;
3616 /* remove existing... */
3617 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3619 cp = configs->next;
3621 if (configs->flags & CONFIG_BANK)
3623 struct hwaddr_config *mac, *tmp;
3624 struct dhcp_netid_list *list, *tmplist;
3626 for (mac = configs->hwaddr; mac; mac = tmp)
3628 tmp = mac->next;
3629 free(mac);
3632 if (configs->flags & CONFIG_CLID)
3633 free(configs->clid);
3635 for (list = configs->netid; list; list = tmplist)
3637 free(list->list);
3638 tmplist = list->next;
3639 free(list);
3642 if (configs->flags & CONFIG_NAME)
3643 free(configs->hostname);
3645 *up = configs->next;
3646 free(configs);
3648 else
3649 up = &configs->next;
3652 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3653 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3654 if (!(hf->flags & AH_INACTIVE))
3656 one_file(hf->fname, LOPT_BANK);
3657 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3661 if (daemon->dhcp_opts_file)
3663 struct dhcp_opt *opts, *cp, **up;
3664 struct dhcp_netid *id, *next;
3666 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3668 cp = opts->next;
3670 if (opts->flags & DHOPT_BANK)
3672 if ((opts->flags & DHOPT_VENDOR))
3673 free(opts->u.vendor_class);
3674 free(opts->val);
3675 for (id = opts->netid; id; id = next)
3677 next = id->next;
3678 free(id->net);
3679 free(id);
3681 *up = opts->next;
3682 free(opts);
3684 else
3685 up = &opts->next;
3688 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3689 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3690 if (!(hf->flags & AH_INACTIVE))
3692 one_file(hf->fname, LOPT_OPTS);
3693 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
3697 #endif
3699 void read_opts(int argc, char **argv, char *compile_opts)
3701 char *buff = opt_malloc(MAXDNAME);
3702 int option, conffile_opt = '7', testmode = 0;
3703 char *errmess, *arg, *conffile = CONFFILE;
3705 opterr = 0;
3707 daemon = opt_malloc(sizeof(struct daemon));
3708 memset(daemon, 0, sizeof(struct daemon));
3709 daemon->namebuff = buff;
3711 /* Set defaults - everything else is zero or NULL */
3712 daemon->cachesize = CACHESIZ;
3713 daemon->ftabsize = FTABSIZ;
3714 daemon->port = NAMESERVER_PORT;
3715 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3716 daemon->dhcp_server_port = DHCP_SERVER_PORT;
3717 daemon->default_resolv.is_default = 1;
3718 daemon->default_resolv.name = RESOLVFILE;
3719 daemon->resolv_files = &daemon->default_resolv;
3720 daemon->username = CHUSER;
3721 daemon->runfile = RUNFILE;
3722 daemon->dhcp_max = MAXLEASES;
3723 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
3724 daemon->edns_pktsz = EDNS_PKTSZ;
3725 daemon->log_fac = -1;
3726 add_txt("version.bind", "dnsmasq-" VERSION );
3727 add_txt("authors.bind", "Simon Kelley");
3728 add_txt("copyright.bind", COPYRIGHT);
3730 while (1)
3732 #ifdef HAVE_GETOPT_LONG
3733 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
3734 #else
3735 option = getopt(argc, argv, OPTSTRING);
3736 #endif
3738 if (option == -1)
3740 for (; optind < argc; optind++)
3742 unsigned char *c = (unsigned char *)argv[optind];
3743 for (; *c != 0; c++)
3744 if (!isspace(*c))
3745 die(_("junk found in command line"), NULL, EC_BADCONF);
3747 break;
3750 /* Copy optarg so that argv doesn't get changed */
3751 if (optarg)
3753 strncpy(buff, optarg, MAXDNAME);
3754 buff[MAXDNAME-1] = 0;
3755 arg = buff;
3757 else
3758 arg = NULL;
3760 /* command-line only stuff */
3761 if (option == LOPT_TEST)
3762 testmode = 1;
3763 else if (option == 'w')
3765 #ifdef HAVE_DHCP
3766 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
3767 display_opts();
3768 #ifdef HAVE_DHCP6
3769 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
3770 display_opts6();
3771 #endif
3772 else
3773 #endif
3774 do_usage();
3776 exit(0);
3778 else if (option == 'v')
3780 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
3781 printf(_("Compile time options: %s\n\n"), compile_opts);
3782 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
3783 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
3784 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
3785 exit(0);
3787 else if (option == 'C')
3789 conffile_opt = 0; /* file must exist */
3790 conffile = opt_string_alloc(arg);
3792 else
3794 #ifdef HAVE_GETOPT_LONG
3795 errmess = one_opt(option, arg, _("try --help"), 1);
3796 #else
3797 errmess = one_opt(option, arg, _("try -w"), 1);
3798 #endif
3799 if (errmess)
3800 die(_("bad command line options: %s"), errmess, EC_BADCONF);
3804 if (conffile)
3805 one_file(conffile, conffile_opt);
3807 /* port might not be known when the address is parsed - fill in here */
3808 if (daemon->servers)
3810 struct server *tmp;
3811 for (tmp = daemon->servers; tmp; tmp = tmp->next)
3812 if (!(tmp->flags & SERV_HAS_SOURCE))
3814 if (tmp->source_addr.sa.sa_family == AF_INET)
3815 tmp->source_addr.in.sin_port = htons(daemon->query_port);
3816 #ifdef HAVE_IPV6
3817 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3818 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
3819 #endif
3823 if (daemon->if_addrs)
3825 struct iname *tmp;
3826 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
3827 if (tmp->addr.sa.sa_family == AF_INET)
3828 tmp->addr.in.sin_port = htons(daemon->port);
3829 #ifdef HAVE_IPV6
3830 else if (tmp->addr.sa.sa_family == AF_INET6)
3831 tmp->addr.in6.sin6_port = htons(daemon->port);
3832 #endif /* IPv6 */
3835 /* only one of these need be specified: the other defaults to the host-name */
3836 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
3838 struct mx_srv_record *mx;
3840 if (gethostname(buff, MAXDNAME) == -1)
3841 die(_("cannot get host-name: %s"), NULL, EC_MISC);
3843 for (mx = daemon->mxnames; mx; mx = mx->next)
3844 if (!mx->issrv && hostname_isequal(mx->name, buff))
3845 break;
3847 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
3849 mx = opt_malloc(sizeof(struct mx_srv_record));
3850 mx->next = daemon->mxnames;
3851 mx->issrv = 0;
3852 mx->target = NULL;
3853 mx->name = opt_string_alloc(buff);
3854 daemon->mxnames = mx;
3857 if (!daemon->mxtarget)
3858 daemon->mxtarget = opt_string_alloc(buff);
3860 for (mx = daemon->mxnames; mx; mx = mx->next)
3861 if (!mx->issrv && !mx->target)
3862 mx->target = daemon->mxtarget;
3865 if (!option_bool(OPT_NO_RESOLV) &&
3866 daemon->resolv_files &&
3867 daemon->resolv_files->next &&
3868 option_bool(OPT_NO_POLL))
3869 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
3871 if (option_bool(OPT_RESOLV_DOMAIN))
3873 char *line;
3874 FILE *f;
3876 if (option_bool(OPT_NO_RESOLV) ||
3877 !daemon->resolv_files ||
3878 (daemon->resolv_files)->next)
3879 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
3881 if (!(f = fopen((daemon->resolv_files)->name, "r")))
3882 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
3884 while ((line = fgets(buff, MAXDNAME, f)))
3886 char *token = strtok(line, " \t\n\r");
3888 if (!token || strcmp(token, "search") != 0)
3889 continue;
3891 if ((token = strtok(NULL, " \t\n\r")) &&
3892 (daemon->domain_suffix = canonicalise_opt(token)))
3893 break;
3896 fclose(f);
3898 if (!daemon->domain_suffix)
3899 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
3902 if (daemon->domain_suffix)
3904 /* add domain for any srv record without one. */
3905 struct mx_srv_record *srv;
3907 for (srv = daemon->mxnames; srv; srv = srv->next)
3908 if (srv->issrv &&
3909 strchr(srv->name, '.') &&
3910 strchr(srv->name, '.') == strrchr(srv->name, '.'))
3912 strcpy(buff, srv->name);
3913 strcat(buff, ".");
3914 strcat(buff, daemon->domain_suffix);
3915 free(srv->name);
3916 srv->name = opt_string_alloc(buff);
3919 else if (option_bool(OPT_DHCP_FQDN))
3920 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
3922 if (testmode)
3924 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
3925 exit(0);