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