Tomato 1.28
[tomato.git] / release / src / router / dnsmasq / src / option.c
blobec16b4ba705b6bd763996e840dac14b39c962977
1 /* dnsmasq is Copyright (c) 2000-2010 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 nest, 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
112 #ifdef HAVE_GETOPT_LONG
113 static const struct option opts[] =
114 #else
115 static const struct myoption opts[] =
116 #endif
118 { "version", 0, 0, 'v' },
119 { "no-hosts", 0, 0, 'h' },
120 { "no-poll", 0, 0, 'n' },
121 { "help", 0, 0, 'w' },
122 { "no-daemon", 0, 0, 'd' },
123 { "log-queries", 0, 0, 'q' },
124 { "user", 2, 0, 'u' },
125 { "group", 2, 0, 'g' },
126 { "resolv-file", 2, 0, 'r' },
127 { "mx-host", 1, 0, 'm' },
128 { "mx-target", 1, 0, 't' },
129 { "cache-size", 2, 0, 'c' },
130 { "port", 1, 0, 'p' },
131 { "dhcp-leasefile", 2, 0, 'l' },
132 { "dhcp-lease", 1, 0, 'l' },
133 { "dhcp-host", 1, 0, 'G' },
134 { "dhcp-range", 1, 0, 'F' },
135 { "dhcp-option", 1, 0, 'O' },
136 { "dhcp-boot", 1, 0, 'M' },
137 { "domain", 1, 0, 's' },
138 { "domain-suffix", 1, 0, 's' },
139 { "interface", 1, 0, 'i' },
140 { "listen-address", 1, 0, 'a' },
141 { "bogus-priv", 0, 0, 'b' },
142 { "bogus-nxdomain", 1, 0, 'B' },
143 { "selfmx", 0, 0, 'e' },
144 { "filterwin2k", 0, 0, 'f' },
145 { "pid-file", 2, 0, 'x' },
146 { "strict-order", 0, 0, 'o' },
147 { "server", 1, 0, 'S' },
148 { "local", 1, 0, LOPT_LOCAL },
149 { "address", 1, 0, 'A' },
150 { "conf-file", 2, 0, 'C' },
151 { "no-resolv", 0, 0, 'R' },
152 { "expand-hosts", 0, 0, 'E' },
153 { "localmx", 0, 0, 'L' },
154 { "local-ttl", 1, 0, 'T' },
155 { "no-negcache", 0, 0, 'N' },
156 { "addn-hosts", 1, 0, 'H' },
157 { "query-port", 1, 0, 'Q' },
158 { "except-interface", 1, 0, 'I' },
159 { "no-dhcp-interface", 1, 0, '2' },
160 { "domain-needed", 0, 0, 'D' },
161 { "dhcp-lease-max", 1, 0, 'X' },
162 { "bind-interfaces", 0, 0, 'z' },
163 { "read-ethers", 0, 0, 'Z' },
164 { "alias", 1, 0, 'V' },
165 { "dhcp-vendorclass", 1, 0, 'U' },
166 { "dhcp-userclass", 1, 0, 'j' },
167 { "dhcp-ignore", 1, 0, 'J' },
168 { "edns-packet-max", 1, 0, 'P' },
169 { "keep-in-foreground", 0, 0, 'k' },
170 { "dhcp-authoritative", 0, 0, 'K' },
171 { "srv-host", 1, 0, 'W' },
172 { "localise-queries", 0, 0, 'y' },
173 { "txt-record", 1, 0, 'Y' },
174 { "enable-dbus", 0, 0, '1' },
175 { "bootp-dynamic", 2, 0, '3' },
176 { "dhcp-mac", 1, 0, '4' },
177 { "no-ping", 0, 0, '5' },
178 { "dhcp-script", 1, 0, '6' },
179 { "conf-dir", 1, 0, '7' },
180 { "log-facility", 1, 0 ,'8' },
181 { "leasefile-ro", 0, 0, '9' },
182 { "dns-forward-max", 1, 0, '0' },
183 { "clear-on-reload", 0, 0, LOPT_RELOAD },
184 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
185 { "enable-tftp", 2, 0, LOPT_TFTP },
186 { "tftp-secure", 0, 0, LOPT_SECURE },
187 { "tftp-unique-root", 0, 0, LOPT_APREF },
188 { "tftp-root", 1, 0, LOPT_PREFIX },
189 { "tftp-max", 1, 0, LOPT_TFTP_MAX },
190 { "ptr-record", 1, 0, LOPT_PTR },
191 { "naptr-record", 1, 0, LOPT_NAPTR },
192 { "bridge-interface", 1, 0 , LOPT_BRIDGE },
193 { "dhcp-option-force", 1, 0, LOPT_FORCE },
194 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
195 { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
196 { "log-async", 2, 0, LOPT_MAX_LOGS },
197 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
198 { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
199 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
200 { "interface-name", 1, 0, LOPT_INTNAME },
201 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
202 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
203 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
204 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
205 { "stop-dns-rebind", 0, 0, LOPT_REBIND },
206 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
207 { "all-servers", 0, 0, LOPT_NOLAST },
208 { "dhcp-match", 1, 0, LOPT_MATCH },
209 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
210 { "neg-ttl", 1, 0, LOPT_NEGTTL },
211 { "max-ttl", 1, 0, LOPT_MAXTTL },
212 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
213 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
214 { "min-port", 1, 0, LOPT_MINPORT },
215 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
216 { "cname", 1, 0, LOPT_CNAME },
217 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
218 { "pxe-service", 1, 0, LOPT_PXE_SERV },
219 { "test", 0, 0, LOPT_TEST },
220 { "tag-if", 1, 0, LOPT_TAG_IF },
221 { "dhcp-proxy", 2, 0, LOPT_PROXY },
222 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
223 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
224 { NULL, 0, 0, 0 }
227 /* These must have more the one '1' bit */
228 #define ARG_DUP 3
229 #define ARG_ONE 5
230 #define ARG_USED_CL 7
231 #define ARG_USED_FILE 9
233 static struct {
234 int opt;
235 unsigned int rept;
236 char * const flagdesc;
237 char * const desc;
238 char * const arg;
239 } usage[] = {
240 { 'a', ARG_DUP, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL },
241 { 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
242 { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
243 { 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
244 { 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
245 { 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
246 { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
247 { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
248 { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
249 { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
250 { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
251 { 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
252 { 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
253 { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
254 { LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file."), NULL },
255 { LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file."), NULL },
256 { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
257 { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
258 { 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
259 { 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
260 { 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
261 { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
262 { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
263 { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
264 { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
265 { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
266 { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
267 { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
268 { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
269 { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
270 { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
271 { 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
272 { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
273 { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
274 { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
275 { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
276 { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
277 { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
278 { 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
279 { 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
280 { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
281 { 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
282 { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
283 { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
284 { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
285 { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
286 { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
287 { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
288 { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
289 { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
290 { LOPT_MAXTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
291 { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
292 { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
293 { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
294 { 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
295 { 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
296 { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
297 { 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
298 { 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
299 { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
300 { 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
301 { LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL },
302 { LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
303 { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
304 { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
305 { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
306 { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
307 { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
308 { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
309 { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
310 { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
311 { '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
312 { '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
313 { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
314 { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
315 { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
316 { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
317 { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
318 { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
319 { LOPT_TFTP, ARG_DUP, "[=<interface>]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
320 { LOPT_PREFIX, ARG_ONE, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
321 { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
322 { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
323 { LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
324 { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
325 { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
326 { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
327 { LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
328 { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
329 { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
330 { LOPT_NO_REBIND, ARG_DUP, "/domain/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
331 { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
332 { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
333 { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
334 { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
335 { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
336 { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
337 { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
338 { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
339 { LOPT_PROXY, ARG_DUP, "[=<ip_address>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
340 { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
341 { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
342 { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
343 { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
344 { 0, 0, NULL, NULL, NULL }
347 #ifdef HAVE_DHCP
348 /* makes options which take a list of addresses */
349 #define OT_ADDR_LIST 0x80
350 /* DHCP-internal options, for logging. not valid in config file */
351 #define OT_INTERNAL 0x40
352 #define OT_NAME 0x20
354 static const struct {
355 char *name;
356 unsigned char val, size;
357 } opttab[] = {
358 { "netmask", 1, OT_ADDR_LIST },
359 { "time-offset", 2, 4 },
360 { "router", 3, OT_ADDR_LIST },
361 { "dns-server", 6, OT_ADDR_LIST },
362 { "log-server", 7, OT_ADDR_LIST },
363 { "lpr-server", 9, OT_ADDR_LIST },
364 { "hostname", 12, OT_INTERNAL | OT_NAME },
365 { "boot-file-size", 13, 2 },
366 { "domain-name", 15, OT_NAME },
367 { "swap-server", 16, OT_ADDR_LIST },
368 { "root-path", 17, 0 },
369 { "extension-path", 18, 0 },
370 { "ip-forward-enable", 19, 1 },
371 { "non-local-source-routing", 20, 1 },
372 { "policy-filter", 21, OT_ADDR_LIST },
373 { "max-datagram-reassembly", 22, 2 },
374 { "default-ttl", 23, 1 },
375 { "mtu", 26, 2 },
376 { "all-subnets-local", 27, 1 },
377 { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
378 { "router-discovery", 31, 1 },
379 { "router-solicitation", 32, OT_ADDR_LIST },
380 { "static-route", 33, OT_ADDR_LIST },
381 { "trailer-encapsulation", 34, 1 },
382 { "arp-timeout", 35, 4 },
383 { "ethernet-encap", 36, 1 },
384 { "tcp-ttl", 37, 1 },
385 { "tcp-keepalive", 38, 4 },
386 { "nis-domain", 40, 0 },
387 { "nis-server", 41, OT_ADDR_LIST },
388 { "ntp-server", 42, OT_ADDR_LIST },
389 { "vendor-encap", 43, OT_INTERNAL },
390 { "netbios-ns", 44, OT_ADDR_LIST },
391 { "netbios-dd", 45, OT_ADDR_LIST },
392 { "netbios-nodetype", 46, 1 },
393 { "netbios-scope", 47, 0 },
394 { "x-windows-fs", 48, OT_ADDR_LIST },
395 { "x-windows-dm", 49, OT_ADDR_LIST },
396 { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
397 { "lease-time", 51, OT_INTERNAL },
398 { "option-overload", 52, OT_INTERNAL },
399 { "message-type", 53, OT_INTERNAL, },
400 { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
401 { "parameter-request", 55, OT_INTERNAL },
402 { "message", 56, OT_INTERNAL },
403 { "max-message-size", 57, OT_INTERNAL },
404 { "T1", 58, OT_INTERNAL },
405 { "T2", 59, OT_INTERNAL },
406 { "vendor-class", 60, 0 },
407 { "client-id", 61,OT_INTERNAL },
408 { "nis+-domain", 64, 0 },
409 { "nis+-server", 65, OT_ADDR_LIST },
410 { "tftp-server", 66, 0 },
411 { "bootfile-name", 67, 0 },
412 { "mobile-ip-home", 68, OT_ADDR_LIST },
413 { "smtp-server", 69, OT_ADDR_LIST },
414 { "pop3-server", 70, OT_ADDR_LIST },
415 { "nntp-server", 71, OT_ADDR_LIST },
416 { "irc-server", 74, OT_ADDR_LIST },
417 { "user-class", 77, 0 },
418 { "FQDN", 81, OT_INTERNAL },
419 { "agent-id", 82, OT_INTERNAL },
420 { "client-arch", 93, 2 },
421 { "client-interface-id", 94, 0 },
422 { "client-machine-id", 97, 0 },
423 { "subnet-select", 118, OT_INTERNAL },
424 { "domain-search", 119, 0 },
425 { "sip-server", 120, 0 },
426 { "classless-static-route", 121, 0 },
427 { "vendor-id-encap", 125, 0 },
428 { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
429 { NULL, 0, 0 }
432 char *option_string(unsigned char opt, int *is_ip, int *is_name)
434 int i;
436 for (i = 0; opttab[i].name; i++)
437 if (opttab[i].val == opt)
439 if (is_ip)
440 *is_ip = !!(opttab[i].size & OT_ADDR_LIST);
441 if (is_name)
442 *is_name = !!(opttab[i].size & OT_NAME);
443 return opttab[i].name;
446 return NULL;
449 #endif
451 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
452 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
453 following sequence so that they map to themselves: it is therefore possible to call
454 unhide_metas repeatedly on string without breaking things.
455 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
456 couple of other places.
457 Note that space is included here so that
458 --dhcp-option=3, string
459 has five characters, whilst
460 --dhcp-option=3," string"
461 has six.
464 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
466 static char hide_meta(char c)
468 unsigned int i;
470 for (i = 0; i < (sizeof(meta) - 1); i++)
471 if (c == meta[i])
472 return (char)i;
474 return c;
477 static char unhide_meta(char cr)
479 unsigned int c = cr;
481 if (c < (sizeof(meta) - 1))
482 cr = meta[c];
484 return cr;
487 static void unhide_metas(char *cp)
489 if (cp)
490 for(; *cp; cp++)
491 *cp = unhide_meta(*cp);
494 static void *opt_malloc(size_t size)
496 void *ret;
498 if (mem_recover)
500 ret = whine_malloc(size);
501 if (!ret)
502 longjmp(mem_jmp, 1);
504 else
505 ret = safe_malloc(size);
507 return ret;
510 static char *opt_string_alloc(char *cp)
512 char *ret = NULL;
514 if (cp && strlen(cp) != 0)
516 ret = opt_malloc(strlen(cp)+1);
517 strcpy(ret, cp);
519 /* restore hidden metachars */
520 unhide_metas(ret);
523 return ret;
527 /* find next comma, split string with zero and eliminate spaces.
528 return start of string following comma */
530 static char *split_chr(char *s, char c)
532 char *comma, *p;
534 if (!s || !(comma = strchr(s, c)))
535 return NULL;
537 p = comma;
538 *comma = ' ';
540 for (; *comma == ' '; comma++);
542 for (; (p >= s) && *p == ' '; p--)
543 *p = 0;
545 return comma;
548 static char *split(char *s)
550 return split_chr(s, ',');
553 static char *canonicalise_opt(char *s)
555 char *ret;
556 int nomem;
558 if (!s)
559 return 0;
561 unhide_metas(s);
562 if (!(ret = canonicalise(s, &nomem)) && nomem)
564 if (mem_recover)
565 longjmp(mem_jmp, 1);
566 else
567 die(_("could not get memory"), NULL, EC_NOMEM);
570 return ret;
573 static int atoi_check(char *a, int *res)
575 char *p;
577 if (!a)
578 return 0;
580 unhide_metas(a);
582 for (p = a; *p; p++)
583 if (*p < '0' || *p > '9')
584 return 0;
586 *res = atoi(a);
587 return 1;
590 static int atoi_check16(char *a, int *res)
592 if (!(atoi_check(a, res)) ||
593 *res < 0 ||
594 *res > 0xffff)
595 return 0;
597 return 1;
600 static void add_txt(char *name, char *txt)
602 size_t len = strlen(txt);
603 struct txt_record *r = opt_malloc(sizeof(struct txt_record));
605 r->name = opt_string_alloc(name);
606 r->next = daemon->txt;
607 daemon->txt = r;
608 r->class = C_CHAOS;
609 r->txt = opt_malloc(len+1);
610 r->len = len+1;
611 *(r->txt) = len;
612 memcpy((r->txt)+1, txt, len);
615 static void do_usage(void)
617 char buff[100];
618 int i, j;
620 struct {
621 char handle;
622 int val;
623 } tab[] = {
624 { '$', CACHESIZ },
625 { '*', EDNS_PKTSZ },
626 { '&', MAXLEASES },
627 { '!', FTABSIZ },
628 { '#', TFTP_MAX_CONNECTIONS },
629 { '\0', 0 }
632 printf(_("Usage: dnsmasq [options]\n\n"));
633 #ifndef HAVE_GETOPT_LONG
634 printf(_("Use short options only on the command line.\n"));
635 #endif
636 printf(_("Valid options are:\n"));
638 for (i = 0; usage[i].opt != 0; i++)
640 char *desc = usage[i].flagdesc;
641 char *eq = "=";
643 if (!desc || *desc == '[')
644 eq = "";
646 if (!desc)
647 desc = "";
649 for ( j = 0; opts[j].name; j++)
650 if (opts[j].val == usage[i].opt)
651 break;
652 if (usage[i].opt < 256)
653 sprintf(buff, "-%c, ", usage[i].opt);
654 else
655 sprintf(buff, " ");
657 sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
658 printf("%-40.40s", buff);
660 if (usage[i].arg)
662 strcpy(buff, usage[i].arg);
663 for (j = 0; tab[j].handle; j++)
664 if (tab[j].handle == *(usage[i].arg))
665 sprintf(buff, "%d", tab[j].val);
667 printf(_(usage[i].desc), buff);
668 printf("\n");
672 #ifdef HAVE_DHCP
673 static void display_opts(void)
675 int i;
677 printf(_("Known DHCP options:\n"));
679 for (i = 0; opttab[i].name; i++)
680 if (!(opttab[i].size & OT_INTERNAL))
681 printf("%3d %s\n", opttab[i].val, opttab[i].name);
684 static int is_tag_prefix(char *arg)
686 if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
687 return 1;
689 return 0;
692 static char *set_prefix(char *arg)
694 if (strstr(arg, "set:") == arg)
695 return arg+4;
697 return arg;
700 /* This is too insanely large to keep in-line in the switch */
701 static char *parse_dhcp_opt(char *arg, int flags)
703 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
704 char lenchar = 0, *cp;
705 int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
706 char *comma = NULL, *problem = NULL;
707 struct dhcp_netid *np = NULL;
708 unsigned char opt_len = 0;
710 new->len = 0;
711 new->flags = flags;
712 new->netid = NULL;
713 new->val = NULL;
714 new->opt = 0;
716 while (arg)
718 comma = split(arg);
720 for (cp = arg; *cp; cp++)
721 if (*cp < '0' || *cp > '9')
722 break;
724 if (!*cp)
726 new->opt = atoi(arg);
727 opt_len = 0;
728 break;
731 if (strstr(arg, "option:") == arg)
733 for (i = 0; opttab[i].name; i++)
734 if (!(opttab[i].size & OT_INTERNAL) &&
735 strcasecmp(opttab[i].name, arg+7) == 0)
737 new->opt = opttab[i].val;
738 opt_len = opttab[i].size;
739 break;
741 /* option:<optname> must follow tag and vendor string. */
742 break;
744 else if (strstr(arg, "vendor:") == arg)
746 new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
747 new->flags |= DHOPT_VENDOR;
749 else if (strstr(arg, "encap:") == arg)
751 new->u.encap = atoi(arg+6);
752 new->flags |= DHOPT_ENCAPSULATE;
754 else if (strstr(arg, "vi-encap:") == arg)
756 new->u.encap = atoi(arg+9);
757 new->flags |= DHOPT_RFC3925;
758 if (flags == DHOPT_MATCH)
760 new->opt = 1; /* avoid error below */
761 break;
764 else
766 new->netid = opt_malloc(sizeof (struct dhcp_netid));
767 /* allow optional "net:" or "tag:" for consistency */
768 if (is_tag_prefix(arg))
769 new->netid->net = opt_string_alloc(arg+4);
770 else
771 new->netid->net = opt_string_alloc(set_prefix(arg));
772 new->netid->next = np;
773 np = new->netid;
776 arg = comma;
779 /* option may be missing with rfc3925 match */
780 if (new->opt == 0)
781 problem = _("bad dhcp-option");
782 else if (comma)
784 /* characterise the value */
785 char c;
786 is_addr = is_hex = is_dec = is_string = 1;
787 addrs = digs = 1;
788 dots = 0;
789 for (cp = comma; (c = *cp); cp++)
790 if (c == ',')
792 addrs++;
793 is_dec = is_hex = 0;
795 else if (c == ':')
797 digs++;
798 is_dec = is_addr = 0;
800 else if (c == '/')
802 is_dec = is_hex = 0;
803 if (cp == comma) /* leading / means a pathname */
804 is_addr = 0;
806 else if (c == '.')
808 is_dec = is_hex = 0;
809 dots++;
811 else if (c == '-')
812 is_hex = is_addr = 0;
813 else if (c == ' ')
814 is_dec = is_hex = 0;
815 else if (!(c >='0' && c <= '9'))
817 is_addr = 0;
818 if (cp[1] == 0 && is_dec &&
819 (c == 'b' || c == 's' || c == 'i'))
821 lenchar = c;
822 *cp = 0;
824 else
825 is_dec = 0;
826 if (!((c >='A' && c <= 'F') ||
827 (c >='a' && c <= 'f') ||
828 (c == '*' && (flags & DHOPT_MATCH))))
829 is_hex = 0;
832 /* We know that some options take addresses */
834 if (opt_len & OT_ADDR_LIST)
836 is_string = is_dec = is_hex = 0;
837 if (!is_addr || dots == 0)
838 problem = _("bad IP address");
841 if (is_hex && digs > 1)
843 new->len = digs;
844 new->val = opt_malloc(new->len);
845 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
846 new->flags |= DHOPT_HEX;
848 else if (is_dec)
850 int i, val = atoi(comma);
851 /* assume numeric arg is 1 byte except for
852 options where it is known otherwise.
853 For vendor class option, we have to hack. */
854 if (opt_len != 0)
855 new->len = opt_len;
856 else if (val & 0xffff0000)
857 new->len = 4;
858 else if (val & 0xff00)
859 new->len = 2;
860 else
861 new->len = 1;
863 if (lenchar == 'b')
864 new->len = 1;
865 else if (lenchar == 's')
866 new->len = 2;
867 else if (lenchar == 'i')
868 new->len = 4;
870 new->val = opt_malloc(new->len);
871 for (i=0; i<new->len; i++)
872 new->val[i] = val>>((new->len - i - 1)*8);
874 else if (is_addr)
876 struct in_addr in;
877 unsigned char *op;
878 char *slash;
879 /* max length of address/subnet descriptor is five bytes,
880 add one for the option 120 enc byte too */
881 new->val = op = opt_malloc((5 * addrs) + 1);
882 new->flags |= DHOPT_ADDR;
884 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) && new->opt == 120)
886 *(op++) = 1; /* RFC 3361 "enc byte" */
887 new->flags &= ~DHOPT_ADDR;
889 while (addrs--)
891 cp = comma;
892 comma = split(cp);
893 slash = split_chr(cp, '/');
894 in.s_addr = inet_addr(cp);
895 if (!slash)
897 memcpy(op, &in, INADDRSZ);
898 op += INADDRSZ;
900 else
902 unsigned char *p = (unsigned char *)&in;
903 int netsize = atoi(slash);
904 *op++ = netsize;
905 if (netsize > 0)
906 *op++ = *p++;
907 if (netsize > 8)
908 *op++ = *p++;
909 if (netsize > 16)
910 *op++ = *p++;
911 if (netsize > 24)
912 *op++ = *p++;
913 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
916 new->len = op - new->val;
918 else if (is_string)
920 /* text arg */
921 if ((new->opt == 119 || new->opt == 120) && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
923 /* dns search, RFC 3397, or SIP, RFC 3361 */
924 unsigned char *q, *r, *tail;
925 unsigned char *p, *m = NULL, *newp;
926 size_t newlen, len = 0;
927 int header_size = (new->opt == 119) ? 0 : 1;
929 arg = comma;
930 comma = split(arg);
932 while (arg && *arg)
934 char *in, *dom = NULL;
935 size_t domlen = 1;
936 /* Allow "." as an empty domain */
937 if (strcmp (arg, ".") != 0)
939 if (!(dom = canonicalise_opt(arg)))
941 problem = _("bad domain in dhcp-option");
942 break;
944 domlen = strlen(dom) + 2;
947 newp = opt_malloc(len + domlen + header_size);
948 if (m)
950 memcpy(newp, m, header_size + len);
951 free(m);
953 m = newp;
954 p = m + header_size;
955 q = p + len;
957 /* add string on the end in RFC1035 format */
958 for (in = dom; in && *in;)
960 unsigned char *cp = q++;
961 int j;
962 for (j = 0; *in && (*in != '.'); in++, j++)
963 *q++ = *in;
964 *cp = j;
965 if (*in)
966 in++;
968 *q++ = 0;
969 free(dom);
971 /* Now tail-compress using earlier names. */
972 newlen = q - p;
973 for (tail = p + len; *tail; tail += (*tail) + 1)
974 for (r = p; r - p < (int)len; r += (*r) + 1)
975 if (strcmp((char *)r, (char *)tail) == 0)
977 PUTSHORT((r - p) | 0xc000, tail);
978 newlen = tail - p;
979 goto end;
981 end:
982 len = newlen;
984 arg = comma;
985 comma = split(arg);
988 /* RFC 3361, enc byte is zero for names */
989 if (new->opt == 120)
990 m[0] = 0;
991 new->len = (int) len + header_size;
992 new->val = m;
994 else
996 new->len = strlen(comma);
997 /* keep terminating zero on string */
998 new->val = (unsigned char *)opt_string_alloc(comma);
999 new->flags |= DHOPT_STRING;
1004 if ((new->len > 255) ||
1005 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
1006 (new->len > 250 && (new->flags & DHOPT_RFC3925)))
1007 problem = _("dhcp-option too long");
1009 if (!problem)
1011 if (flags == DHOPT_MATCH)
1013 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1014 !new->netid ||
1015 new->netid->next)
1016 problem = _("illegal dhcp-match");
1017 else
1019 new->next = daemon->dhcp_match;
1020 daemon->dhcp_match = new;
1023 else
1025 new->next = daemon->dhcp_opts;
1026 daemon->dhcp_opts = new;
1030 return problem;
1033 #endif
1035 static char *one_opt(int option, char *arg, char *gen_prob, int nest)
1037 int i;
1038 char *comma, *problem = NULL;;
1040 if (option == '?')
1041 return gen_prob;
1043 for (i=0; usage[i].opt != 0; i++)
1044 if (usage[i].opt == option)
1046 int rept = usage[i].rept;
1048 if (nest == 0)
1050 /* command line */
1051 if (rept == ARG_USED_CL)
1052 return _("illegal repeated flag");
1053 if (rept == ARG_ONE)
1054 usage[i].rept = ARG_USED_CL;
1056 else
1058 /* allow file to override command line */
1059 if (rept == ARG_USED_FILE)
1060 return _("illegal repeated keyword");
1061 if (rept == ARG_USED_CL || rept == ARG_ONE)
1062 usage[i].rept = ARG_USED_FILE;
1065 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1067 daemon->options |= rept;
1068 return NULL;
1071 break;
1074 switch (option)
1076 case 'C': /* --conf-file */
1078 char *file = opt_string_alloc(arg);
1079 if (file)
1081 one_file(file, nest, 0);
1082 free(file);
1084 break;
1087 case '7': /* --conf-dir */
1089 DIR *dir_stream;
1090 struct dirent *ent;
1091 char *directory, *path;
1092 struct list {
1093 char *suffix;
1094 struct list *next;
1095 } *ignore_suffix = NULL, *li;
1097 comma = split(arg);
1098 if (!(directory = opt_string_alloc(arg)))
1099 break;
1101 for (arg = comma; arg; arg = comma)
1103 comma = split(arg);
1104 li = opt_malloc(sizeof(struct list));
1105 li->next = ignore_suffix;
1106 ignore_suffix = li;
1107 /* Have to copy: buffer is overwritten */
1108 li->suffix = opt_string_alloc(arg);
1111 if (!(dir_stream = opendir(directory)))
1112 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1114 while ((ent = readdir(dir_stream)))
1116 size_t len = strlen(ent->d_name);
1117 struct stat buf;
1119 /* ignore emacs backups and dotfiles */
1120 if (len == 0 ||
1121 ent->d_name[len - 1] == '~' ||
1122 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1123 ent->d_name[0] == '.')
1124 continue;
1126 for (li = ignore_suffix; li; li = li->next)
1128 /* check for proscribed suffices */
1129 size_t ls = strlen(li->suffix);
1130 if (len > ls &&
1131 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1132 break;
1134 if (li)
1135 continue;
1137 path = opt_malloc(strlen(directory) + len + 2);
1138 strcpy(path, directory);
1139 strcat(path, "/");
1140 strcat(path, ent->d_name);
1142 if (stat(path, &buf) == -1)
1143 die(_("cannot access %s: %s"), path, EC_FILE);
1144 /* only reg files allowed. */
1145 if (!S_ISREG(buf.st_mode))
1146 continue;
1148 /* dir is one level, so files must be readable */
1149 one_file(path, nest + 1, 0);
1150 free(path);
1153 closedir(dir_stream);
1154 free(directory);
1155 for(; ignore_suffix; ignore_suffix = li)
1157 li = ignore_suffix->next;
1158 free(ignore_suffix->suffix);
1159 free(ignore_suffix);
1162 break;
1165 case '8': /* --log-facility */
1166 /* may be a filename */
1167 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
1168 daemon->log_file = opt_string_alloc(arg);
1169 else
1171 for (i = 0; facilitynames[i].c_name; i++)
1172 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1173 break;
1175 if (facilitynames[i].c_name)
1176 daemon->log_fac = facilitynames[i].c_val;
1177 else
1178 problem = "bad log facility";
1180 break;
1182 case 'x': /* --pid-file */
1183 daemon->runfile = opt_string_alloc(arg);
1184 break;
1186 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1187 if (daemon->dhcp_hosts_file)
1188 problem = _("only one dhcp-hostsfile allowed");
1189 else
1190 daemon->dhcp_hosts_file = opt_string_alloc(arg);
1191 break;
1193 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1194 if (daemon->dhcp_opts_file)
1195 problem = _("only one dhcp-optsfile allowed");
1196 else
1197 daemon->dhcp_opts_file = opt_string_alloc(arg);
1198 break;
1200 case 'r': /* --resolv-file */
1202 char *name = opt_string_alloc(arg);
1203 struct resolvc *new, *list = daemon->resolv_files;
1205 if (list && list->is_default)
1207 /* replace default resolv file - possibly with nothing */
1208 if (name)
1210 list->is_default = 0;
1211 list->name = name;
1213 else
1214 list = NULL;
1216 else if (name)
1218 new = opt_malloc(sizeof(struct resolvc));
1219 new->next = list;
1220 new->name = name;
1221 new->is_default = 0;
1222 new->mtime = 0;
1223 new->logged = 0;
1224 list = new;
1226 daemon->resolv_files = list;
1227 break;
1230 case 'm': /* --mx-host */
1232 int pref = 1;
1233 struct mx_srv_record *new;
1234 char *name, *target = NULL;
1236 if ((comma = split(arg)))
1238 char *prefstr;
1239 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1240 problem = _("bad MX preference");
1243 if (!(name = canonicalise_opt(arg)) ||
1244 (comma && !(target = canonicalise_opt(comma))))
1245 problem = _("bad MX name");
1247 new = opt_malloc(sizeof(struct mx_srv_record));
1248 new->next = daemon->mxnames;
1249 daemon->mxnames = new;
1250 new->issrv = 0;
1251 new->name = name;
1252 new->target = target; /* may be NULL */
1253 new->weight = pref;
1254 break;
1257 case 't': /* --mx-target */
1258 if (!(daemon->mxtarget = canonicalise_opt(arg)))
1259 problem = _("bad MX target");
1260 break;
1262 #ifdef HAVE_DHCP
1263 case 'l': /* --dhcp-leasefile */
1264 daemon->lease_file = opt_string_alloc(arg);
1265 break;
1267 case '6': /* --dhcp-script */
1268 # if defined(NO_FORK)
1269 problem = _("cannot run scripts under uClinux");
1270 # elif !defined(HAVE_SCRIPT)
1271 problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1272 # else
1273 daemon->lease_change_command = opt_string_alloc(arg);
1274 # endif
1275 break;
1276 #endif
1278 case 'H': /* --addn-hosts */
1280 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1281 static int hosts_index = 1;
1282 new->fname = opt_string_alloc(arg);
1283 new->index = hosts_index++;
1284 new->flags = 0;
1285 new->next = daemon->addn_hosts;
1286 daemon->addn_hosts = new;
1287 break;
1290 case 's': /* --domain */
1291 if (strcmp (arg, "#") == 0)
1292 daemon->options |= OPT_RESOLV_DOMAIN;
1293 else
1295 char *d;
1296 comma = split(arg);
1297 if (!(d = canonicalise_opt(arg)))
1298 option = '?';
1299 else
1301 if (comma)
1303 struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
1304 unhide_metas(comma);
1305 if ((arg = split_chr(comma, '/')))
1307 int mask;
1308 if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1309 !atoi_check(arg, &mask))
1310 option = '?';
1311 else
1313 mask = (1 << (32 - mask)) - 1;
1314 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1315 new->end.s_addr = new->start.s_addr | htonl(mask);
1318 else if ((arg = split(comma)))
1320 if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1321 (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
1322 option = '?';
1324 else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1325 option = '?';
1327 new->domain = d;
1328 new->next = daemon->cond_domain;
1329 daemon->cond_domain = new;
1331 else
1332 daemon->domain_suffix = d;
1335 break;
1337 case 'u': /* --user */
1338 daemon->username = opt_string_alloc(arg);
1339 break;
1341 case 'g': /* --group */
1342 daemon->groupname = opt_string_alloc(arg);
1343 daemon->group_set = 1;
1344 break;
1346 #ifdef HAVE_DHCP
1347 case LOPT_SCRIPTUSR: /* --scriptuser */
1348 daemon->scriptuser = opt_string_alloc(arg);
1349 break;
1350 #endif
1352 case 'i': /* --interface */
1353 do {
1354 struct iname *new = opt_malloc(sizeof(struct iname));
1355 comma = split(arg);
1356 new->next = daemon->if_names;
1357 daemon->if_names = new;
1358 /* new->name may be NULL if someone does
1359 "interface=" to disable all interfaces except loop. */
1360 new->name = opt_string_alloc(arg);
1361 new->isloop = new->used = 0;
1362 arg = comma;
1363 } while (arg);
1364 break;
1366 case 'I': /* --except-interface */
1367 case '2': /* --no-dhcp-interface */
1368 do {
1369 struct iname *new = opt_malloc(sizeof(struct iname));
1370 comma = split(arg);
1371 new->name = opt_string_alloc(arg);
1372 if (option == 'I')
1374 new->next = daemon->if_except;
1375 daemon->if_except = new;
1377 else
1379 new->next = daemon->dhcp_except;
1380 daemon->dhcp_except = new;
1382 arg = comma;
1383 } while (arg);
1384 break;
1386 case 'B': /* --bogus-nxdomain */
1388 struct in_addr addr;
1389 unhide_metas(arg);
1390 if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1392 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1393 baddr->next = daemon->bogus_addr;
1394 daemon->bogus_addr = baddr;
1395 baddr->addr = addr;
1397 else
1398 option = '?'; /* error */
1399 break;
1402 case 'a': /* --listen-address */
1403 do {
1404 struct iname *new = opt_malloc(sizeof(struct iname));
1405 comma = split(arg);
1406 unhide_metas(arg);
1407 new->next = daemon->if_addrs;
1408 if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1410 new->addr.sa.sa_family = AF_INET;
1411 #ifdef HAVE_SOCKADDR_SA_LEN
1412 new->addr.in.sin_len = sizeof(new->addr.in);
1413 #endif
1415 #ifdef HAVE_IPV6
1416 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1418 new->addr.sa.sa_family = AF_INET6;
1419 new->addr.in6.sin6_flowinfo = 0;
1420 new->addr.in6.sin6_scope_id = 0;
1421 #ifdef HAVE_SOCKADDR_SA_LEN
1422 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1423 #endif
1425 #endif
1426 else
1428 option = '?'; /* error */
1429 break;
1432 daemon->if_addrs = new;
1433 arg = comma;
1434 } while (arg);
1435 break;
1437 case 'S': /* --server */
1438 case LOPT_LOCAL: /* --local */
1439 case 'A': /* --address */
1440 case LOPT_NO_REBIND: /* --rebind-domain-ok */
1442 struct server *serv, *newlist = NULL;
1444 unhide_metas(arg);
1446 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
1448 int rebind = !(*arg == '/');
1449 char *end = NULL;
1450 if (!rebind)
1451 arg++;
1452 while (rebind || (end = split_chr(arg, '/')))
1454 char *domain = NULL;
1455 /* elide leading dots - they are implied in the search algorithm */
1456 while (*arg == '.') arg++;
1457 /* # matches everything and becomes a zero length domain string */
1458 if (strcmp(arg, "#") == 0)
1459 domain = "";
1460 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1461 option = '?';
1462 serv = opt_malloc(sizeof(struct server));
1463 memset(serv, 0, sizeof(struct server));
1464 serv->next = newlist;
1465 newlist = serv;
1466 serv->domain = domain;
1467 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1468 arg = end;
1469 if (rebind)
1470 break;
1472 if (!newlist)
1474 option = '?';
1475 break;
1479 else
1481 newlist = opt_malloc(sizeof(struct server));
1482 memset(newlist, 0, sizeof(struct server));
1485 if (option == 'A')
1487 newlist->flags |= SERV_LITERAL_ADDRESS;
1488 if (!(newlist->flags & SERV_TYPE))
1489 option = '?';
1491 else if (option == LOPT_NO_REBIND)
1492 newlist->flags |= SERV_NO_REBIND;
1494 if (!arg || !*arg)
1496 if (!(newlist->flags & SERV_NO_REBIND))
1497 newlist->flags |= SERV_NO_ADDR; /* no server */
1498 if (newlist->flags & SERV_LITERAL_ADDRESS)
1499 option = '?';
1502 else if (strcmp(arg, "#") == 0)
1504 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
1505 if (newlist->flags & SERV_LITERAL_ADDRESS)
1506 option = '?';
1508 else
1510 int source_port = 0, serv_port = NAMESERVER_PORT;
1511 char *portno, *source;
1513 if ((source = split_chr(arg, '@')) && /* is there a source. */
1514 (portno = split_chr(source, '#')) &&
1515 !atoi_check16(portno, &source_port))
1516 problem = _("bad port");
1518 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1519 !atoi_check16(portno, &serv_port))
1520 problem = _("bad port");
1522 if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
1524 newlist->addr.in.sin_port = htons(serv_port);
1525 newlist->source_addr.in.sin_port = htons(source_port);
1526 newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
1527 #ifdef HAVE_SOCKADDR_SA_LEN
1528 newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
1529 #endif
1530 if (source)
1532 newlist->flags |= SERV_HAS_SOURCE;
1533 if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
1535 #if defined(SO_BINDTODEVICE)
1536 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1537 strncpy(newlist->interface, source, IF_NAMESIZE - 1);
1538 #else
1539 problem = _("interface binding not supported");
1540 #endif
1543 else
1544 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1546 #ifdef HAVE_IPV6
1547 else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
1549 newlist->addr.in6.sin6_port = htons(serv_port);
1550 newlist->source_addr.in6.sin6_port = htons(source_port);
1551 newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
1552 #ifdef HAVE_SOCKADDR_SA_LEN
1553 newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
1554 #endif
1555 if (source)
1557 newlist->flags |= SERV_HAS_SOURCE;
1558 if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
1560 #if defined(SO_BINDTODEVICE)
1561 newlist->source_addr.in6.sin6_addr = in6addr_any;
1562 strncpy(newlist->interface, source, IF_NAMESIZE - 1);
1563 #else
1564 problem = _("interface binding not supported");
1565 #endif
1568 else
1569 newlist->source_addr.in6.sin6_addr = in6addr_any;
1571 #endif
1572 else
1573 option = '?'; /* error */
1577 serv = newlist;
1578 while (serv->next)
1580 serv->next->flags = serv->flags;
1581 serv->next->addr = serv->addr;
1582 serv->next->source_addr = serv->source_addr;
1583 serv = serv->next;
1585 serv->next = daemon->servers;
1586 daemon->servers = newlist;
1587 break;
1590 case 'c': /* --cache-size */
1592 int size;
1594 if (!atoi_check(arg, &size))
1595 option = '?';
1596 else
1598 /* zero is OK, and means no caching. */
1600 if (size < 0)
1601 size = 0;
1602 else if (size > 10000)
1603 size = 10000;
1605 daemon->cachesize = size;
1607 break;
1610 case 'p': /* --port */
1611 if (!atoi_check16(arg, &daemon->port))
1612 option = '?';
1613 break;
1615 case LOPT_MINPORT: /* --min-port */
1616 if (!atoi_check16(arg, &daemon->min_port))
1617 option = '?';
1618 break;
1620 case '0': /* --dns-forward-max */
1621 if (!atoi_check(arg, &daemon->ftabsize))
1622 option = '?';
1623 break;
1625 case LOPT_MAX_LOGS: /* --log-async */
1626 daemon->max_logs = LOG_MAX; /* default */
1627 if (arg && !atoi_check(arg, &daemon->max_logs))
1628 option = '?';
1629 else if (daemon->max_logs > 100)
1630 daemon->max_logs = 100;
1631 break;
1633 case 'P': /* --edns-packet-max */
1635 int i;
1636 if (!atoi_check(arg, &i))
1637 option = '?';
1638 daemon->edns_pktsz = (unsigned short)i;
1639 break;
1642 case 'Q': /* --query-port */
1643 if (!atoi_check16(arg, &daemon->query_port))
1644 option = '?';
1645 /* if explicitly set to zero, use single OS ephemeral port
1646 and disable random ports */
1647 if (daemon->query_port == 0)
1648 daemon->osport = 1;
1649 break;
1651 case 'T': /* --local-ttl */
1652 case LOPT_NEGTTL: /* --neg-ttl */
1653 case LOPT_MAXTTL: /* --max-ttl */
1655 int ttl;
1656 if (!atoi_check(arg, &ttl))
1657 option = '?';
1658 else if (option == LOPT_NEGTTL)
1659 daemon->neg_ttl = (unsigned long)ttl;
1660 else if (option == LOPT_MAXTTL)
1661 daemon->max_ttl = (unsigned long)ttl;
1662 else
1663 daemon->local_ttl = (unsigned long)ttl;
1664 break;
1667 #ifdef HAVE_DHCP
1668 case 'X': /* --dhcp-lease-max */
1669 if (!atoi_check(arg, &daemon->dhcp_max))
1670 option = '?';
1671 break;
1672 #endif
1674 #ifdef HAVE_TFTP
1675 case LOPT_TFTP: /* --enable-tftp */
1676 if (arg)
1678 struct interface_list *new = opt_malloc(sizeof(struct interface_list));
1679 new->interface = opt_string_alloc(arg);
1680 new->next = daemon->tftp_interfaces;
1681 daemon->tftp_interfaces = new;
1683 else
1684 daemon->tftp_unlimited = 1;
1685 break;
1687 case LOPT_TFTP_MAX: /* --tftp-max */
1688 if (!atoi_check(arg, &daemon->tftp_max))
1689 option = '?';
1690 break;
1692 case LOPT_PREFIX: /* --tftp-prefix */
1693 comma = split(arg);
1694 if (comma)
1696 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
1697 new->interface = opt_string_alloc(comma);
1698 new->prefix = opt_string_alloc(arg);
1699 new->next = daemon->if_prefix;
1700 daemon->if_prefix = new;
1702 else
1703 daemon->tftp_prefix = opt_string_alloc(arg);
1704 break;
1706 case LOPT_TFTPPORTS: /* --tftp-port-range */
1707 if (!(comma = split(arg)) ||
1708 !atoi_check16(arg, &daemon->start_tftp_port) ||
1709 !atoi_check16(comma, &daemon->end_tftp_port))
1710 problem = _("bad port range");
1712 if (daemon->start_tftp_port > daemon->end_tftp_port)
1714 int tmp = daemon->start_tftp_port;
1715 daemon->start_tftp_port = daemon->end_tftp_port;
1716 daemon->end_tftp_port = tmp;
1719 break;
1720 #endif
1722 case LOPT_BRIDGE: /* --bridge-interface */
1724 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
1725 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
1727 problem = _("bad bridge-interface");
1728 break;
1731 strcpy(new->iface, arg);
1732 new->alias = NULL;
1733 new->next = daemon->bridges;
1734 daemon->bridges = new;
1736 do {
1737 arg = comma;
1738 comma = split(arg);
1739 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
1741 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
1742 b->next = new->alias;
1743 new->alias = b;
1744 strcpy(b->iface, arg);
1746 } while (comma);
1748 break;
1751 #ifdef HAVE_DHCP
1752 case 'F': /* --dhcp-range */
1754 int k, leasepos = 2;
1755 char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
1756 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
1758 new->next = daemon->dhcp;
1759 new->lease_time = DEFLEASE;
1760 new->addr_epoch = 0;
1761 new->netmask.s_addr = 0;
1762 new->broadcast.s_addr = 0;
1763 new->router.s_addr = 0;
1764 new->netid.net = NULL;
1765 new->filter = NULL;
1766 new->flags = 0;
1767 new->interface = NULL;
1769 gen_prob = _("bad dhcp-range");
1771 if (!arg)
1773 option = '?';
1774 break;
1777 while(1)
1779 for (cp = arg; *cp; cp++)
1780 if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
1781 break;
1783 if (*cp != ',' && (comma = split(arg)))
1785 if (strstr(arg, "interface:") == arg)
1786 new->interface = opt_string_alloc(arg+10);
1787 else if (is_tag_prefix(arg))
1789 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
1790 tt->net = opt_string_alloc(arg+4);
1791 tt->next = new->filter;
1792 new->filter = tt;
1794 else
1796 if (new->netid.net)
1797 problem = _("only one tag allowed");
1798 else if (strstr(arg, "set:") == arg)
1799 new->netid.net = opt_string_alloc(arg+4);
1800 else
1801 new->netid.net = opt_string_alloc(arg);
1803 arg = comma;
1805 else
1807 a[0] = arg;
1808 break;
1812 for (k = 1; k < 5; k++)
1813 if (!(a[k] = split(a[k-1])))
1814 break;
1816 if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
1817 option = '?';
1818 else if (strcmp(a[1], "static") == 0)
1820 new->end = new->start;
1821 new->flags |= CONTEXT_STATIC;
1823 else if (strcmp(a[1], "proxy") == 0)
1825 new->end = new->start;
1826 new->flags |= CONTEXT_PROXY;
1828 else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
1829 option = '?';
1831 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
1833 struct in_addr tmp = new->start;
1834 new->start = new->end;
1835 new->end = tmp;
1838 if (option != '?' && k >= 3 && strchr(a[2], '.') &&
1839 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
1841 new->flags |= CONTEXT_NETMASK;
1842 leasepos = 3;
1843 if (!is_same_net(new->start, new->end, new->netmask))
1844 problem = _("inconsistent DHCP range");
1846 daemon->dhcp = new;
1848 if (k >= 4 && strchr(a[3], '.') &&
1849 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
1851 new->flags |= CONTEXT_BRDCAST;
1852 leasepos = 4;
1855 if (k >= leasepos+1)
1857 if (strcmp(a[leasepos], "infinite") == 0)
1858 new->lease_time = 0xffffffff;
1859 else
1861 int fac = 1;
1862 if (strlen(a[leasepos]) > 0)
1864 switch (a[leasepos][strlen(a[leasepos]) - 1])
1866 case 'd':
1867 case 'D':
1868 fac *= 24;
1869 /* fall though */
1870 case 'h':
1871 case 'H':
1872 fac *= 60;
1873 /* fall through */
1874 case 'm':
1875 case 'M':
1876 fac *= 60;
1877 /* fall through */
1878 case 's':
1879 case 'S':
1880 a[leasepos][strlen(a[leasepos]) - 1] = 0;
1883 new->lease_time = atoi(a[leasepos]) * fac;
1884 /* Leases of a minute or less confuse
1885 some clients, notably Apple's */
1886 if (new->lease_time < 120)
1887 new->lease_time = 120;
1891 break;
1894 case LOPT_BANK:
1895 case 'G': /* --dhcp-host */
1897 int j, k = 0;
1898 char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
1899 struct dhcp_config *new;
1900 struct in_addr in;
1902 new = opt_malloc(sizeof(struct dhcp_config));
1904 new->next = daemon->dhcp_conf;
1905 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
1906 new->hwaddr = NULL;
1907 new->netid = NULL;
1909 if ((a[0] = arg))
1910 for (k = 1; k < 6; k++)
1911 if (!(a[k] = split(a[k-1])))
1912 break;
1914 for (j = 0; j < k; j++)
1915 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
1917 char *arg = a[j];
1919 if ((arg[0] == 'i' || arg[0] == 'I') &&
1920 (arg[1] == 'd' || arg[1] == 'D') &&
1921 arg[2] == ':')
1923 if (arg[3] == '*')
1924 new->flags |= CONFIG_NOCLID;
1925 else
1927 int len;
1928 arg += 3; /* dump id: */
1929 if (strchr(arg, ':'))
1930 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
1931 else
1933 unhide_metas(arg);
1934 len = (int) strlen(arg);
1937 if ((new->clid = opt_malloc(len)))
1939 new->flags |= CONFIG_CLID;
1940 new->clid_len = len;
1941 memcpy(new->clid, arg, len);
1945 /* dhcp-host has strange backwards-compat needs. */
1946 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
1948 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
1949 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
1950 newtag->net = opt_malloc(strlen(arg + 4) + 1);
1951 newlist->next = new->netid;
1952 new->netid = newlist;
1953 newlist->list = newtag;
1954 strcpy(newtag->net, arg+4);
1955 unhide_metas(newtag->net);
1957 else
1959 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
1960 newhw->next = new->hwaddr;
1961 new->hwaddr = newhw;
1962 newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
1963 &newhw->wildcard_mask, &newhw->hwaddr_type);
1966 else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
1968 new->addr = in;
1969 new->flags |= CONFIG_ADDR;
1971 else
1973 char *cp, *lastp = NULL, last = 0;
1974 int fac = 1;
1976 if (strlen(a[j]) > 1)
1978 lastp = a[j] + strlen(a[j]) - 1;
1979 last = *lastp;
1980 switch (last)
1982 case 'd':
1983 case 'D':
1984 fac *= 24;
1985 /* fall through */
1986 case 'h':
1987 case 'H':
1988 fac *= 60;
1989 /* fall through */
1990 case 'm':
1991 case 'M':
1992 fac *= 60;
1993 /* fall through */
1994 case 's':
1995 case 'S':
1996 *lastp = 0;
2000 for (cp = a[j]; *cp; cp++)
2001 if (!isdigit((int)*cp) && *cp != ' ')
2002 break;
2004 if (*cp)
2006 if (lastp)
2007 *lastp = last;
2008 if (strcmp(a[j], "infinite") == 0)
2010 new->lease_time = 0xffffffff;
2011 new->flags |= CONFIG_TIME;
2013 else if (strcmp(a[j], "ignore") == 0)
2014 new->flags |= CONFIG_DISABLE;
2015 else
2017 if (!(new->hostname = canonicalise_opt(a[j])) ||
2018 !legal_hostname(new->hostname))
2019 problem = _("bad DHCP host name");
2020 else
2021 new->flags |= CONFIG_NAME;
2022 new->domain = NULL;
2025 else
2027 new->lease_time = atoi(a[j]) * fac;
2028 /* Leases of a minute or less confuse
2029 some clients, notably Apple's */
2030 if (new->lease_time < 120)
2031 new->lease_time = 120;
2032 new->flags |= CONFIG_TIME;
2036 daemon->dhcp_conf = new;
2037 break;
2040 case LOPT_TAG_IF: /* --tag-if */
2042 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2044 new->tag = NULL;
2045 new->set = NULL;
2046 new->next = NULL;
2048 /* preserve order */
2049 if (!daemon->tag_if)
2050 daemon->tag_if = new;
2051 else
2053 struct tag_if *tmp;
2054 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2055 tmp->next = new;
2058 while (arg)
2060 size_t len;
2062 comma = split(arg);
2063 len = strlen(arg);
2065 if (len < 5)
2067 new->set = NULL;
2068 break;
2070 else
2072 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2073 newtag->net = opt_malloc(len - 3);
2074 strcpy(newtag->net, arg+4);
2075 unhide_metas(newtag->net);
2077 if (strstr(arg, "set:") == arg)
2079 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2080 newlist->next = new->set;
2081 new->set = newlist;
2082 newlist->list = newtag;
2084 else if (strstr(arg, "tag:") == arg)
2086 newtag->next = new->tag;
2087 new->tag = newtag;
2089 else
2091 new->set = NULL;
2092 break;
2096 arg = comma;
2099 if (!new->set)
2100 problem = _("bad tag-if");
2102 break;
2106 case 'O': /* --dhcp-option */
2107 case LOPT_FORCE: /* --dhcp-option-force */
2108 case LOPT_OPTS:
2109 case LOPT_MATCH: /* --dhcp-match */
2110 problem = parse_dhcp_opt(arg,
2111 option == LOPT_FORCE ? DHOPT_FORCE :
2112 (option == LOPT_MATCH ? DHOPT_MATCH :
2113 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2114 break;
2116 case 'M': /* --dhcp-boot */
2118 struct dhcp_netid *id = NULL;
2119 while (is_tag_prefix(arg))
2121 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
2122 newid->next = id;
2123 id = newid;
2124 comma = split(arg);
2125 newid->net = opt_string_alloc(arg+4);
2126 arg = comma;
2129 if (!arg)
2130 option = '?';
2131 else
2133 char *dhcp_file, *dhcp_sname = NULL;
2134 struct in_addr dhcp_next_server;
2135 comma = split(arg);
2136 dhcp_file = opt_string_alloc(arg);
2137 dhcp_next_server.s_addr = 0;
2138 if (comma)
2140 arg = comma;
2141 comma = split(arg);
2142 dhcp_sname = opt_string_alloc(arg);
2143 if (comma)
2145 unhide_metas(comma);
2146 if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
2147 option = '?';
2150 if (option != '?')
2152 struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
2153 new->file = dhcp_file;
2154 new->sname = dhcp_sname;
2155 new->next_server = dhcp_next_server;
2156 new->netid = id;
2157 new->next = daemon->boot_config;
2158 daemon->boot_config = new;
2162 break;
2165 case LOPT_PXE_PROMT: /* --pxe-prompt */
2167 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2168 int timeout;
2170 new->netid = NULL;
2171 new->opt = 10; /* PXE_MENU_PROMPT */
2173 while (is_tag_prefix(arg))
2175 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2176 comma = split(arg);
2177 nn->next = new->netid;
2178 new->netid = nn;
2179 nn->net = opt_string_alloc(arg+4);
2180 arg = comma;
2183 if (!arg)
2184 option = '?';
2185 else
2187 comma = split(arg);
2188 unhide_metas(arg);
2189 new->len = strlen(arg) + 1;
2190 new->val = opt_malloc(new->len);
2191 memcpy(new->val + 1, arg, new->len - 1);
2193 new->u.vendor_class = (unsigned char *)"PXEClient";
2194 new->flags = DHOPT_VENDOR;
2196 if (comma && atoi_check(comma, &timeout))
2197 *(new->val) = timeout;
2198 else
2199 *(new->val) = 255;
2201 new->next = daemon->dhcp_opts;
2202 daemon->dhcp_opts = new;
2203 daemon->enable_pxe = 1;
2206 break;
2209 case LOPT_PXE_SERV: /* --pxe-service */
2211 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2212 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2213 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2214 static int boottype = 32768;
2216 new->netid = NULL;
2217 new->server.s_addr = 0;
2219 while (is_tag_prefix(arg))
2221 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2222 comma = split(arg);
2223 nn->next = new->netid;
2224 new->netid = nn;
2225 nn->net = opt_string_alloc(arg+4);
2226 arg = comma;
2229 if (arg && (comma = split(arg)))
2231 for (i = 0; CSA[i]; i++)
2232 if (strcasecmp(CSA[i], arg) == 0)
2233 break;
2235 if (CSA[i] || atoi_check(arg, &i))
2237 arg = comma;
2238 comma = split(arg);
2240 new->CSA = i;
2241 new->menu = opt_string_alloc(arg);
2243 if (!comma)
2245 new->type = 0; /* local boot */
2246 new->basename = NULL;
2248 else
2250 arg = comma;
2251 comma = split(arg);
2252 if (atoi_check(arg, &i))
2254 new->type = i;
2255 new->basename = NULL;
2257 else
2259 new->type = boottype++;
2260 new->basename = opt_string_alloc(arg);
2263 if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
2264 option = '?';
2267 /* Order matters */
2268 new->next = NULL;
2269 if (!daemon->pxe_services)
2270 daemon->pxe_services = new;
2271 else
2273 struct pxe_service *s;
2274 for (s = daemon->pxe_services; s->next; s = s->next);
2275 s->next = new;
2278 daemon->enable_pxe = 1;
2279 break;
2284 option = '?';
2285 break;
2288 case '4': /* --dhcp-mac */
2290 if (!(comma = split(arg)))
2291 option = '?';
2292 else
2294 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2295 new->netid.net = opt_string_alloc(set_prefix(arg));
2296 unhide_metas(comma);
2297 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2298 new->next = daemon->dhcp_macs;
2299 daemon->dhcp_macs = new;
2302 break;
2304 case 'U': /* --dhcp-vendorclass */
2305 case 'j': /* --dhcp-userclass */
2306 case LOPT_CIRCUIT: /* --dhcp-circuitid */
2307 case LOPT_REMOTE: /* --dhcp-remoteid */
2308 case LOPT_SUBSCR: /* --dhcp-subscrid */
2310 if (!(comma = split(arg)))
2311 option = '?';
2312 else
2314 char *p;
2315 int dig = 0;
2316 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2317 new->netid.net = opt_string_alloc(set_prefix(arg));
2318 /* check for hex string - must digits may include : must not have nothing else,
2319 only allowed for agent-options. */
2320 for (p = comma; *p; p++)
2321 if (isxdigit((int)*p))
2322 dig = 1;
2323 else if (*p != ':')
2324 break;
2325 unhide_metas(comma);
2326 if (option == 'U' || option == 'j' || *p || !dig)
2328 new->len = strlen(comma);
2329 new->data = opt_malloc(new->len);
2330 memcpy(new->data, comma, new->len);
2332 else
2334 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2335 new->data = opt_malloc(new->len);
2336 memcpy(new->data, comma, new->len);
2339 switch (option)
2341 case 'j':
2342 new->match_type = MATCH_USER;
2343 break;
2344 case 'U':
2345 new->match_type = MATCH_VENDOR;
2346 break;
2347 case LOPT_CIRCUIT:
2348 new->match_type = MATCH_CIRCUIT;
2349 break;
2350 case LOPT_REMOTE:
2351 new->match_type = MATCH_REMOTE;
2352 break;
2353 case LOPT_SUBSCR:
2354 new->match_type = MATCH_SUBSCRIBER;
2355 break;
2357 new->next = daemon->dhcp_vendors;
2358 daemon->dhcp_vendors = new;
2360 break;
2363 case LOPT_ALTPORT: /* --dhcp-alternate-port */
2364 if (!arg)
2366 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2367 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2369 else
2371 comma = split(arg);
2372 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2373 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
2374 problem = _("invalid port number");
2375 if (!comma)
2376 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2378 break;
2380 case 'J': /* --dhcp-ignore */
2381 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
2382 case LOPT_BROADCAST: /* --dhcp-broadcast */
2383 case '3': /* --bootp-dynamic */
2384 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
2386 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
2387 struct dhcp_netid *list = NULL;
2388 if (option == 'J')
2390 new->next = daemon->dhcp_ignore;
2391 daemon->dhcp_ignore = new;
2393 else if (option == LOPT_BROADCAST)
2395 new->next = daemon->force_broadcast;
2396 daemon->force_broadcast = new;
2398 else if (option == '3')
2400 new->next = daemon->bootp_dynamic;
2401 daemon->bootp_dynamic = new;
2403 else if (option == LOPT_GEN_NAMES)
2405 new->next = daemon->dhcp_gen_names;
2406 daemon->dhcp_gen_names = new;
2408 else
2410 new->next = daemon->dhcp_ignore_names;
2411 daemon->dhcp_ignore_names = new;
2414 while (arg) {
2415 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
2416 comma = split(arg);
2417 member->next = list;
2418 list = member;
2419 if (is_tag_prefix(arg))
2420 member->net = opt_string_alloc(arg+4);
2421 else
2422 member->net = opt_string_alloc(arg);
2423 arg = comma;
2426 new->list = list;
2427 break;
2430 case LOPT_PROXY: /* --dhcp-proxy */
2431 daemon->override = 1;
2432 while (arg) {
2433 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
2434 comma = split(arg);
2435 if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
2436 problem = _("bad dhcp-proxy address");
2437 new->next = daemon->override_relays;
2438 daemon->override_relays = new;
2439 arg = comma;
2441 break;
2442 #endif
2444 case 'V': /* --alias */
2446 char *dash, *a[3] = { NULL, NULL, NULL };
2447 int k = 0;
2448 struct doctor *new = opt_malloc(sizeof(struct doctor));
2449 new->next = daemon->doctors;
2450 daemon->doctors = new;
2451 new->mask.s_addr = 0xffffffff;
2452 new->end.s_addr = 0;
2454 if ((a[0] = arg))
2455 for (k = 1; k < 3; k++)
2457 if (!(a[k] = split(a[k-1])))
2458 break;
2459 unhide_metas(a[k]);
2462 dash = split_chr(a[0], '-');
2464 if ((k < 2) ||
2465 ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
2466 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
2467 option = '?';
2469 if (k == 3)
2470 new->mask.s_addr = inet_addr(a[2]);
2472 if (dash &&
2473 ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
2474 !is_same_net(new->in, new->end, new->mask) ||
2475 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
2476 problem = _("invalid alias range");
2478 break;
2481 case LOPT_INTNAME: /* --interface-name */
2483 struct interface_name *new, **up;
2484 char *domain = NULL;
2486 comma = split(arg);
2488 if (!comma || !(domain = canonicalise_opt(arg)))
2489 problem = _("bad interface name");
2491 new = opt_malloc(sizeof(struct interface_name));
2492 new->next = NULL;
2493 /* Add to the end of the list, so that first name
2494 of an interface is used for PTR lookups. */
2495 for (up = &daemon->int_names; *up; up = &((*up)->next));
2496 *up = new;
2497 new->name = domain;
2498 new->intr = opt_string_alloc(comma);
2499 break;
2502 case LOPT_CNAME: /* --cname */
2504 struct cname *new;
2506 if (!(comma = split(arg)))
2507 option = '?';
2508 else
2510 char *alias = canonicalise_opt(arg);
2511 char *target = canonicalise_opt(comma);
2513 if (!alias || !target)
2514 problem = _("bad CNAME");
2515 else
2517 for (new = daemon->cnames; new; new = new->next)
2518 if (hostname_isequal(new->alias, arg))
2519 problem = _("duplicate CNAME");
2520 new = opt_malloc(sizeof(struct cname));
2521 new->next = daemon->cnames;
2522 daemon->cnames = new;
2523 new->alias = alias;
2524 new->target = target;
2527 break;
2530 case LOPT_PTR: /* --ptr-record */
2532 struct ptr_record *new;
2533 char *dom, *target = NULL;
2535 comma = split(arg);
2537 if (!(dom = canonicalise_opt(arg)) ||
2538 (comma && !(target = canonicalise_opt(comma))))
2539 problem = _("bad PTR record");
2540 else
2542 new = opt_malloc(sizeof(struct ptr_record));
2543 new->next = daemon->ptr;
2544 daemon->ptr = new;
2545 new->name = dom;
2546 new->ptr = target;
2548 break;
2551 case LOPT_NAPTR: /* --naptr-record */
2553 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2554 int k = 0;
2555 struct naptr *new;
2556 int order, pref;
2557 char *name, *replace = NULL;
2559 if ((a[0] = arg))
2560 for (k = 1; k < 7; k++)
2561 if (!(a[k] = split(a[k-1])))
2562 break;
2565 if (k < 6 ||
2566 !(name = canonicalise_opt(a[0])) ||
2567 !atoi_check16(a[1], &order) ||
2568 !atoi_check16(a[2], &pref) ||
2569 (k == 7 && !(replace = canonicalise_opt(a[6]))))
2570 problem = _("bad NAPTR record");
2571 else
2573 new = opt_malloc(sizeof(struct naptr));
2574 new->next = daemon->naptr;
2575 daemon->naptr = new;
2576 new->name = name;
2577 new->flags = opt_string_alloc(a[3]);
2578 new->services = opt_string_alloc(a[4]);
2579 new->regexp = opt_string_alloc(a[5]);
2580 new->replace = replace;
2581 new->order = order;
2582 new->pref = pref;
2584 break;
2587 case 'Y': /* --txt-record */
2589 struct txt_record *new;
2590 unsigned char *p, *q;
2592 if ((comma = split(arg)))
2593 comma--;
2595 gen_prob = _("TXT record string too long");
2597 if ((q = (unsigned char *)comma))
2598 while (1)
2600 size_t len;
2601 if ((p = (unsigned char *)strchr((char*)q+1, ',')))
2603 if ((len = p - q - 1) > 255)
2604 option = '?';
2605 *q = len;
2606 for (q = q+1; q < p; q++)
2607 *q = unhide_meta(*q);
2609 else
2611 if ((len = strlen((char *)q+1)) > 255)
2612 option = '?';
2613 *q = len;
2614 for (q = q+1; *q; q++)
2615 *q = unhide_meta(*q);
2616 break;
2620 new = opt_malloc(sizeof(struct txt_record));
2621 new->next = daemon->txt;
2622 daemon->txt = new;
2623 new->class = C_IN;
2624 if (comma)
2626 new->len = q - ((unsigned char *)comma);
2627 new->txt = opt_malloc(new->len);
2628 memcpy(new->txt, comma, new->len);
2630 else
2632 static char empty[] = "";
2633 new->len = 1;
2634 new->txt = empty;
2637 /* ensure arg is terminated */
2638 if (comma)
2639 *comma = 0;
2641 if (!(new->name = canonicalise_opt(arg)))
2643 problem = _("bad TXT record");
2644 break;
2647 break;
2650 case 'W': /* --srv-host */
2652 int port = 1, priority = 0, weight = 0;
2653 char *name, *target = NULL;
2654 struct mx_srv_record *new;
2656 comma = split(arg);
2658 if (!(name = canonicalise_opt(arg)))
2659 problem = _("bad SRV record");
2661 if (comma)
2663 arg = comma;
2664 comma = split(arg);
2665 if (!(target = canonicalise_opt(arg))
2666 ) problem = _("bad SRV target");
2668 if (comma)
2670 arg = comma;
2671 comma = split(arg);
2672 if (!atoi_check16(arg, &port))
2673 problem = _("invalid port number");
2675 if (comma)
2677 arg = comma;
2678 comma = split(arg);
2679 if (!atoi_check16(arg, &priority))
2680 problem = _("invalid priority");
2682 if (comma)
2684 arg = comma;
2685 comma = split(arg);
2686 if (!atoi_check16(arg, &weight))
2687 problem = _("invalid weight");
2693 new = opt_malloc(sizeof(struct mx_srv_record));
2694 new->next = daemon->mxnames;
2695 daemon->mxnames = new;
2696 new->issrv = 1;
2697 new->name = name;
2698 new->target = target;
2699 new->srvport = port;
2700 new->priority = priority;
2701 new->weight = weight;
2702 break;
2705 default:
2706 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2710 if (problem)
2711 return problem;
2713 if (option == '?')
2714 return gen_prob;
2716 return NULL;
2719 static void one_file(char *file, int nest, int hard_opt)
2721 volatile int lineno = 0;
2722 FILE *f;
2723 char *buff = daemon->namebuff;
2724 static struct fileread {
2725 dev_t dev;
2726 ino_t ino;
2727 struct fileread *next;
2728 } *filesread = NULL;
2729 struct stat statbuf;
2731 /* ignore repeated files. */
2732 if (hard_opt == 0 && stat(file, &statbuf) == 0)
2734 struct fileread *r;
2736 for (r = filesread; r; r = r->next)
2737 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
2738 return;
2740 r = safe_malloc(sizeof(struct fileread));
2741 r->next = filesread;
2742 filesread = r;
2743 r->dev = statbuf.st_dev;
2744 r->ino = statbuf.st_ino;
2747 if (nest > 20)
2748 die(_("files nested too deep in %s"), file, EC_BADCONF);
2750 if (!(f = fopen(file, "r")))
2752 if (errno == ENOENT && nest == 0)
2753 return; /* No conffile, all done. */
2754 else
2756 char *str = _("cannot read %s: %s");
2757 if (hard_opt != 0)
2759 my_syslog(LOG_ERR, str, file, strerror(errno));
2760 return;
2762 else
2763 die(str, file, EC_FILE);
2767 while (fgets(buff, MAXDNAME, f))
2769 int white, i, option; ;
2770 char *errmess, *p, *arg, *start;
2771 size_t len;
2773 /* Memory allocation failure longjmps here if mem_recover == 1 */
2774 if (hard_opt)
2776 if (setjmp(mem_jmp))
2777 continue;
2778 mem_recover = 1;
2781 lineno++;
2782 errmess = NULL;
2784 /* Implement quotes, inside quotes we allow \\ \" \n and \t
2785 metacharacters get hidden also strip comments */
2786 for (white = 1, p = buff; *p; p++)
2788 if (*p == '"')
2790 memmove(p, p+1, strlen(p+1)+1);
2792 for(; *p && *p != '"'; p++)
2794 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
2796 if (p[1] == 't')
2797 p[1] = '\t';
2798 else if (p[1] == 'n')
2799 p[1] = '\n';
2800 else if (p[1] == 'b')
2801 p[1] = '\b';
2802 else if (p[1] == 'r')
2803 p[1] = '\r';
2804 else if (p[1] == 'e') /* escape */
2805 p[1] = '\033';
2806 memmove(p, p+1, strlen(p+1)+1);
2808 *p = hide_meta(*p);
2811 if (*p == 0)
2813 errmess = _("missing \"");
2814 goto oops;
2817 memmove(p, p+1, strlen(p+1)+1);
2820 if (isspace(*p))
2822 *p = ' ';
2823 white = 1;
2825 else
2827 if (white && *p == '#')
2829 *p = 0;
2830 break;
2832 white = 0;
2837 /* strip leading spaces */
2838 for (start = buff; *start && *start == ' '; start++);
2840 /* strip trailing spaces */
2841 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
2843 if (len == 0)
2844 continue;
2845 else
2846 start[len] = 0;
2848 if (hard_opt != 0)
2849 arg = start;
2850 else if ((p=strchr(start, '=')))
2852 /* allow spaces around "=" */
2853 for (arg = p+1; *arg == ' '; arg++);
2854 for (; p >= start && (*p == ' ' || *p == '='); p--)
2855 *p = 0;
2857 else
2858 arg = NULL;
2860 if (hard_opt != 0)
2861 option = hard_opt;
2862 else
2864 for (option = 0, i = 0; opts[i].name; i++)
2865 if (strcmp(opts[i].name, start) == 0)
2867 option = opts[i].val;
2868 break;
2871 if (!option)
2872 errmess = _("bad option");
2873 else if (opts[i].has_arg == 0 && arg)
2874 errmess = _("extraneous parameter");
2875 else if (opts[i].has_arg == 1 && !arg)
2876 errmess = _("missing parameter");
2879 if (!errmess)
2880 errmess = one_opt(option, arg, _("error"), nest + 1);
2882 if (errmess)
2884 oops:
2885 sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
2886 if (hard_opt != 0)
2887 my_syslog(LOG_ERR, buff, file);
2888 else
2889 die(buff, file, EC_BADCONF);
2893 mem_recover = 0;
2894 fclose(f);
2897 #ifdef HAVE_DHCP
2898 void reread_dhcp(void)
2900 if (daemon->dhcp_hosts_file)
2902 struct dhcp_config *configs, *cp, **up;
2904 /* remove existing... */
2905 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
2907 cp = configs->next;
2909 if (configs->flags & CONFIG_BANK)
2911 struct hwaddr_config *mac, *tmp;
2912 struct dhcp_netid_list *list, *tmplist;
2914 for (mac = configs->hwaddr; mac; mac = tmp)
2916 tmp = mac->next;
2917 free(mac);
2920 if (configs->flags & CONFIG_CLID)
2921 free(configs->clid);
2923 for (list = configs->netid; list; list = tmplist)
2925 free(list->list);
2926 tmplist = list->next;
2927 free(list);
2930 if (configs->flags & CONFIG_NAME)
2931 free(configs->hostname);
2934 *up = configs->next;
2935 free(configs);
2937 else
2938 up = &configs->next;
2941 one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
2942 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
2945 if (daemon->dhcp_opts_file)
2947 struct dhcp_opt *opts, *cp, **up;
2948 struct dhcp_netid *id, *next;
2950 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
2952 cp = opts->next;
2954 if (opts->flags & DHOPT_BANK)
2956 if ((opts->flags & DHOPT_VENDOR))
2957 free(opts->u.vendor_class);
2958 free(opts->val);
2959 for (id = opts->netid; id; id = next)
2961 next = id->next;
2962 free(id->net);
2963 free(id);
2965 *up = opts->next;
2966 free(opts);
2968 else
2969 up = &opts->next;
2972 one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
2973 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
2976 #endif
2978 void read_opts(int argc, char **argv, char *compile_opts)
2980 char *buff = opt_malloc(MAXDNAME);
2981 int option, nest = 0, testmode = 0;
2982 char *errmess, *arg, *conffile = CONFFILE;
2984 opterr = 0;
2986 daemon = opt_malloc(sizeof(struct daemon));
2987 memset(daemon, 0, sizeof(struct daemon));
2988 daemon->namebuff = buff;
2990 /* Set defaults - everything else is zero or NULL */
2991 daemon->cachesize = CACHESIZ;
2992 daemon->ftabsize = FTABSIZ;
2993 daemon->port = NAMESERVER_PORT;
2994 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
2995 daemon->dhcp_server_port = DHCP_SERVER_PORT;
2996 daemon->default_resolv.is_default = 1;
2997 daemon->default_resolv.name = RESOLVFILE;
2998 daemon->resolv_files = &daemon->default_resolv;
2999 daemon->username = CHUSER;
3000 daemon->runfile = RUNFILE;
3001 daemon->dhcp_max = MAXLEASES;
3002 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
3003 daemon->edns_pktsz = EDNS_PKTSZ;
3004 daemon->log_fac = -1;
3005 add_txt("version.bind", "dnsmasq-" VERSION );
3006 add_txt("authors.bind", "Simon Kelley");
3007 add_txt("copyright.bind", COPYRIGHT);
3009 while (1)
3011 #ifdef HAVE_GETOPT_LONG
3012 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
3013 #else
3014 option = getopt(argc, argv, OPTSTRING);
3015 #endif
3017 if (option == -1)
3018 break;
3020 /* Copy optarg so that argv doesn't get changed */
3021 if (optarg)
3023 strncpy(buff, optarg, MAXDNAME);
3024 buff[MAXDNAME-1] = 0;
3025 arg = buff;
3027 else
3028 arg = NULL;
3030 /* command-line only stuff */
3031 if (option == LOPT_TEST)
3032 testmode = 1;
3033 else if (option == 'w')
3035 if (argc != 3 || strcmp(argv[2], "dhcp") != 0)
3036 do_usage();
3037 #ifdef HAVE_DHCP
3038 else
3039 display_opts();
3040 #endif
3041 exit(0);
3043 else if (option == 'v')
3045 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
3046 printf(_("Compile time options %s\n\n"), compile_opts);
3047 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
3048 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
3049 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
3050 exit(0);
3052 else if (option == 'C')
3054 conffile = opt_string_alloc(arg);
3055 nest++;
3057 else
3059 #ifdef HAVE_GETOPT_LONG
3060 errmess = one_opt(option, arg, _("try --help"), 0);
3061 #else
3062 errmess = one_opt(option, arg, _("try -w"), 0);
3063 #endif
3064 if (errmess)
3065 die(_("bad command line options: %s"), errmess, EC_BADCONF);
3069 if (conffile)
3070 one_file(conffile, nest, 0);
3072 /* port might not be known when the address is parsed - fill in here */
3073 if (daemon->servers)
3075 struct server *tmp;
3076 for (tmp = daemon->servers; tmp; tmp = tmp->next)
3077 if (!(tmp->flags & SERV_HAS_SOURCE))
3079 if (tmp->source_addr.sa.sa_family == AF_INET)
3080 tmp->source_addr.in.sin_port = htons(daemon->query_port);
3081 #ifdef HAVE_IPV6
3082 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3083 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
3084 #endif
3088 if (daemon->if_addrs)
3090 struct iname *tmp;
3091 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
3092 if (tmp->addr.sa.sa_family == AF_INET)
3093 tmp->addr.in.sin_port = htons(daemon->port);
3094 #ifdef HAVE_IPV6
3095 else if (tmp->addr.sa.sa_family == AF_INET6)
3096 tmp->addr.in6.sin6_port = htons(daemon->port);
3097 #endif /* IPv6 */
3100 /* only one of these need be specified: the other defaults to the host-name */
3101 if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
3103 struct mx_srv_record *mx;
3105 if (gethostname(buff, MAXDNAME) == -1)
3106 die(_("cannot get host-name: %s"), NULL, EC_MISC);
3108 for (mx = daemon->mxnames; mx; mx = mx->next)
3109 if (!mx->issrv && hostname_isequal(mx->name, buff))
3110 break;
3112 if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
3114 mx = opt_malloc(sizeof(struct mx_srv_record));
3115 mx->next = daemon->mxnames;
3116 mx->issrv = 0;
3117 mx->target = NULL;
3118 mx->name = opt_string_alloc(buff);
3119 daemon->mxnames = mx;
3122 if (!daemon->mxtarget)
3123 daemon->mxtarget = opt_string_alloc(buff);
3125 for (mx = daemon->mxnames; mx; mx = mx->next)
3126 if (!mx->issrv && !mx->target)
3127 mx->target = daemon->mxtarget;
3130 if (!(daemon->options & OPT_NO_RESOLV) &&
3131 daemon->resolv_files &&
3132 daemon->resolv_files->next &&
3133 (daemon->options & OPT_NO_POLL))
3134 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
3136 if (daemon->options & OPT_RESOLV_DOMAIN)
3138 char *line;
3139 FILE *f;
3141 if ((daemon->options & OPT_NO_RESOLV) ||
3142 !daemon->resolv_files ||
3143 (daemon->resolv_files)->next)
3144 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
3146 if (!(f = fopen((daemon->resolv_files)->name, "r")))
3147 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
3149 while ((line = fgets(buff, MAXDNAME, f)))
3151 char *token = strtok(line, " \t\n\r");
3153 if (!token || strcmp(token, "search") != 0)
3154 continue;
3156 if ((token = strtok(NULL, " \t\n\r")) &&
3157 (daemon->domain_suffix = canonicalise_opt(token)))
3158 break;
3161 fclose(f);
3163 if (!daemon->domain_suffix)
3164 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
3167 if (daemon->domain_suffix)
3169 /* add domain for any srv record without one. */
3170 struct mx_srv_record *srv;
3172 for (srv = daemon->mxnames; srv; srv = srv->next)
3173 if (srv->issrv &&
3174 strchr(srv->name, '.') &&
3175 strchr(srv->name, '.') == strrchr(srv->name, '.'))
3177 strcpy(buff, srv->name);
3178 strcat(buff, ".");
3179 strcat(buff, daemon->domain_suffix);
3180 free(srv->name);
3181 srv->name = opt_string_alloc(buff);
3184 else if (daemon->options & OPT_DHCP_FQDN)
3185 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
3187 if (testmode)
3189 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
3190 exit(0);