]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/option.c
Typo.
[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 {
4cb1b320 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;
814
832af0ba
SK
815 if (is_hex && digs > 1)
816 {
817 new->len = digs;
824af85b 818 new->val = opt_malloc(new->len);
73a08a24
SK
819 parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
820 new->flags |= DHOPT_HEX;
832af0ba
SK
821 }
822 else if (is_dec)
823 {
824 int i, val = atoi(comma);
825 /* assume numeric arg is 1 byte except for
826 options where it is known otherwise.
827 For vendor class option, we have to hack. */
f2621c7f
SK
828 if (opt_len != 0)
829 new->len = opt_len;
830 else if (val & 0xffff0000)
831 new->len = 4;
832 else if (val & 0xff00)
833 new->len = 2;
834 else
835 new->len = 1;
836
832af0ba
SK
837 if (lenchar == 'b')
838 new->len = 1;
839 else if (lenchar == 's')
840 new->len = 2;
841 else if (lenchar == 'i')
842 new->len = 4;
f2621c7f 843
824af85b 844 new->val = opt_malloc(new->len);
832af0ba
SK
845 for (i=0; i<new->len; i++)
846 new->val[i] = val>>((new->len - i - 1)*8);
847 }
4cb1b320 848 else if (is_addr && !is6)
832af0ba
SK
849 {
850 struct in_addr in;
851 unsigned char *op;
852 char *slash;
853 /* max length of address/subnet descriptor is five bytes,
854 add one for the option 120 enc byte too */
824af85b 855 new->val = op = opt_malloc((5 * addrs) + 1);
6b01084f
SK
856 new->flags |= DHOPT_ADDR;
857
572b41eb
SK
858 if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
859 new->opt == OPTION_SIP_SERVER)
832af0ba 860 {
6b01084f
SK
861 *(op++) = 1; /* RFC 3361 "enc byte" */
862 new->flags &= ~DHOPT_ADDR;
832af0ba
SK
863 }
864 while (addrs--)
865 {
866 cp = comma;
f2621c7f 867 comma = split(cp);
73a08a24 868 slash = split_chr(cp, '/');
832af0ba
SK
869 in.s_addr = inet_addr(cp);
870 if (!slash)
871 {
872 memcpy(op, &in, INADDRSZ);
873 op += INADDRSZ;
874 }
875 else
876 {
877 unsigned char *p = (unsigned char *)&in;
878 int netsize = atoi(slash);
879 *op++ = netsize;
880 if (netsize > 0)
881 *op++ = *p++;
882 if (netsize > 8)
883 *op++ = *p++;
884 if (netsize > 16)
885 *op++ = *p++;
886 if (netsize > 24)
887 *op++ = *p++;
888 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
889 }
890 }
891 new->len = op - new->val;
892 }
4cb1b320
SK
893 else if (is_addr6 && is6)
894 {
895 unsigned char *op;
896 new->val = op = opt_malloc(16 * addrs);
897 new->flags |= DHOPT_ADDR6;
898 while (addrs--)
899 {
900 cp = comma;
901 comma = split(cp);
902
903 /* check for [1234::7] */
904 if (*cp == '[')
905 cp++;
906 if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
907 cp[strlen(cp)-1] = 0;
908
909 if (inet_pton(AF_INET6, cp, op))
910 {
911 op += IN6ADDRSZ;
912 continue;
913 }
914
c4a7f90e 915 ret_err(_("bad IPv6 address"));
4cb1b320
SK
916 }
917 new->len = op - new->val;
918 }
f2621c7f 919 else if (is_string)
832af0ba 920 {
4cb1b320 921 /* text arg */
572b41eb 922 if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
4cb1b320 923 !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
832af0ba
SK
924 {
925 /* dns search, RFC 3397, or SIP, RFC 3361 */
926 unsigned char *q, *r, *tail;
824af85b 927 unsigned char *p, *m = NULL, *newp;
832af0ba 928 size_t newlen, len = 0;
572b41eb 929 int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
832af0ba
SK
930
931 arg = comma;
f2621c7f 932 comma = split(arg);
832af0ba
SK
933
934 while (arg && *arg)
935 {
c52e1897
SK
936 char *in, *dom = NULL;
937 size_t domlen = 1;
938 /* Allow "." as an empty domain */
939 if (strcmp (arg, ".") != 0)
832af0ba 940 {
c52e1897 941 if (!(dom = canonicalise_opt(arg)))
c4a7f90e
SK
942 ret_err(_("bad domain in dhcp-option"));
943
c52e1897 944 domlen = strlen(dom) + 2;
832af0ba 945 }
c52e1897
SK
946
947 newp = opt_malloc(len + domlen + header_size);
824af85b 948 if (m)
c52e1897
SK
949 {
950 memcpy(newp, m, header_size + len);
951 free(m);
952 }
824af85b 953 m = newp;
832af0ba
SK
954 p = m + header_size;
955 q = p + len;
956
957 /* add string on the end in RFC1035 format */
c52e1897 958 for (in = dom; in && *in;)
832af0ba
SK
959 {
960 unsigned char *cp = q++;
961 int j;
c52e1897
SK
962 for (j = 0; *in && (*in != '.'); in++, j++)
963 *q++ = *in;
832af0ba 964 *cp = j;
c52e1897
SK
965 if (*in)
966 in++;
832af0ba
SK
967 }
968 *q++ = 0;
1f15b81d 969 free(dom);
c52e1897 970
832af0ba
SK
971 /* Now tail-compress using earlier names. */
972 newlen = q - p;
973 for (tail = p + len; *tail; tail += (*tail) + 1)
974 for (r = p; r - p < (int)len; r += (*r) + 1)
975 if (strcmp((char *)r, (char *)tail) == 0)
976 {
977 PUTSHORT((r - p) | 0xc000, tail);
978 newlen = tail - p;
979 goto end;
980 }
981 end:
982 len = newlen;
983
984 arg = comma;
f2621c7f 985 comma = split(arg);
832af0ba
SK
986 }
987
988 /* RFC 3361, enc byte is zero for names */
572b41eb 989 if (new->opt == OPTION_SIP_SERVER)
832af0ba
SK
990 m[0] = 0;
991 new->len = (int) len + header_size;
992 new->val = m;
993 }
4cb1b320
SK
994#ifdef HAVE_DHCP6
995 else if (comma && (opt_len & OT_CSTRING))
996 {
997 /* length fields are two bytes so need 16 bits for each string */
40ef23b5 998 int i, commas = 1;
4cb1b320
SK
999 unsigned char *p, *newp;
1000
40ef23b5 1001 for (i = 0; comma[i]; i++)
4cb1b320
SK
1002 if (comma[i] == ',')
1003 commas++;
1004
1005 newp = opt_malloc(strlen(comma)+(2*commas));
1006 p = newp;
1007 arg = comma;
1008 comma = split(arg);
1009
1010 while (arg && *arg)
1011 {
1012 u16 len = strlen(arg);
18f0fb05 1013 unhide_metas(arg);
4cb1b320
SK
1014 PUTSHORT(len, p);
1015 memcpy(p, arg, len);
1016 p += len;
1017
1018 arg = comma;
1019 comma = split(arg);
1020 }
1021
1022 new->val = newp;
1023 new->len = p - newp;
1024 }
1025 else if (comma && (opt_len & OT_RFC1035_NAME))
1026 {
18f0fb05
SK
1027 unsigned char *p = NULL, *newp, *end;
1028 int len = 0;
4cb1b320
SK
1029 arg = comma;
1030 comma = split(arg);
1031
1032 while (arg && *arg)
1033 {
18f0fb05
SK
1034 char *dom = canonicalise_opt(arg);
1035 if (!dom)
c4a7f90e
SK
1036 ret_err(_("bad domain in dhcp-option"));
1037
18f0fb05
SK
1038 newp = opt_malloc(len + strlen(dom) + 2);
1039
1040 if (p)
1041 {
1042 memcpy(newp, p, len);
1043 free(p);
1044 }
4cb1b320 1045
18f0fb05
SK
1046 p = newp;
1047 end = do_rfc1035_name(p + len, dom);
1048 *end++ = 0;
1049 len = end - p;
1050 free(dom);
1051
4cb1b320
SK
1052 arg = comma;
1053 comma = split(arg);
1054 }
1055
18f0fb05
SK
1056 new->val = p;
1057 new->len = len;
4cb1b320
SK
1058 }
1059#endif
832af0ba
SK
1060 else
1061 {
1062 new->len = strlen(comma);
1063 /* keep terminating zero on string */
824af85b 1064 new->val = (unsigned char *)opt_string_alloc(comma);
832af0ba
SK
1065 new->flags |= DHOPT_STRING;
1066 }
1067 }
1068 }
1069
4cb1b320
SK
1070 if (!is6 &&
1071 ((new->len > 255) ||
316e2730 1072 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
4cb1b320 1073 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
c4a7f90e 1074 ret_err(_("dhcp-option too long"));
832af0ba 1075
c4a7f90e 1076 if (flags == DHOPT_MATCH)
824af85b 1077 {
c4a7f90e
SK
1078 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
1079 !new->netid ||
1080 new->netid->next)
1081 ret_err(_("illegal dhcp-match"));
1082
1083 if (is6)
4cb1b320 1084 {
c4a7f90e
SK
1085 new->next = daemon->dhcp_match6;
1086 daemon->dhcp_match6 = new;
4cb1b320
SK
1087 }
1088 else
73a08a24 1089 {
c4a7f90e
SK
1090 new->next = daemon->dhcp_match;
1091 daemon->dhcp_match = new;
73a08a24 1092 }
824af85b 1093 }
c4a7f90e
SK
1094 else if (is6)
1095 {
1096 new->next = daemon->dhcp_opts6;
1097 daemon->dhcp_opts6 = new;
1098 }
1099 else
1100 {
1101 new->next = daemon->dhcp_opts;
1102 daemon->dhcp_opts = new;
1103 }
1104
1105 return 1;
832af0ba
SK
1106}
1107
7622fc06 1108#endif
832af0ba 1109
28866e95
SK
1110void set_option_bool(unsigned int opt)
1111{
1112 if (opt < 32)
1113 daemon->options |= 1u << opt;
1114 else
1115 daemon->options2 |= 1u << (opt - 32);
1116}
1117
2b5bae9a
SK
1118void reset_option_bool(unsigned int opt)
1119{
1120 if (opt < 32)
1121 daemon->options &= ~(1u << opt);
1122 else
1123 daemon->options2 &= ~(1u << (opt - 32));
1124}
1125
c4a7f90e 1126static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
849a8357
SK
1127{
1128 int i;
c4a7f90e 1129 char *comma;
b8187c80 1130
832af0ba 1131 if (option == '?')
c4a7f90e 1132 ret_err(gen_err);
832af0ba 1133
1a6bca81
SK
1134 for (i=0; usage[i].opt != 0; i++)
1135 if (usage[i].opt == option)
849a8357 1136 {
1a6bca81
SK
1137 int rept = usage[i].rept;
1138
28866e95 1139 if (command_line)
1a6bca81
SK
1140 {
1141 /* command line */
1142 if (rept == ARG_USED_CL)
c4a7f90e 1143 ret_err(_("illegal repeated flag"));
1a6bca81
SK
1144 if (rept == ARG_ONE)
1145 usage[i].rept = ARG_USED_CL;
1146 }
1147 else
1148 {
1149 /* allow file to override command line */
1150 if (rept == ARG_USED_FILE)
c4a7f90e 1151 ret_err(_("illegal repeated keyword"));
1a6bca81
SK
1152 if (rept == ARG_USED_CL || rept == ARG_ONE)
1153 usage[i].rept = ARG_USED_FILE;
1154 }
1155
1156 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1157 {
28866e95 1158 set_option_bool(rept);
c4a7f90e 1159 return 1;
1a6bca81
SK
1160 }
1161
1162 break;
849a8357 1163 }
1a6bca81 1164
849a8357
SK
1165 switch (option)
1166 {
f2621c7f 1167 case 'C': /* --conf-file */
849a8357 1168 {
824af85b 1169 char *file = opt_string_alloc(arg);
849a8357 1170 if (file)
9009d746 1171 {
28866e95 1172 one_file(file, 0);
9009d746
SK
1173 free(file);
1174 }
849a8357
SK
1175 break;
1176 }
1177
f2621c7f 1178 case '7': /* --conf-dir */
849a8357
SK
1179 {
1180 DIR *dir_stream;
1181 struct dirent *ent;
1182 char *directory, *path;
1f15b81d
SK
1183 struct list {
1184 char *suffix;
1185 struct list *next;
1186 } *ignore_suffix = NULL, *li;
849a8357 1187
1f15b81d 1188 comma = split(arg);
824af85b 1189 if (!(directory = opt_string_alloc(arg)))
849a8357
SK
1190 break;
1191
1f15b81d
SK
1192 for (arg = comma; arg; arg = comma)
1193 {
1194 comma = split(arg);
1195 li = opt_malloc(sizeof(struct list));
1196 li->next = ignore_suffix;
1197 ignore_suffix = li;
1198 /* Have to copy: buffer is overwritten */
1199 li->suffix = opt_string_alloc(arg);
1200 };
1201
849a8357 1202 if (!(dir_stream = opendir(directory)))
5aabfc78 1203 die(_("cannot access directory %s: %s"), directory, EC_FILE);
1f15b81d 1204
849a8357 1205 while ((ent = readdir(dir_stream)))
9e4abcb5 1206 {
7622fc06 1207 size_t len = strlen(ent->d_name);
849a8357 1208 struct stat buf;
1f15b81d
SK
1209
1210 /* ignore emacs backups and dotfiles */
7622fc06
SK
1211 if (len == 0 ||
1212 ent->d_name[len - 1] == '~' ||
849a8357
SK
1213 (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1214 ent->d_name[0] == '.')
1215 continue;
7622fc06 1216
1f15b81d
SK
1217 for (li = ignore_suffix; li; li = li->next)
1218 {
1219 /* check for proscribed suffices */
1220 size_t ls = strlen(li->suffix);
1221 if (len > ls &&
1222 strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1223 break;
1224 }
1225 if (li)
1226 continue;
1227
824af85b 1228 path = opt_malloc(strlen(directory) + len + 2);
849a8357
SK
1229 strcpy(path, directory);
1230 strcat(path, "/");
1231 strcat(path, ent->d_name);
7622fc06 1232
849a8357 1233 if (stat(path, &buf) == -1)
5aabfc78 1234 die(_("cannot access %s: %s"), path, EC_FILE);
849a8357
SK
1235 /* only reg files allowed. */
1236 if (!S_ISREG(buf.st_mode))
1237 continue;
1238
28866e95
SK
1239 /* files must be readable */
1240 one_file(path, 0);
849a8357 1241 free(path);
9e4abcb5 1242 }
849a8357
SK
1243
1244 closedir(dir_stream);
9009d746 1245 free(directory);
1f15b81d
SK
1246 for(; ignore_suffix; ignore_suffix = li)
1247 {
1248 li = ignore_suffix->next;
1249 free(ignore_suffix->suffix);
1250 free(ignore_suffix);
1251 }
1252
849a8357
SK
1253 break;
1254 }
1255
f2621c7f
SK
1256 case '8': /* --log-facility */
1257 /* may be a filename */
8ef5ada2 1258 if (strchr(arg, '/') || strcmp (arg, "-") == 0)
824af85b 1259 daemon->log_file = opt_string_alloc(arg);
849a8357 1260 else
f2621c7f 1261 {
572b41eb 1262#ifdef __ANDROID__
c4a7f90e 1263 ret_err(_("setting log facility is not possible under Android"));
572b41eb 1264#else
f2621c7f
SK
1265 for (i = 0; facilitynames[i].c_name; i++)
1266 if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1267 break;
1268
1269 if (facilitynames[i].c_name)
1270 daemon->log_fac = facilitynames[i].c_val;
1271 else
c4a7f90e 1272 ret_err(_("bad log facility"));
572b41eb 1273#endif
849a8357
SK
1274 }
1275 break;
1276
f2621c7f 1277 case 'x': /* --pid-file */
824af85b 1278 daemon->runfile = opt_string_alloc(arg);
849a8357 1279 break;
5aabfc78 1280
f2621c7f 1281 case 'r': /* --resolv-file */
849a8357 1282 {
824af85b 1283 char *name = opt_string_alloc(arg);
849a8357
SK
1284 struct resolvc *new, *list = daemon->resolv_files;
1285
1286 if (list && list->is_default)
1287 {
1288 /* replace default resolv file - possibly with nothing */
1289 if (name)
9e4abcb5 1290 {
849a8357
SK
1291 list->is_default = 0;
1292 list->name = name;
9e4abcb5 1293 }
849a8357
SK
1294 else
1295 list = NULL;
1296 }
1297 else if (name)
1298 {
824af85b 1299 new = opt_malloc(sizeof(struct resolvc));
849a8357
SK
1300 new->next = list;
1301 new->name = name;
1302 new->is_default = 0;
1303 new->mtime = 0;
1304 new->logged = 0;
1305 list = new;
1306 }
1307 daemon->resolv_files = list;
1308 break;
1309 }
1310
f2621c7f 1311 case 'm': /* --mx-host */
849a8357
SK
1312 {
1313 int pref = 1;
1314 struct mx_srv_record *new;
1f15b81d
SK
1315 char *name, *target = NULL;
1316
f2621c7f 1317 if ((comma = split(arg)))
849a8357
SK
1318 {
1319 char *prefstr;
1f15b81d 1320 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
c4a7f90e 1321 ret_err(_("bad MX preference"));
849a8357
SK
1322 }
1323
1f15b81d
SK
1324 if (!(name = canonicalise_opt(arg)) ||
1325 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 1326 ret_err(_("bad MX name"));
1f15b81d 1327
824af85b 1328 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
1329 new->next = daemon->mxnames;
1330 daemon->mxnames = new;
1331 new->issrv = 0;
1f15b81d
SK
1332 new->name = name;
1333 new->target = target; /* may be NULL */
849a8357
SK
1334 new->weight = pref;
1335 break;
1336 }
1337
f2621c7f 1338 case 't': /* --mx-target */
1f15b81d 1339 if (!(daemon->mxtarget = canonicalise_opt(arg)))
c4a7f90e 1340 ret_err(_("bad MX target"));
849a8357 1341 break;
7622fc06
SK
1342
1343#ifdef HAVE_DHCP
f2621c7f 1344 case 'l': /* --dhcp-leasefile */
824af85b 1345 daemon->lease_file = opt_string_alloc(arg);
849a8357
SK
1346 break;
1347
c72daea8
SK
1348 /* Sorry about the gross pre-processor abuse */
1349 case '6': /* --dhcp-script */
1350 case LOPT_LUASCRIPT: /* --dhcp-luascript */
1f15b81d 1351# if defined(NO_FORK)
c4a7f90e 1352 ret_err(_("cannot run scripts under uClinux"));
1f15b81d 1353# elif !defined(HAVE_SCRIPT)
c4a7f90e 1354 ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
7622fc06 1355# else
c72daea8
SK
1356 if (option == LOPT_LUASCRIPT)
1357# if !defined(HAVE_LUASCRIPT)
c4a7f90e 1358 ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
c72daea8
SK
1359# else
1360 daemon->luascript = opt_string_alloc(arg);
1361# endif
1362 else
1363 daemon->lease_change_command = opt_string_alloc(arg);
7622fc06 1364# endif
849a8357 1365 break;
c72daea8 1366#endif /* HAVE_DHCP */
7622fc06 1367
28866e95
SK
1368 case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1369 case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
f2621c7f 1370 case 'H': /* --addn-hosts */
849a8357 1371 {
824af85b 1372 struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
849a8357 1373 static int hosts_index = 1;
824af85b 1374 new->fname = opt_string_alloc(arg);
849a8357 1375 new->index = hosts_index++;
7622fc06 1376 new->flags = 0;
28866e95
SK
1377 if (option == 'H')
1378 {
1379 new->next = daemon->addn_hosts;
1380 daemon->addn_hosts = new;
1381 }
1382 else if (option == LOPT_DHCP_HOST)
1383 {
1384 new->next = daemon->dhcp_hosts_file;
1385 daemon->dhcp_hosts_file = new;
1386 }
1387 else if (option == LOPT_DHCP_OPTS)
1388 {
1389 new->next = daemon->dhcp_opts_file;
1390 daemon->dhcp_opts_file = new;
1391 }
849a8357
SK
1392 break;
1393 }
1394
f2621c7f 1395 case 's': /* --domain */
849a8357 1396 if (strcmp (arg, "#") == 0)
28866e95 1397 set_option_bool(OPT_RESOLV_DOMAIN);
849a8357 1398 else
9009d746 1399 {
1f15b81d 1400 char *d;
9009d746 1401 comma = split(arg);
1f15b81d 1402 if (!(d = canonicalise_opt(arg)))
c4a7f90e 1403 ret_err(gen_err);
9009d746
SK
1404 else
1405 {
9009d746
SK
1406 if (comma)
1407 {
1408 struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
28866e95
SK
1409 char *netpart;
1410
9009d746 1411 unhide_metas(comma);
28866e95 1412 if ((netpart = split_chr(comma, '/')))
9009d746 1413 {
d74942a0
SK
1414 int msize;
1415
28866e95 1416 arg = split(netpart);
d74942a0 1417 if (!atoi_check(netpart, &msize))
c4a7f90e 1418 ret_err(gen_err);
d74942a0 1419 else if (inet_pton(AF_INET, comma, &new->start))
9009d746 1420 {
d74942a0
SK
1421 int mask = (1 << (32 - msize)) - 1;
1422 new->is6 = 0;
9009d746
SK
1423 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1424 new->end.s_addr = new->start.s_addr | htonl(mask);
28866e95
SK
1425 if (arg)
1426 {
1427 /* generate the equivalent of
1428 local=/<domain>/
1429 local=/xxx.yyy.zzz.in-addr.arpa/ */
1430
1431 if (strcmp(arg, "local") != 0 ||
1432 (msize != 8 && msize != 16 && msize != 24))
c4a7f90e 1433 ret_err(gen_err);
28866e95
SK
1434 else
1435 {
1436 struct server *serv = opt_malloc(sizeof(struct server));
1437 in_addr_t a = ntohl(new->start.s_addr) >> 8;
1438 char *p;
1439
1440 memset(serv, 0, sizeof(struct server));
1441 serv->domain = d;
1442 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1443 serv->next = daemon->servers;
1444 daemon->servers = serv;
1445
1446 serv = opt_malloc(sizeof(struct server));
1447 memset(serv, 0, sizeof(struct server));
1448 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1449
1450 if (msize == 24)
1451 p += sprintf(p, "%d.", a & 0xff);
1452 a = a >> 8;
1453 if (msize != 8)
1454 p += sprintf(p, "%d.", a & 0xff);
1455 a = a >> 8;
1456 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
1457
1458 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1459 serv->next = daemon->servers;
1460 daemon->servers = serv;
1461 }
1462 }
9009d746 1463 }
d74942a0
SK
1464#ifdef HAVE_IPV6
1465 else if (inet_pton(AF_INET6, comma, &new->start6))
1466 {
1467 u64 mask = (1LLU << (128 - msize)) - 1LLU;
1468 u64 addrpart = addr6part(&new->start6);
1469 new->is6 = 1;
1470
1471 /* prefix==64 overflows the mask calculation above */
1472 if (msize == 64)
1473 mask = (u64)-1LL;
1474
1475 new->end6 = new->start6;
1476 setaddr6part(&new->start6, addrpart & ~mask);
1477 setaddr6part(&new->end6, addrpart | mask);
1478
1479 if (msize < 64)
c4a7f90e 1480 ret_err(gen_err);
d74942a0
SK
1481 else if (arg)
1482 {
1483 /* generate the equivalent of
1484 local=/<domain>/
1485 local=/xxx.yyy.zzz.ip6.arpa/ */
1486
ceae00dd 1487 if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
c4a7f90e 1488 ret_err(gen_err);
d74942a0
SK
1489 else
1490 {
1491 struct server *serv = opt_malloc(sizeof(struct server));
d74942a0 1492 char *p;
ceae00dd 1493
d74942a0
SK
1494 memset(serv, 0, sizeof(struct server));
1495 serv->domain = d;
1496 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1497 serv->next = daemon->servers;
1498 daemon->servers = serv;
1499
1500 serv = opt_malloc(sizeof(struct server));
1501 memset(serv, 0, sizeof(struct server));
1502 p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
1503
1504 for (i = msize-1; i >= 0; i -= 4)
1505 {
1506 int dig = ((unsigned char *)&new->start6)[i>>3];
1507 p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
1508 }
1509 p += sprintf(p, "ip6.arpa");
1510
1511 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
1512 serv->next = daemon->servers;
1513 daemon->servers = serv;
1514 }
1515 }
1516 }
1517#endif
1518 else
c4a7f90e 1519 ret_err(gen_err);
9009d746 1520 }
d74942a0 1521 else
9009d746 1522 {
d74942a0
SK
1523 arg = split(comma);
1524 if (inet_pton(AF_INET, comma, &new->start))
1525 {
1526 new->is6 = 0;
1527 if (!arg)
1528 new->end.s_addr = new->start.s_addr;
1529 else if (!inet_pton(AF_INET, arg, &new->end))
c4a7f90e 1530 ret_err(gen_err);
d74942a0
SK
1531 }
1532#ifdef HAVE_IPV6
1533 else if (inet_pton(AF_INET6, comma, &new->start6))
1534 {
1535 new->is6 = 1;
1536 if (!arg)
1537 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
1538 else if (!inet_pton(AF_INET6, arg, &new->end6))
c4a7f90e 1539 ret_err(gen_err);
d74942a0
SK
1540 }
1541#endif
1542 else
c4a7f90e 1543 ret_err(gen_err);
d74942a0 1544 }
2307eac6
SK
1545
1546 new->domain = d;
1547 new->next = daemon->cond_domain;
1548 daemon->cond_domain = new;
9009d746
SK
1549 }
1550 else
1551 daemon->domain_suffix = d;
1552 }
1553 }
849a8357
SK
1554 break;
1555
f2621c7f 1556 case 'u': /* --user */
824af85b 1557 daemon->username = opt_string_alloc(arg);
849a8357
SK
1558 break;
1559
f2621c7f 1560 case 'g': /* --group */
824af85b 1561 daemon->groupname = opt_string_alloc(arg);
1a6bca81 1562 daemon->group_set = 1;
849a8357 1563 break;
9e038946 1564
7622fc06 1565#ifdef HAVE_DHCP
9e038946
SK
1566 case LOPT_SCRIPTUSR: /* --scriptuser */
1567 daemon->scriptuser = opt_string_alloc(arg);
1568 break;
7622fc06 1569#endif
849a8357 1570
f2621c7f 1571 case 'i': /* --interface */
849a8357 1572 do {
824af85b 1573 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1574 comma = split(arg);
849a8357
SK
1575 new->next = daemon->if_names;
1576 daemon->if_names = new;
1577 /* new->name may be NULL if someone does
1578 "interface=" to disable all interfaces except loop. */
824af85b 1579 new->name = opt_string_alloc(arg);
4ce4f377 1580 new->used = 0;
849a8357
SK
1581 arg = comma;
1582 } while (arg);
1583 break;
1584
f2621c7f
SK
1585 case 'I': /* --except-interface */
1586 case '2': /* --no-dhcp-interface */
849a8357 1587 do {
824af85b 1588 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1589 comma = split(arg);
824af85b 1590 new->name = opt_string_alloc(arg);
849a8357
SK
1591 if (option == 'I')
1592 {
1593 new->next = daemon->if_except;
1594 daemon->if_except = new;
1595 }
1596 else
1597 {
1598 new->next = daemon->dhcp_except;
1599 daemon->dhcp_except = new;
1600 }
1601 arg = comma;
1602 } while (arg);
1603 break;
1604
f2621c7f 1605 case 'B': /* --bogus-nxdomain */
849a8357
SK
1606 {
1607 struct in_addr addr;
1608 unhide_metas(arg);
1609 if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1610 {
824af85b 1611 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
849a8357
SK
1612 baddr->next = daemon->bogus_addr;
1613 daemon->bogus_addr = baddr;
1614 baddr->addr = addr;
1615 }
1616 else
c4a7f90e 1617 ret_err(gen_err); /* error */
849a8357
SK
1618 break;
1619 }
1620
f2621c7f 1621 case 'a': /* --listen-address */
849a8357 1622 do {
824af85b 1623 struct iname *new = opt_malloc(sizeof(struct iname));
f2621c7f 1624 comma = split(arg);
849a8357
SK
1625 unhide_metas(arg);
1626 new->next = daemon->if_addrs;
1627 if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1628 {
1629 new->addr.sa.sa_family = AF_INET;
1630#ifdef HAVE_SOCKADDR_SA_LEN
1631 new->addr.in.sin_len = sizeof(new->addr.in);
1632#endif
1633 }
1634#ifdef HAVE_IPV6
1635 else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1636 {
1637 new->addr.sa.sa_family = AF_INET6;
1638 new->addr.in6.sin6_flowinfo = 0;
1639 new->addr.in6.sin6_scope_id = 0;
1640#ifdef HAVE_SOCKADDR_SA_LEN
1641 new->addr.in6.sin6_len = sizeof(new->addr.in6);
1642#endif
1643 }
1644#endif
1645 else
c4a7f90e 1646 ret_err(gen_err);
4ce4f377
SK
1647
1648 new->used = 0;
849a8357
SK
1649 daemon->if_addrs = new;
1650 arg = comma;
1651 } while (arg);
1652 break;
1653
8ef5ada2
SK
1654 case 'S': /* --server */
1655 case LOPT_LOCAL: /* --local */
1656 case 'A': /* --address */
1657 case LOPT_NO_REBIND: /* --rebind-domain-ok */
849a8357
SK
1658 {
1659 struct server *serv, *newlist = NULL;
1660
1661 unhide_metas(arg);
1662
8ef5ada2 1663 if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
849a8357 1664 {
8ef5ada2
SK
1665 int rebind = !(*arg == '/');
1666 char *end = NULL;
1667 if (!rebind)
1668 arg++;
1669 while (rebind || (end = split_chr(arg, '/')))
fd9fa481 1670 {
849a8357 1671 char *domain = NULL;
8ef5ada2
SK
1672 /* elide leading dots - they are implied in the search algorithm */
1673 while (*arg == '.') arg++;
849a8357
SK
1674 /* # matches everything and becomes a zero length domain string */
1675 if (strcmp(arg, "#") == 0)
1676 domain = "";
1f15b81d 1677 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
849a8357 1678 option = '?';
824af85b
SK
1679 serv = opt_malloc(sizeof(struct server));
1680 memset(serv, 0, sizeof(struct server));
849a8357
SK
1681 serv->next = newlist;
1682 newlist = serv;
849a8357
SK
1683 serv->domain = domain;
1684 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
73a08a24 1685 arg = end;
8ef5ada2
SK
1686 if (rebind)
1687 break;
fd9fa481 1688 }
849a8357 1689 if (!newlist)
c4a7f90e 1690 ret_err(gen_err);
849a8357
SK
1691 }
1692 else
1693 {
824af85b
SK
1694 newlist = opt_malloc(sizeof(struct server));
1695 memset(newlist, 0, sizeof(struct server));
849a8357
SK
1696 }
1697
1698 if (option == 'A')
1699 {
1700 newlist->flags |= SERV_LITERAL_ADDRESS;
1701 if (!(newlist->flags & SERV_TYPE))
c4a7f90e 1702 ret_err(gen_err);
849a8357 1703 }
8ef5ada2
SK
1704 else if (option == LOPT_NO_REBIND)
1705 newlist->flags |= SERV_NO_REBIND;
849a8357
SK
1706
1707 if (!arg || !*arg)
1708 {
8ef5ada2
SK
1709 if (!(newlist->flags & SERV_NO_REBIND))
1710 newlist->flags |= SERV_NO_ADDR; /* no server */
1711 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 1712 ret_err(gen_err);
8ef5ada2
SK
1713 }
1714
1715 else if (strcmp(arg, "#") == 0)
1716 {
1717 newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
849a8357 1718 if (newlist->flags & SERV_LITERAL_ADDRESS)
c4a7f90e 1719 ret_err(gen_err);
849a8357
SK
1720 }
1721 else
1722 {
1723 int source_port = 0, serv_port = NAMESERVER_PORT;
1724 char *portno, *source;
7de060b0
SK
1725#ifdef HAVE_IPV6
1726 int scope_index = 0;
1727 char *scope_id;
1728#endif
849a8357 1729
73a08a24
SK
1730 if ((source = split_chr(arg, '@')) && /* is there a source. */
1731 (portno = split_chr(source, '#')) &&
1732 !atoi_check16(portno, &source_port))
c4a7f90e 1733 ret_err(_("bad port"));
73a08a24
SK
1734
1735 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1736 !atoi_check16(portno, &serv_port))
c4a7f90e 1737 ret_err(_("bad port"));
849a8357 1738
7de060b0
SK
1739#ifdef HAVE_IPV6
1740 scope_id = split_chr(arg, '%');
1741#endif
1742
849a8357
SK
1743 if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
1744 {
1745 newlist->addr.in.sin_port = htons(serv_port);
1746 newlist->source_addr.in.sin_port = htons(source_port);
1747 newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
9e4abcb5 1748#ifdef HAVE_SOCKADDR_SA_LEN
849a8357 1749 newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
9e4abcb5 1750#endif
849a8357
SK
1751 if (source)
1752 {
824af85b 1753 newlist->flags |= SERV_HAS_SOURCE;
73a08a24 1754 if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
824af85b
SK
1755 {
1756#if defined(SO_BINDTODEVICE)
1757 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
316e2730 1758 strncpy(newlist->interface, source, IF_NAMESIZE - 1);
824af85b 1759#else
c4a7f90e 1760 ret_err(_("interface binding not supported"));
824af85b
SK
1761#endif
1762 }
9e4abcb5 1763 }
849a8357
SK
1764 else
1765 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
5aabfc78 1766 }
3d8df260 1767#ifdef HAVE_IPV6
849a8357
SK
1768 else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
1769 {
7de060b0 1770 if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
c4a7f90e 1771 ret_err(_("bad interface name"));
7de060b0 1772
849a8357 1773 newlist->addr.in6.sin6_port = htons(serv_port);
7de060b0 1774 newlist->addr.in6.sin6_scope_id = scope_index;
849a8357 1775 newlist->source_addr.in6.sin6_port = htons(source_port);
7de060b0 1776 newlist->source_addr.in6.sin6_scope_id = 0;
849a8357 1777 newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
7de060b0 1778 newlist->addr.in6.sin6_flowinfo = newlist->source_addr.in6.sin6_flowinfo = 0;
9e4abcb5 1779#ifdef HAVE_SOCKADDR_SA_LEN
849a8357 1780 newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
9e4abcb5 1781#endif
849a8357 1782 if (source)
9e4abcb5 1783 {
7de060b0
SK
1784 newlist->flags |= SERV_HAS_SOURCE;
1785 if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
824af85b 1786 {
73a08a24 1787#if defined(SO_BINDTODEVICE)
824af85b 1788 newlist->source_addr.in6.sin6_addr = in6addr_any;
316e2730 1789 strncpy(newlist->interface, source, IF_NAMESIZE - 1);
824af85b 1790#else
c4a7f90e 1791 ret_err(_("interface binding not supported"));
824af85b
SK
1792#endif
1793 }
9e4abcb5
SK
1794 }
1795 else
849a8357
SK
1796 newlist->source_addr.in6.sin6_addr = in6addr_any;
1797 }
1798#endif
1799 else
c4a7f90e 1800 ret_err(gen_err);
849a8357
SK
1801 }
1802
f2621c7f
SK
1803 serv = newlist;
1804 while (serv->next)
849a8357 1805 {
f2621c7f
SK
1806 serv->next->flags = serv->flags;
1807 serv->next->addr = serv->addr;
1808 serv->next->source_addr = serv->source_addr;
1809 serv = serv->next;
849a8357 1810 }
f2621c7f
SK
1811 serv->next = daemon->servers;
1812 daemon->servers = newlist;
849a8357
SK
1813 break;
1814 }
1815
f2621c7f 1816 case 'c': /* --cache-size */
849a8357
SK
1817 {
1818 int size;
1819
1820 if (!atoi_check(arg, &size))
c4a7f90e 1821 ret_err(gen_err);
849a8357
SK
1822 else
1823 {
1824 /* zero is OK, and means no caching. */
1825
1826 if (size < 0)
1827 size = 0;
1828 else if (size > 10000)
1829 size = 10000;
1830
1831 daemon->cachesize = size;
1832 }
1833 break;
1834 }
1835
f2621c7f 1836 case 'p': /* --port */
1ad24ae1 1837 if (!atoi_check16(arg, &daemon->port))
c4a7f90e 1838 ret_err(gen_err);
849a8357 1839 break;
208b65c5 1840
1a6bca81 1841 case LOPT_MINPORT: /* --min-port */
1ad24ae1 1842 if (!atoi_check16(arg, &daemon->min_port))
c4a7f90e 1843 ret_err(gen_err);
1a6bca81
SK
1844 break;
1845
f2621c7f 1846 case '0': /* --dns-forward-max */
208b65c5 1847 if (!atoi_check(arg, &daemon->ftabsize))
c4a7f90e 1848 ret_err(gen_err);
208b65c5
SK
1849 break;
1850
f2621c7f
SK
1851 case LOPT_MAX_LOGS: /* --log-async */
1852 daemon->max_logs = LOG_MAX; /* default */
1853 if (arg && !atoi_check(arg, &daemon->max_logs))
c4a7f90e 1854 ret_err(gen_err);
f2621c7f
SK
1855 else if (daemon->max_logs > 100)
1856 daemon->max_logs = 100;
1857 break;
1858
1859 case 'P': /* --edns-packet-max */
849a8357
SK
1860 {
1861 int i;
1862 if (!atoi_check(arg, &i))
c4a7f90e 1863 ret_err(gen_err);
849a8357
SK
1864 daemon->edns_pktsz = (unsigned short)i;
1865 break;
1866 }
1867
f2621c7f 1868 case 'Q': /* --query-port */
1ad24ae1 1869 if (!atoi_check16(arg, &daemon->query_port))
c4a7f90e 1870 ret_err(gen_err);
1a6bca81
SK
1871 /* if explicitly set to zero, use single OS ephemeral port
1872 and disable random ports */
1873 if (daemon->query_port == 0)
1874 daemon->osport = 1;
849a8357
SK
1875 break;
1876
824af85b
SK
1877 case 'T': /* --local-ttl */
1878 case LOPT_NEGTTL: /* --neg-ttl */
8ef5ada2 1879 case LOPT_MAXTTL: /* --max-ttl */
849a8357
SK
1880 {
1881 int ttl;
1882 if (!atoi_check(arg, &ttl))
c4a7f90e 1883 ret_err(gen_err);
824af85b
SK
1884 else if (option == LOPT_NEGTTL)
1885 daemon->neg_ttl = (unsigned long)ttl;
8ef5ada2
SK
1886 else if (option == LOPT_MAXTTL)
1887 daemon->max_ttl = (unsigned long)ttl;
849a8357
SK
1888 else
1889 daemon->local_ttl = (unsigned long)ttl;
1890 break;
1891 }
1892
7622fc06 1893#ifdef HAVE_DHCP
f2621c7f 1894 case 'X': /* --dhcp-lease-max */
849a8357 1895 if (!atoi_check(arg, &daemon->dhcp_max))
c4a7f90e 1896 ret_err(gen_err);
849a8357 1897 break;
7622fc06 1898#endif
849a8357 1899
7622fc06 1900#ifdef HAVE_TFTP
f2621c7f 1901 case LOPT_TFTP_MAX: /* --tftp-max */
832af0ba 1902 if (!atoi_check(arg, &daemon->tftp_max))
c4a7f90e 1903 ret_err(gen_err);
832af0ba
SK
1904 break;
1905
824af85b 1906 case LOPT_PREFIX: /* --tftp-prefix */
8ef5ada2
SK
1907 comma = split(arg);
1908 if (comma)
1909 {
1910 struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
1911 new->interface = opt_string_alloc(comma);
1912 new->prefix = opt_string_alloc(arg);
1913 new->next = daemon->if_prefix;
1914 daemon->if_prefix = new;
1915 }
1916 else
1917 daemon->tftp_prefix = opt_string_alloc(arg);
832af0ba
SK
1918 break;
1919
824af85b
SK
1920 case LOPT_TFTPPORTS: /* --tftp-port-range */
1921 if (!(comma = split(arg)) ||
1ad24ae1
SK
1922 !atoi_check16(arg, &daemon->start_tftp_port) ||
1923 !atoi_check16(comma, &daemon->end_tftp_port))
c4a7f90e 1924 ret_err(_("bad port range"));
824af85b
SK
1925
1926 if (daemon->start_tftp_port > daemon->end_tftp_port)
1927 {
1928 int tmp = daemon->start_tftp_port;
1929 daemon->start_tftp_port = daemon->end_tftp_port;
1930 daemon->end_tftp_port = tmp;
1931 }
1932
1933 break;
7622fc06 1934#endif
824af85b 1935
f2621c7f 1936 case LOPT_BRIDGE: /* --bridge-interface */
832af0ba 1937 {
824af85b 1938 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
316e2730 1939 if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
c4a7f90e 1940 ret_err(_("bad bridge-interface"));
832af0ba 1941
316e2730 1942 strcpy(new->iface, arg);
832af0ba
SK
1943 new->alias = NULL;
1944 new->next = daemon->bridges;
1945 daemon->bridges = new;
1946
1947 do {
f2621c7f
SK
1948 arg = comma;
1949 comma = split(arg);
316e2730 1950 if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
832af0ba 1951 {
824af85b 1952 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
832af0ba
SK
1953 b->next = new->alias;
1954 new->alias = b;
316e2730 1955 strcpy(b->iface, arg);
832af0ba
SK
1956 }
1957 } while (comma);
1958
1959 break;
1960 }
832af0ba 1961
7622fc06 1962#ifdef HAVE_DHCP
f2621c7f 1963 case 'F': /* --dhcp-range */
849a8357
SK
1964 {
1965 int k, leasepos = 2;
30cd9666 1966 char *cp, *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
824af85b 1967 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
849a8357 1968
52b92f4d 1969 memset (new, 0, sizeof(*new));
849a8357 1970 new->lease_time = DEFLEASE;
52b92f4d 1971
849a8357
SK
1972 if (!arg)
1973 {
1974 option = '?';
1975 break;
1976 }
1977
1978 while(1)
1979 {
1980 for (cp = arg; *cp; cp++)
52b92f4d
SK
1981 if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
1982 (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
1983 (*cp >='0' && *cp <= '9')))
849a8357
SK
1984 break;
1985
f2621c7f 1986 if (*cp != ',' && (comma = split(arg)))
849a8357 1987 {
8bc4cece 1988 if (is_tag_prefix(arg))
9e4abcb5 1989 {
824af85b
SK
1990 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
1991 tt->net = opt_string_alloc(arg+4);
849a8357
SK
1992 tt->next = new->filter;
1993 new->filter = tt;
9e4abcb5
SK
1994 }
1995 else
1996 {
849a8357 1997 if (new->netid.net)
c4a7f90e 1998 ret_err(_("only one tag allowed"));
8ef5ada2
SK
1999 else if (strstr(arg, "set:") == arg)
2000 new->netid.net = opt_string_alloc(arg+4);
9e4abcb5 2001 else
824af85b 2002 new->netid.net = opt_string_alloc(arg);
9e4abcb5 2003 }
f2621c7f 2004 arg = comma;
9e4abcb5 2005 }
849a8357 2006 else
9e4abcb5 2007 {
849a8357 2008 a[0] = arg;
9e4abcb5
SK
2009 break;
2010 }
849a8357
SK
2011 }
2012
30cd9666 2013 for (k = 1; k < 7; k++)
f2621c7f
SK
2014 if (!(a[k] = split(a[k-1])))
2015 break;
849a8357 2016
52b92f4d 2017 if (k < 2)
c4a7f90e
SK
2018 ret_err(_("bad dhcp-range"));
2019
2020 if (inet_pton(AF_INET, a[0], &new->start))
849a8357 2021 {
52b92f4d
SK
2022 new->next = daemon->dhcp;
2023 daemon->dhcp = new;
30cd9666 2024 new->end = new->start;
52b92f4d 2025 if (strcmp(a[1], "static") == 0)
30cd9666 2026 new->flags |= CONTEXT_STATIC;
52b92f4d 2027 else if (strcmp(a[1], "proxy") == 0)
30cd9666
SK
2028 new->flags |= CONTEXT_PROXY;
2029 else if (!inet_pton(AF_INET, a[1], &new->end))
c4a7f90e 2030 ret_err(_("bad dhcp-range"));
52b92f4d
SK
2031
2032 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
2033 {
2034 struct in_addr tmp = new->start;
2035 new->start = new->end;
2036 new->end = tmp;
2037 }
2038
c4a7f90e 2039 if (k >= 3 && strchr(a[2], '.') &&
52b92f4d
SK
2040 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
2041 {
2042 new->flags |= CONTEXT_NETMASK;
2043 leasepos = 3;
2044 if (!is_same_net(new->start, new->end, new->netmask))
c4a7f90e 2045 ret_err(_("inconsistent DHCP range"));
52b92f4d
SK
2046 }
2047
2048 if (k >= 4 && strchr(a[3], '.') &&
2049 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
2050 {
2051 new->flags |= CONTEXT_BRDCAST;
2052 leasepos = 4;
2053 }
849a8357 2054 }
52b92f4d
SK
2055#ifdef HAVE_DHCP6
2056 else if (inet_pton(AF_INET6, a[0], &new->start6))
849a8357 2057 {
52b92f4d 2058 new->prefix = 64; /* default */
30cd9666
SK
2059 new->end6 = new->start6;
2060
2061 for (leasepos = 1; leasepos < k; leasepos++)
801ca9a7 2062 {
30cd9666
SK
2063 if (strcmp(a[leasepos], "static") == 0)
2064 new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
2065 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
2066 new->flags |= CONTEXT_RA_ONLY;
2067 else if (strcmp(a[leasepos], "ra-names") == 0)
2068 new->flags |= CONTEXT_RA_NAME;
2069 else if (strcmp(a[leasepos], "ra-stateless") == 0)
2070 new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP;
2071 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
2072 new->flags |= CONTEXT_DHCP;
2073 else
2074 break;
801ca9a7 2075 }
52b92f4d 2076
30cd9666 2077 if (new->flags & CONTEXT_DHCP)
c5ad4e79 2078 {
30cd9666
SK
2079 new->next = daemon->dhcp6;
2080 daemon->dhcp6 = new;
c5ad4e79
SK
2081 }
2082 else
2083 {
30cd9666
SK
2084 new->next = daemon->ra_contexts;
2085 daemon->ra_contexts = new;
c5ad4e79 2086 }
30cd9666 2087
52b92f4d 2088 /* bare integer < 128 is prefix value */
c4a7f90e 2089 if (leasepos < k)
52b92f4d
SK
2090 {
2091 int pref;
30cd9666 2092 for (cp = a[leasepos]; *cp; cp++)
52b92f4d
SK
2093 if (!(*cp >= '0' && *cp <= '9'))
2094 break;
30cd9666 2095 if (!*cp && (pref = atoi(a[leasepos])) <= 128)
52b92f4d
SK
2096 {
2097 new->prefix = pref;
30cd9666
SK
2098 leasepos++;
2099 if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) &&
2100 new->prefix != 64)
c4a7f90e 2101 ret_err(_("prefix must be exactly 64 for RA subnets"));
801ca9a7 2102 else if (new->prefix < 64)
c4a7f90e 2103 ret_err(_("prefix must be at least 64"));
52b92f4d
SK
2104 }
2105 }
30cd9666 2106
c4a7f90e
SK
2107 if (!is_same_net6(&new->start6, &new->end6, new->prefix))
2108 ret_err(_("inconsistent DHCPv6 range"));
2109 if (addr6part(&new->start6) > addr6part(&new->end6))
52b92f4d
SK
2110 {
2111 struct in6_addr tmp = new->start6;
2112 new->start6 = new->end6;
2113 new->end6 = tmp;
2114 }
849a8357 2115 }
52b92f4d 2116#endif
849a8357 2117
30cd9666 2118 if (leasepos < k)
849a8357
SK
2119 {
2120 if (strcmp(a[leasepos], "infinite") == 0)
2121 new->lease_time = 0xffffffff;
c8257540
SK
2122 else if (strcmp(a[leasepos], "deprecated") == 0)
2123 new->flags |= CONTEXT_DEPRECATE;
849a8357 2124 else
9e4abcb5 2125 {
849a8357
SK
2126 int fac = 1;
2127 if (strlen(a[leasepos]) > 0)
36717eee 2128 {
849a8357 2129 switch (a[leasepos][strlen(a[leasepos]) - 1])
36717eee 2130 {
849a8357
SK
2131 case 'd':
2132 case 'D':
2133 fac *= 24;
2134 /* fall though */
2135 case 'h':
2136 case 'H':
2137 fac *= 60;
2138 /* fall through */
2139 case 'm':
2140 case 'M':
2141 fac *= 60;
2142 /* fall through */
2143 case 's':
2144 case 'S':
f2621c7f 2145 a[leasepos][strlen(a[leasepos]) - 1] = 0;
9e4abcb5 2146 }
849a8357
SK
2147
2148 new->lease_time = atoi(a[leasepos]) * fac;
2149 /* Leases of a minute or less confuse
2150 some clients, notably Apple's */
2151 if (new->lease_time < 120)
2152 new->lease_time = 120;
9e4abcb5 2153 }
9e4abcb5 2154 }
849a8357
SK
2155 }
2156 break;
2157 }
5aabfc78 2158
5aabfc78 2159 case LOPT_BANK:
f2621c7f 2160 case 'G': /* --dhcp-host */
849a8357 2161 {
f2621c7f 2162 int j, k = 0;
849a8357 2163 char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
5aabfc78 2164 struct dhcp_config *new;
849a8357
SK
2165 struct in_addr in;
2166
824af85b
SK
2167 new = opt_malloc(sizeof(struct dhcp_config));
2168
849a8357 2169 new->next = daemon->dhcp_conf;
9009d746
SK
2170 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
2171 new->hwaddr = NULL;
8ef5ada2
SK
2172 new->netid = NULL;
2173
849a8357
SK
2174 if ((a[0] = arg))
2175 for (k = 1; k < 6; k++)
f2621c7f
SK
2176 if (!(a[k] = split(a[k-1])))
2177 break;
849a8357
SK
2178
2179 for (j = 0; j < k; j++)
2180 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
2181 {
2182 char *arg = a[j];
2183
2184 if ((arg[0] == 'i' || arg[0] == 'I') &&
2185 (arg[1] == 'd' || arg[1] == 'D') &&
2186 arg[2] == ':')
2187 {
2188 if (arg[3] == '*')
2189 new->flags |= CONFIG_NOCLID;
2190 else
3d8df260 2191 {
849a8357
SK
2192 int len;
2193 arg += 3; /* dump id: */
2194 if (strchr(arg, ':'))
2195 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
2196 else
5aabfc78
SK
2197 {
2198 unhide_metas(arg);
2199 len = (int) strlen(arg);
2200 }
2201
28866e95 2202 if (len == -1)
9f7f3b12 2203
c4a7f90e 2204 ret_err(_("bad hex constant"));
28866e95 2205 else if ((new->clid = opt_malloc(len)))
5aabfc78
SK
2206 {
2207 new->flags |= CONFIG_CLID;
2208 new->clid_len = len;
2209 memcpy(new->clid, arg, len);
2210 }
3d8df260 2211 }
849a8357 2212 }
8ef5ada2
SK
2213 /* dhcp-host has strange backwards-compat needs. */
2214 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
849a8357 2215 {
8ef5ada2
SK
2216 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2217 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2218 newtag->net = opt_malloc(strlen(arg + 4) + 1);
2219 newlist->next = new->netid;
2220 new->netid = newlist;
2221 newlist->list = newtag;
2222 strcpy(newtag->net, arg+4);
2223 unhide_metas(newtag->net);
849a8357 2224 }
7de060b0 2225 else if (strstr(arg, "tag:") == arg)
c4a7f90e 2226 ret_err(_("cannot match tags in --dhcp-host"));
4cb1b320
SK
2227#ifdef HAVE_DHCP6
2228 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
2229 {
2230 arg[strlen(arg)-1] = 0;
2231 arg++;
2232
2233 if (!inet_pton(AF_INET6, arg, &new->addr6))
c4a7f90e 2234 ret_err(_("bad IPv6 address"));
4cb1b320
SK
2235
2236 new->flags |= CONFIG_ADDR6;
2237 }
2238#endif
7de060b0 2239 else
849a8357 2240 {
9009d746 2241 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
28866e95
SK
2242 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
2243 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
c4a7f90e 2244 ret_err(_("bad hex constant"));
28866e95
SK
2245 else
2246 {
2247
2248 newhw->next = new->hwaddr;
2249 new->hwaddr = newhw;
2250 }
849a8357
SK
2251 }
2252 }
2253 else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
2254 {
c4a7f90e
SK
2255 struct dhcp_config *configs;
2256
849a8357
SK
2257 new->addr = in;
2258 new->flags |= CONFIG_ADDR;
c4a7f90e
SK
2259
2260 /* If the same IP appears in more than one host config, then DISCOVER
2261 for one of the hosts will get the address, but REQUEST will be NAKed,
2262 since the address is reserved by the other one -> protocol loop. */
2263 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
2264 if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
2265 {
2266 sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
2267 return 0;
2268 }
849a8357
SK
2269 }
2270 else
2271 {
2272 char *cp, *lastp = NULL, last = 0;
2273 int fac = 1;
2274
2275 if (strlen(a[j]) > 1)
2276 {
2277 lastp = a[j] + strlen(a[j]) - 1;
2278 last = *lastp;
2279 switch (last)
9e4abcb5 2280 {
849a8357
SK
2281 case 'd':
2282 case 'D':
2283 fac *= 24;
2284 /* fall through */
2285 case 'h':
2286 case 'H':
2287 fac *= 60;
2288 /* fall through */
2289 case 'm':
2290 case 'M':
2291 fac *= 60;
2292 /* fall through */
2293 case 's':
2294 case 'S':
2295 *lastp = 0;
9e4abcb5 2296 }
849a8357
SK
2297 }
2298
2299 for (cp = a[j]; *cp; cp++)
572b41eb 2300 if (!isdigit((unsigned char)*cp) && *cp != ' ')
849a8357
SK
2301 break;
2302
2303 if (*cp)
2304 {
2305 if (lastp)
2306 *lastp = last;
2307 if (strcmp(a[j], "infinite") == 0)
33820b7e 2308 {
849a8357
SK
2309 new->lease_time = 0xffffffff;
2310 new->flags |= CONFIG_TIME;
33820b7e 2311 }
849a8357
SK
2312 else if (strcmp(a[j], "ignore") == 0)
2313 new->flags |= CONFIG_DISABLE;
9e4abcb5
SK
2314 else
2315 {
1f15b81d
SK
2316 if (!(new->hostname = canonicalise_opt(a[j])) ||
2317 !legal_hostname(new->hostname))
c4a7f90e
SK
2318 ret_err(_("bad DHCP host name"));
2319
2320 new->flags |= CONFIG_NAME;
2321 new->domain = strip_hostname(new->hostname);
9e4abcb5 2322 }
849a8357
SK
2323 }
2324 else
2325 {
2326 new->lease_time = atoi(a[j]) * fac;
2327 /* Leases of a minute or less confuse
2328 some clients, notably Apple's */
2329 if (new->lease_time < 120)
2330 new->lease_time = 120;
2331 new->flags |= CONFIG_TIME;
2332 }
2333 }
2334
5aabfc78 2335 daemon->dhcp_conf = new;
849a8357
SK
2336 break;
2337 }
8ef5ada2
SK
2338
2339 case LOPT_TAG_IF: /* --tag-if */
2340 {
2341 struct tag_if *new = opt_malloc(sizeof(struct tag_if));
2342
2343 new->tag = NULL;
2344 new->set = NULL;
2345 new->next = NULL;
2346
2347 /* preserve order */
2348 if (!daemon->tag_if)
2349 daemon->tag_if = new;
2350 else
2351 {
2352 struct tag_if *tmp;
2353 for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
2354 tmp->next = new;
2355 }
2356
2357 while (arg)
2358 {
2359 size_t len;
2360
2361 comma = split(arg);
2362 len = strlen(arg);
2363
2364 if (len < 5)
2365 {
2366 new->set = NULL;
2367 break;
2368 }
2369 else
2370 {
2371 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
2372 newtag->net = opt_malloc(len - 3);
2373 strcpy(newtag->net, arg+4);
2374 unhide_metas(newtag->net);
2375
2376 if (strstr(arg, "set:") == arg)
2377 {
2378 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
2379 newlist->next = new->set;
2380 new->set = newlist;
2381 newlist->list = newtag;
2382 }
2383 else if (strstr(arg, "tag:") == arg)
2384 {
2385 newtag->next = new->tag;
2386 new->tag = newtag;
2387 }
2388 else
2389 {
2390 new->set = NULL;
2391 break;
2392 }
2393 }
2394
2395 arg = comma;
2396 }
2397
2398 if (!new->set)
c4a7f90e 2399 ret_err(_("bad tag-if"));
8ef5ada2
SK
2400
2401 break;
2402 }
2403
849a8357 2404
73a08a24
SK
2405 case 'O': /* --dhcp-option */
2406 case LOPT_FORCE: /* --dhcp-option-force */
824af85b 2407 case LOPT_OPTS:
73a08a24 2408 case LOPT_MATCH: /* --dhcp-match */
c4a7f90e
SK
2409 return parse_dhcp_opt(errstr, arg,
2410 option == LOPT_FORCE ? DHOPT_FORCE :
2411 (option == LOPT_MATCH ? DHOPT_MATCH :
2412 (option == LOPT_OPTS ? DHOPT_BANK : 0)));
2413
f2621c7f 2414 case 'M': /* --dhcp-boot */
849a8357
SK
2415 {
2416 struct dhcp_netid *id = NULL;
8ef5ada2 2417 while (is_tag_prefix(arg))
849a8357 2418 {
824af85b 2419 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
849a8357
SK
2420 newid->next = id;
2421 id = newid;
f2621c7f 2422 comma = split(arg);
824af85b 2423 newid->net = opt_string_alloc(arg+4);
849a8357
SK
2424 arg = comma;
2425 };
2426
2427 if (!arg)
c4a7f90e 2428 ret_err(gen_err);
849a8357
SK
2429 else
2430 {
7de060b0 2431 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
849a8357 2432 struct in_addr dhcp_next_server;
c4a7f90e 2433 struct dhcp_boot *new;
f2621c7f 2434 comma = split(arg);
824af85b 2435 dhcp_file = opt_string_alloc(arg);
849a8357
SK
2436 dhcp_next_server.s_addr = 0;
2437 if (comma)
a84fa1d0 2438 {
849a8357 2439 arg = comma;
f2621c7f 2440 comma = split(arg);
824af85b 2441 dhcp_sname = opt_string_alloc(arg);
849a8357 2442 if (comma)
a84fa1d0 2443 {
849a8357 2444 unhide_metas(comma);
7de060b0
SK
2445 if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) {
2446
2447 /*
2448 * The user may have specified the tftp hostname here.
2449 * save it so that it can be resolved/looked up during
2450 * actual dhcp_reply().
2451 */
2452
2453 tftp_sname = opt_string_alloc(comma);
2454 dhcp_next_server.s_addr = 0;
2455 }
a84fa1d0 2456 }
a84fa1d0 2457 }
c4a7f90e
SK
2458
2459 new = opt_malloc(sizeof(struct dhcp_boot));
2460 new->file = dhcp_file;
2461 new->sname = dhcp_sname;
2462 new->tftp_sname = tftp_sname;
2463 new->next_server = dhcp_next_server;
2464 new->netid = id;
2465 new->next = daemon->boot_config;
2466 daemon->boot_config = new;
849a8357
SK
2467 }
2468
849a8357
SK
2469 break;
2470 }
7622fc06
SK
2471
2472 case LOPT_PXE_PROMT: /* --pxe-prompt */
2473 {
2474 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
2475 int timeout;
2476
2477 new->netid = NULL;
2478 new->opt = 10; /* PXE_MENU_PROMPT */
2479
8ef5ada2
SK
2480 while (is_tag_prefix(arg))
2481 {
7622fc06
SK
2482 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2483 comma = split(arg);
2484 nn->next = new->netid;
2485 new->netid = nn;
2486 nn->net = opt_string_alloc(arg+4);
2487 arg = comma;
2488 }
2489
2490 if (!arg)
c4a7f90e 2491 ret_err(gen_err);
7622fc06
SK
2492 else
2493 {
2494 comma = split(arg);
2495 unhide_metas(arg);
2496 new->len = strlen(arg) + 1;
2497 new->val = opt_malloc(new->len);
2498 memcpy(new->val + 1, arg, new->len - 1);
2499
2500 new->u.vendor_class = (unsigned char *)"PXEClient";
2501 new->flags = DHOPT_VENDOR;
2502
2503 if (comma && atoi_check(comma, &timeout))
2504 *(new->val) = timeout;
2505 else
2506 *(new->val) = 255;
2507
2508 new->next = daemon->dhcp_opts;
2509 daemon->dhcp_opts = new;
1f15b81d 2510 daemon->enable_pxe = 1;
7622fc06
SK
2511 }
2512
2513 break;
2514 }
2515
2516 case LOPT_PXE_SERV: /* --pxe-service */
2517 {
2518 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2519 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2520 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2521 static int boottype = 32768;
2522
2523 new->netid = NULL;
751d6f4a 2524 new->sname = NULL;
7622fc06
SK
2525 new->server.s_addr = 0;
2526
8ef5ada2 2527 while (is_tag_prefix(arg))
7622fc06
SK
2528 {
2529 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2530 comma = split(arg);
2531 nn->next = new->netid;
2532 new->netid = nn;
2533 nn->net = opt_string_alloc(arg+4);
2534 arg = comma;
2535 }
2536
2537 if (arg && (comma = split(arg)))
2538 {
2539 for (i = 0; CSA[i]; i++)
2540 if (strcasecmp(CSA[i], arg) == 0)
2541 break;
2542
2543 if (CSA[i] || atoi_check(arg, &i))
2544 {
2545 arg = comma;
2546 comma = split(arg);
2547
2548 new->CSA = i;
2549 new->menu = opt_string_alloc(arg);
2550
316e2730
SK
2551 if (!comma)
2552 {
2553 new->type = 0; /* local boot */
2554 new->basename = NULL;
2555 }
2556 else
7622fc06
SK
2557 {
2558 arg = comma;
2559 comma = split(arg);
2560 if (atoi_check(arg, &i))
2561 {
2562 new->type = i;
2563 new->basename = NULL;
2564 }
2565 else
2566 {
2567 new->type = boottype++;
2568 new->basename = opt_string_alloc(arg);
2569 }
2570
751d6f4a
SK
2571 if (comma)
2572 {
2573 if (!inet_pton(AF_INET, comma, &new->server))
2574 {
2575 new->server.s_addr = 0;
2576 new->sname = opt_string_alloc(comma);
2577 }
2578
2579 }
7622fc06 2580 }
751d6f4a 2581
316e2730
SK
2582 /* Order matters */
2583 new->next = NULL;
2584 if (!daemon->pxe_services)
2585 daemon->pxe_services = new;
2586 else
2587 {
2588 struct pxe_service *s;
2589 for (s = daemon->pxe_services; s->next; s = s->next);
2590 s->next = new;
2591 }
2592
2593 daemon->enable_pxe = 1;
2594 break;
2595
7622fc06
SK
2596 }
2597 }
2598
c4a7f90e 2599 ret_err(gen_err);
7622fc06
SK
2600 }
2601
f2621c7f 2602 case '4': /* --dhcp-mac */
849a8357 2603 {
f2621c7f 2604 if (!(comma = split(arg)))
c4a7f90e 2605 ret_err(gen_err);
849a8357
SK
2606 else
2607 {
824af85b 2608 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
8ef5ada2 2609 new->netid.net = opt_string_alloc(set_prefix(arg));
f2621c7f
SK
2610 unhide_metas(comma);
2611 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
28866e95 2612 if (new->hwaddr_len == -1)
c4a7f90e 2613 ret_err(gen_err);
28866e95
SK
2614 else
2615 {
2616 new->next = daemon->dhcp_macs;
2617 daemon->dhcp_macs = new;
2618 }
849a8357
SK
2619 }
2620 }
2621 break;
2622
f2621c7f
SK
2623 case 'U': /* --dhcp-vendorclass */
2624 case 'j': /* --dhcp-userclass */
2625 case LOPT_CIRCUIT: /* --dhcp-circuitid */
2626 case LOPT_REMOTE: /* --dhcp-remoteid */
2627 case LOPT_SUBSCR: /* --dhcp-subscrid */
849a8357 2628 {
c4a7f90e
SK
2629 unsigned char *p;
2630 int dig = 0;
2631 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2632
2633 if (!(comma = split(arg)))
2634 ret_err(gen_err);
2635
2636 new->netid.net = opt_string_alloc(set_prefix(arg));
2637 /* check for hex string - must digits may include : must not have nothing else,
2638 only allowed for agent-options. */
2639
2640 arg = comma;
2641 if ((comma = split(arg)))
2642 {
2643 if (option != 'U' || strstr(arg, "enterprise:") != arg)
2644 ret_err(gen_err);
2645 else
2646 new->enterprise = atoi(arg+11);
2647 }
2648 else
2649 comma = arg;
2650
2651 for (p = (unsigned char *)comma; *p; p++)
2652 if (isxdigit(*p))
2653 dig = 1;
2654 else if (*p != ':')
2655 break;
2656 unhide_metas(comma);
2657 if (option == 'U' || option == 'j' || *p || !dig)
2658 {
2659 new->len = strlen(comma);
2660 new->data = opt_malloc(new->len);
2661 memcpy(new->data, comma, new->len);
2662 }
2663 else
2664 {
2665 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2666 new->data = opt_malloc(new->len);
2667 memcpy(new->data, comma, new->len);
2668 }
2669
2670 switch (option)
2671 {
2672 case 'j':
2673 new->match_type = MATCH_USER;
2674 break;
2675 case 'U':
2676 new->match_type = MATCH_VENDOR;
2677 break;
2678 case LOPT_CIRCUIT:
2679 new->match_type = MATCH_CIRCUIT;
2680 break;
2681 case LOPT_REMOTE:
2682 new->match_type = MATCH_REMOTE;
2683 break;
2684 case LOPT_SUBSCR:
2685 new->match_type = MATCH_SUBSCRIBER;
2686 break;
2687 }
2688 new->next = daemon->dhcp_vendors;
2689 daemon->dhcp_vendors = new;
824af85b 2690
c4a7f90e 2691 break;
849a8357
SK
2692 }
2693
9e038946
SK
2694 case LOPT_ALTPORT: /* --dhcp-alternate-port */
2695 if (!arg)
2696 {
2697 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2698 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2699 }
2700 else
2701 {
2702 comma = split(arg);
1ad24ae1
SK
2703 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2704 (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
c4a7f90e 2705 ret_err(_("invalid port number"));
9e038946
SK
2706 if (!comma)
2707 daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2708 }
2709 break;
2710
824af85b
SK
2711 case 'J': /* --dhcp-ignore */
2712 case LOPT_NO_NAMES: /* --dhcp-ignore-names */
2713 case LOPT_BROADCAST: /* --dhcp-broadcast */
8ef5ada2
SK
2714 case '3': /* --bootp-dynamic */
2715 case LOPT_GEN_NAMES: /* --dhcp-generate-names */
849a8357 2716 {
824af85b 2717 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
849a8357 2718 struct dhcp_netid *list = NULL;
832af0ba
SK
2719 if (option == 'J')
2720 {
2721 new->next = daemon->dhcp_ignore;
2722 daemon->dhcp_ignore = new;
2723 }
824af85b
SK
2724 else if (option == LOPT_BROADCAST)
2725 {
2726 new->next = daemon->force_broadcast;
2727 daemon->force_broadcast = new;
2728 }
9009d746
SK
2729 else if (option == '3')
2730 {
2731 new->next = daemon->bootp_dynamic;
2732 daemon->bootp_dynamic = new;
2733 }
8ef5ada2
SK
2734 else if (option == LOPT_GEN_NAMES)
2735 {
2736 new->next = daemon->dhcp_gen_names;
2737 daemon->dhcp_gen_names = new;
2738 }
832af0ba
SK
2739 else
2740 {
2741 new->next = daemon->dhcp_ignore_names;
2742 daemon->dhcp_ignore_names = new;
2743 }
2744
2745 while (arg) {
824af85b 2746 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
f2621c7f 2747 comma = split(arg);
849a8357
SK
2748 member->next = list;
2749 list = member;
8ef5ada2 2750 if (is_tag_prefix(arg))
9009d746
SK
2751 member->net = opt_string_alloc(arg+4);
2752 else
2753 member->net = opt_string_alloc(arg);
849a8357 2754 arg = comma;
832af0ba 2755 }
849a8357
SK
2756
2757 new->list = list;
2758 break;
2759 }
8ef5ada2
SK
2760
2761 case LOPT_PROXY: /* --dhcp-proxy */
2762 daemon->override = 1;
2763 while (arg) {
2764 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
2765 comma = split(arg);
2766 if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
c4a7f90e 2767 ret_err(_("bad dhcp-proxy address"));
8ef5ada2
SK
2768 new->next = daemon->override_relays;
2769 daemon->override_relays = new;
2770 arg = comma;
2771 }
2772 break;
7622fc06 2773#endif
849a8357 2774
8b372704
SK
2775#ifdef HAVE_DHCP6
2776 case LOPT_DUID: /* --dhcp-duid */
2777 if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
c4a7f90e 2778 ret_err(_("bad DUID"));
8b372704
SK
2779 else
2780 {
2781 daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
2782 daemon->duid_config = opt_malloc(daemon->duid_config_len);
2783 memcpy(daemon->duid_config, comma, daemon->duid_config_len);
2784 }
2785 break;
2786#endif
2787
f2621c7f 2788 case 'V': /* --alias */
849a8357 2789 {
73a08a24 2790 char *dash, *a[3] = { NULL, NULL, NULL };
f2621c7f 2791 int k = 0;
73a08a24
SK
2792 struct doctor *new = opt_malloc(sizeof(struct doctor));
2793 new->next = daemon->doctors;
2794 daemon->doctors = new;
2795 new->mask.s_addr = 0xffffffff;
2796 new->end.s_addr = 0;
2797
849a8357
SK
2798 if ((a[0] = arg))
2799 for (k = 1; k < 3; k++)
2800 {
f2621c7f 2801 if (!(a[k] = split(a[k-1])))
849a8357 2802 break;
849a8357
SK
2803 unhide_metas(a[k]);
2804 }
849a8357 2805
73a08a24
SK
2806 dash = split_chr(a[0], '-');
2807
849a8357 2808 if ((k < 2) ||
73a08a24
SK
2809 ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
2810 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
2811 option = '?';
849a8357
SK
2812
2813 if (k == 3)
73a08a24 2814 new->mask.s_addr = inet_addr(a[2]);
849a8357 2815
73a08a24
SK
2816 if (dash &&
2817 ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
2818 !is_same_net(new->in, new->end, new->mask) ||
2819 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
c4a7f90e 2820 ret_err(_("invalid alias range"));
849a8357
SK
2821
2822 break;
2823 }
2824
f2621c7f 2825 case LOPT_INTNAME: /* --interface-name */
832af0ba 2826 {
f2621c7f 2827 struct interface_name *new, **up;
1f15b81d
SK
2828 char *domain = NULL;
2829
f2621c7f
SK
2830 comma = split(arg);
2831
1f15b81d 2832 if (!comma || !(domain = canonicalise_opt(arg)))
c4a7f90e 2833 ret_err(_("bad interface name"));
1f15b81d 2834
824af85b 2835 new = opt_malloc(sizeof(struct interface_name));
f2621c7f
SK
2836 new->next = NULL;
2837 /* Add to the end of the list, so that first name
2838 of an interface is used for PTR lookups. */
824af85b 2839 for (up = &daemon->int_names; *up; up = &((*up)->next));
f2621c7f 2840 *up = new;
1f15b81d 2841 new->name = domain;
824af85b 2842 new->intr = opt_string_alloc(comma);
f2621c7f
SK
2843 break;
2844 }
9009d746
SK
2845
2846 case LOPT_CNAME: /* --cname */
2847 {
2848 struct cname *new;
c4a7f90e
SK
2849 char *alias;
2850 char *target;
2851
9009d746 2852 if (!(comma = split(arg)))
c4a7f90e
SK
2853 ret_err(gen_err);
2854
2855 alias = canonicalise_opt(arg);
2856 target = canonicalise_opt(comma);
2857
2858 if (!alias || !target)
2859 ret_err(_("bad CNAME"));
9009d746
SK
2860 else
2861 {
c4a7f90e
SK
2862 for (new = daemon->cnames; new; new = new->next)
2863 if (hostname_isequal(new->alias, arg))
2864 ret_err(_("duplicate CNAME"));
2865 new = opt_malloc(sizeof(struct cname));
2866 new->next = daemon->cnames;
2867 daemon->cnames = new;
2868 new->alias = alias;
2869 new->target = target;
9009d746 2870 }
c4a7f90e 2871
9009d746
SK
2872 break;
2873 }
f2621c7f
SK
2874
2875 case LOPT_PTR: /* --ptr-record */
2876 {
2877 struct ptr_record *new;
1f15b81d
SK
2878 char *dom, *target = NULL;
2879
f2621c7f
SK
2880 comma = split(arg);
2881
1f15b81d
SK
2882 if (!(dom = canonicalise_opt(arg)) ||
2883 (comma && !(target = canonicalise_opt(comma))))
c4a7f90e 2884 ret_err(_("bad PTR record"));
1f15b81d
SK
2885 else
2886 {
2887 new = opt_malloc(sizeof(struct ptr_record));
2888 new->next = daemon->ptr;
2889 daemon->ptr = new;
2890 new->name = dom;
2891 new->ptr = target;
2892 }
832af0ba
SK
2893 break;
2894 }
2895
1a6bca81
SK
2896 case LOPT_NAPTR: /* --naptr-record */
2897 {
2898 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2899 int k = 0;
2900 struct naptr *new;
2901 int order, pref;
1f15b81d 2902 char *name, *replace = NULL;
1a6bca81
SK
2903
2904 if ((a[0] = arg))
2905 for (k = 1; k < 7; k++)
2906 if (!(a[k] = split(a[k-1])))
2907 break;
2908
2909
2910 if (k < 6 ||
1f15b81d 2911 !(name = canonicalise_opt(a[0])) ||
1ad24ae1
SK
2912 !atoi_check16(a[1], &order) ||
2913 !atoi_check16(a[2], &pref) ||
1f15b81d 2914 (k == 7 && !(replace = canonicalise_opt(a[6]))))
c4a7f90e 2915 ret_err(_("bad NAPTR record"));
1a6bca81
SK
2916 else
2917 {
2918 new = opt_malloc(sizeof(struct naptr));
2919 new->next = daemon->naptr;
2920 daemon->naptr = new;
1f15b81d 2921 new->name = name;
1a6bca81
SK
2922 new->flags = opt_string_alloc(a[3]);
2923 new->services = opt_string_alloc(a[4]);
2924 new->regexp = opt_string_alloc(a[5]);
1f15b81d 2925 new->replace = replace;
1a6bca81
SK
2926 new->order = order;
2927 new->pref = pref;
2928 }
2929 break;
2930 }
9f7f3b12
SK
2931
2932 case LOPT_RR: /* dns-rr */
2933 {
2934 struct txt_record *new;
2935 size_t len;
2936 char *data;
2937 int val;
2938
2939 comma = split(arg);
2940 data = split(comma);
2941
2942 new = opt_malloc(sizeof(struct txt_record));
2943 new->next = daemon->rr;
2944 daemon->rr = new;
2945
2946 if (!atoi_check(comma, &val) ||
2947 !(new->name = canonicalise_opt(arg)) ||
51931b88 2948 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
c4a7f90e
SK
2949 ret_err(_("bad RR record"));
2950
9f7f3b12
SK
2951 new->class = val;
2952 new->len = 0;
2953
2954 if (data)
2955 {
2956 new->txt=opt_malloc(len);
2957 new->len = len;
2958 memcpy(new->txt, data, len);
2959 }
2960
2961 break;
2962 }
2963
f2621c7f 2964 case 'Y': /* --txt-record */
849a8357
SK
2965 {
2966 struct txt_record *new;
28866e95
SK
2967 unsigned char *p, *cnt;
2968 size_t len;
2969
2970 comma = split(arg);
2971
824af85b 2972 new = opt_malloc(sizeof(struct txt_record));
849a8357
SK
2973 new->next = daemon->txt;
2974 daemon->txt = new;
2975 new->class = C_IN;
849a8357 2976
1f15b81d 2977 if (!(new->name = canonicalise_opt(arg)))
c4a7f90e
SK
2978 ret_err(_("bad TXT record"));
2979
28866e95
SK
2980 len = comma ? strlen(comma) : 0;
2981 len += (len/255) + 1; /* room for extra counts */
2982 new->txt = p = opt_malloc(len);
2983
2984 cnt = p++;
2985 *cnt = 0;
2986
2987 while (comma && *comma)
2988 {
2989 unsigned char c = (unsigned char)*comma++;
2990
2991 if (c == ',' || *cnt == 255)
2992 {
2993 if (c != ',')
2994 comma--;
2995 cnt = p++;
2996 *cnt = 0;
2997 }
2998 else
2999 {
3000 *p++ = unhide_meta(c);
3001 (*cnt)++;
3002 }
3003 }
3004
3005 new->len = p - new->txt;
3006
849a8357
SK
3007 break;
3008 }
3009
f2621c7f 3010 case 'W': /* --srv-host */
849a8357
SK
3011 {
3012 int port = 1, priority = 0, weight = 0;
3013 char *name, *target = NULL;
3014 struct mx_srv_record *new;
3015
f2621c7f 3016 comma = split(arg);
849a8357 3017
1f15b81d 3018 if (!(name = canonicalise_opt(arg)))
c4a7f90e
SK
3019 ret_err(_("bad SRV record"));
3020
849a8357
SK
3021 if (comma)
3022 {
3023 arg = comma;
f2621c7f 3024 comma = split(arg);
c4a7f90e
SK
3025 if (!(target = canonicalise_opt(arg)))
3026 ret_err(_("bad SRV target"));
824af85b 3027
849a8357 3028 if (comma)
f6b7dc47 3029 {
849a8357 3030 arg = comma;
f2621c7f 3031 comma = split(arg);
1ad24ae1 3032 if (!atoi_check16(arg, &port))
c4a7f90e 3033 ret_err(_("invalid port number"));
824af85b 3034
f6b7dc47
SK
3035 if (comma)
3036 {
91dccd09 3037 arg = comma;
f2621c7f 3038 comma = split(arg);
1ad24ae1 3039 if (!atoi_check16(arg, &priority))
c4a7f90e 3040 ret_err(_("invalid priority"));
824af85b 3041
f6b7dc47
SK
3042 if (comma)
3043 {
91dccd09 3044 arg = comma;
f2621c7f 3045 comma = split(arg);
1ad24ae1 3046 if (!atoi_check16(arg, &weight))
c4a7f90e 3047 ret_err(_("invalid weight"));
f6b7dc47
SK
3048 }
3049 }
f6b7dc47 3050 }
849a8357
SK
3051 }
3052
824af85b 3053 new = opt_malloc(sizeof(struct mx_srv_record));
849a8357
SK
3054 new->next = daemon->mxnames;
3055 daemon->mxnames = new;
3056 new->issrv = 1;
3057 new->name = name;
3058 new->target = target;
3059 new->srvport = port;
3060 new->priority = priority;
3061 new->weight = weight;
3062 break;
3063 }
7622fc06 3064
e759d426
SK
3065 case LOPT_HOST_REC: /* --host-record */
3066 {
3067 struct host_record *new = opt_malloc(sizeof(struct host_record));
3068 memset(new, 0, sizeof(struct host_record));
3069
3070 if (!arg || !(comma = split(arg)))
c4a7f90e
SK
3071 ret_err(_("Bad host-record"));
3072
3073 while (arg)
3074 {
3075 struct all_addr addr;
3076 if (inet_pton(AF_INET, arg, &addr))
3077 new->addr = addr.addr.addr4;
e759d426 3078#ifdef HAVE_IPV6
c4a7f90e
SK
3079 else if (inet_pton(AF_INET6, arg, &addr))
3080 new->addr6 = addr.addr.addr6;
e759d426 3081#endif
c4a7f90e
SK
3082 else
3083 {
3084 int nomem;
3085 char *canon = canonicalise(arg, &nomem);
3086 struct name_list *nl = opt_malloc(sizeof(struct name_list));
3087 if (!canon)
3088 ret_err(_("Bad name in host-record"));
3089
3090 nl->name = canon;
3091 /* keep order, so that PTR record goes to first name */
3092 nl->next = NULL;
3093 if (!new->names)
3094 new->names = nl;
3095 else
3096 {
3097 struct name_list *tmp;
3098 for (tmp = new->names; tmp->next; tmp = tmp->next);
3099 tmp->next = nl;
3100 }
3101
3102 arg = comma;
3103 comma = split(arg);
3104 }
3105 }
e759d426
SK
3106
3107 /* Keep list order */
3108 if (!daemon->host_records_tail)
3109 daemon->host_records = new;
3110 else
3111 daemon->host_records_tail->next = new;
3112 new->next = NULL;
3113 daemon->host_records_tail = new;
3114 break;
3115 }
c4a7f90e 3116
7622fc06 3117 default:
c4a7f90e
SK
3118 ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));
3119
849a8357 3120 }
824af85b 3121
c4a7f90e 3122 return 1;
849a8357
SK
3123}
3124
28866e95 3125static void read_file(char *file, FILE *f, int hard_opt)
849a8357 3126{
824af85b 3127 volatile int lineno = 0;
8ef5ada2 3128 char *buff = daemon->namebuff;
849a8357
SK
3129
3130 while (fgets(buff, MAXDNAME, f))
3131 {
611ebc5f
SK
3132 int white, i, option = hard_opt;
3133 char *errmess, *p, *arg = NULL, *start;
8ef5ada2 3134 size_t len;
832af0ba 3135
824af85b 3136 /* Memory allocation failure longjmps here if mem_recover == 1 */
611ebc5f 3137 if (option != 0)
824af85b
SK
3138 {
3139 if (setjmp(mem_jmp))
3140 continue;
3141 mem_recover = 1;
3142 }
3143
849a8357 3144 lineno++;
824af85b
SK
3145 errmess = NULL;
3146
849a8357
SK
3147 /* Implement quotes, inside quotes we allow \\ \" \n and \t
3148 metacharacters get hidden also strip comments */
8ef5ada2 3149 for (white = 1, p = buff; *p; p++)
849a8357
SK
3150 {
3151 if (*p == '"')
3152 {
3153 memmove(p, p+1, strlen(p+1)+1);
8ef5ada2 3154
849a8357
SK
3155 for(; *p && *p != '"'; p++)
3156 {
5aabfc78 3157 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
849a8357
SK
3158 {
3159 if (p[1] == 't')
3160 p[1] = '\t';
3161 else if (p[1] == 'n')
3162 p[1] = '\n';
849a8357
SK
3163 else if (p[1] == 'b')
3164 p[1] = '\b';
3165 else if (p[1] == 'r')
3166 p[1] = '\r';
6b01084f
SK
3167 else if (p[1] == 'e') /* escape */
3168 p[1] = '\033';
849a8357
SK
3169 memmove(p, p+1, strlen(p+1)+1);
3170 }
3171 *p = hide_meta(*p);
3172 }
8ef5ada2
SK
3173
3174 if (*p == 0)
f2621c7f
SK
3175 {
3176 errmess = _("missing \"");
3177 goto oops;
3178 }
8ef5ada2
SK
3179
3180 memmove(p, p+1, strlen(p+1)+1);
849a8357 3181 }
f2621c7f 3182
8ef5ada2
SK
3183 if (isspace(*p))
3184 {
3185 *p = ' ';
3186 white = 1;
9e4abcb5 3187 }
8ef5ada2
SK
3188 else
3189 {
3190 if (white && *p == '#')
3191 {
3192 *p = 0;
3193 break;
3194 }
3195 white = 0;
3196 }
849a8357
SK
3197 }
3198
8ef5ada2
SK
3199
3200 /* strip leading spaces */
3201 for (start = buff; *start && *start == ' '; start++);
3202
3203 /* strip trailing spaces */
3204 for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
3205
3206 if (len == 0)
849a8357 3207 continue;
8ef5ada2
SK
3208 else
3209 start[len] = 0;
3210
611ebc5f 3211 if (option != 0)
8ef5ada2
SK
3212 arg = start;
3213 else if ((p=strchr(start, '=')))
849a8357
SK
3214 {
3215 /* allow spaces around "=" */
8ef5ada2
SK
3216 for (arg = p+1; *arg == ' '; arg++);
3217 for (; p >= start && (*p == ' ' || *p == '='); p--)
849a8357 3218 *p = 0;
9e4abcb5 3219 }
849a8357
SK
3220 else
3221 arg = NULL;
832af0ba 3222
611ebc5f 3223 if (option == 0)
5aabfc78 3224 {
5aabfc78
SK
3225 for (option = 0, i = 0; opts[i].name; i++)
3226 if (strcmp(opts[i].name, start) == 0)
3227 {
3228 option = opts[i].val;
3229 break;
3230 }
3231
3232 if (!option)
3233 errmess = _("bad option");
3234 else if (opts[i].has_arg == 0 && arg)
3235 errmess = _("extraneous parameter");
3236 else if (opts[i].has_arg == 1 && !arg)
3237 errmess = _("missing parameter");
3238 }
c4a7f90e
SK
3239
3240 oops:
832af0ba 3241 if (errmess)
c4a7f90e
SK
3242 strcpy(daemon->namebuff, errmess);
3243
3244 if (errmess || !one_opt(option, arg, buff, _("error"), 0))
f2621c7f 3245 {
c4a7f90e 3246 sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
824af85b 3247 if (hard_opt != 0)
c4a7f90e 3248 my_syslog(LOG_ERR, "%s", daemon->namebuff);
5aabfc78 3249 else
c4a7f90e 3250 die("%s", daemon->namebuff, EC_BADCONF);
f2621c7f 3251 }
849a8357
SK
3252 }
3253
8ef5ada2 3254 mem_recover = 0;
849a8357
SK
3255 fclose(f);
3256}
3257
395eb719 3258static int one_file(char *file, int hard_opt)
28866e95
SK
3259{
3260 FILE *f;
3261 int nofile_ok = 0;
3262 static int read_stdin = 0;
3263 static struct fileread {
3264 dev_t dev;
3265 ino_t ino;
3266 struct fileread *next;
3267 } *filesread = NULL;
3268
3269 if (hard_opt == '7')
3270 {
3271 /* default conf-file reading */
3272 hard_opt = 0;
3273 nofile_ok = 1;
3274 }
3275
3276 if (hard_opt == 0 && strcmp(file, "-") == 0)
3277 {
3278 if (read_stdin == 1)
395eb719 3279 return 1;
28866e95
SK
3280 read_stdin = 1;
3281 file = "stdin";
3282 f = stdin;
3283 }
3284 else
3285 {
3286 /* ignore repeated files. */
3287 struct stat statbuf;
3288
3289 if (hard_opt == 0 && stat(file, &statbuf) == 0)
3290 {
3291 struct fileread *r;
3292
3293 for (r = filesread; r; r = r->next)
3294 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
395eb719 3295 return 1;
28866e95
SK
3296
3297 r = safe_malloc(sizeof(struct fileread));
3298 r->next = filesread;
3299 filesread = r;
3300 r->dev = statbuf.st_dev;
3301 r->ino = statbuf.st_ino;
3302 }
3303
3304 if (!(f = fopen(file, "r")))
3305 {
3306 if (errno == ENOENT && nofile_ok)
395eb719 3307 return 1; /* No conffile, all done. */
28866e95
SK
3308 else
3309 {
3310 char *str = _("cannot read %s: %s");
3311 if (hard_opt != 0)
3312 {
3313 my_syslog(LOG_ERR, str, file, strerror(errno));
395eb719 3314 return 0;
28866e95
SK
3315 }
3316 else
3317 die(str, file, EC_FILE);
3318 }
3319 }
3320 }
3321
3322 read_file(file, f, hard_opt);
395eb719 3323 return 1;
28866e95
SK
3324}
3325
3326/* expand any name which is a directory */
3327struct hostsfile *expand_filelist(struct hostsfile *list)
3328{
3329 int i;
3330 struct hostsfile *ah;
3331
3332 for (i = 0, ah = list; ah; ah = ah->next)
3333 {
3334 if (i <= ah->index)
3335 i = ah->index + 1;
3336
3337 if (ah->flags & AH_DIR)
3338 ah->flags |= AH_INACTIVE;
3339 else
3340 ah->flags &= ~AH_INACTIVE;
3341 }
3342
3343 for (ah = list; ah; ah = ah->next)
3344 if (!(ah->flags & AH_INACTIVE))
3345 {
3346 struct stat buf;
3347 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
3348 {
3349 DIR *dir_stream;
3350 struct dirent *ent;
3351
3352 /* don't read this as a file */
3353 ah->flags |= AH_INACTIVE;
3354
3355 if (!(dir_stream = opendir(ah->fname)))
3356 my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
3357 ah->fname, strerror(errno));
3358 else
3359 {
3360 while ((ent = readdir(dir_stream)))
3361 {
3362 size_t lendir = strlen(ah->fname);
3363 size_t lenfile = strlen(ent->d_name);
3364 struct hostsfile *ah1;
3365 char *path;
3366
3367 /* ignore emacs backups and dotfiles */
3368 if (lenfile == 0 ||
3369 ent->d_name[lenfile - 1] == '~' ||
3370 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
3371 ent->d_name[0] == '.')
3372 continue;
3373
3374 /* see if we have an existing record.
3375 dir is ah->fname
3376 file is ent->d_name
3377 path to match is ah1->fname */
3378
3379 for (ah1 = list; ah1; ah1 = ah1->next)
3380 {
3381 if (lendir < strlen(ah1->fname) &&
3382 strstr(ah1->fname, ah->fname) == ah1->fname &&
3383 ah1->fname[lendir] == '/' &&
3384 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
3385 {
3386 ah1->flags &= ~AH_INACTIVE;
3387 break;
3388 }
3389 }
3390
3391 /* make new record */
3392 if (!ah1)
3393 {
3394 if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
3395 continue;
3396
3397 if (!(path = whine_malloc(lendir + lenfile + 2)))
3398 {
3399 free(ah1);
3400 continue;
3401 }
3402
3403 strcpy(path, ah->fname);
3404 strcat(path, "/");
3405 strcat(path, ent->d_name);
3406 ah1->fname = path;
3407 ah1->index = i++;
3408 ah1->flags = AH_DIR;
3409 ah1->next = list;
3410 list = ah1;
3411 }
3412
3413 /* inactivate record if not regular file */
3414 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
3415 ah1->flags |= AH_INACTIVE;
3416
3417 }
3418 closedir(dir_stream);
3419 }
3420 }
3421 }
3422
3423 return list;
3424}
3425
3426
7622fc06 3427#ifdef HAVE_DHCP
824af85b
SK
3428void reread_dhcp(void)
3429{
28866e95
SK
3430 struct hostsfile *hf;
3431
824af85b
SK
3432 if (daemon->dhcp_hosts_file)
3433 {
3434 struct dhcp_config *configs, *cp, **up;
28866e95 3435
824af85b
SK
3436 /* remove existing... */
3437 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
3438 {
3439 cp = configs->next;
3440
3441 if (configs->flags & CONFIG_BANK)
3442 {
9009d746 3443 struct hwaddr_config *mac, *tmp;
8ef5ada2 3444 struct dhcp_netid_list *list, *tmplist;
9009d746
SK
3445
3446 for (mac = configs->hwaddr; mac; mac = tmp)
3447 {
3448 tmp = mac->next;
3449 free(mac);
3450 }
8ef5ada2 3451
824af85b
SK
3452 if (configs->flags & CONFIG_CLID)
3453 free(configs->clid);
8ef5ada2
SK
3454
3455 for (list = configs->netid; list; list = tmplist)
3456 {
3457 free(list->list);
3458 tmplist = list->next;
3459 free(list);
3460 }
3461
824af85b
SK
3462 if (configs->flags & CONFIG_NAME)
3463 free(configs->hostname);
3464
3465 *up = configs->next;
3466 free(configs);
3467 }
3468 else
3469 up = &configs->next;
3470 }
3471
28866e95
SK
3472 daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
3473 for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
3474 if (!(hf->flags & AH_INACTIVE))
3475 {
395eb719
SK
3476 if (one_file(hf->fname, LOPT_BANK))
3477 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 3478 }
824af85b
SK
3479 }
3480
3481 if (daemon->dhcp_opts_file)
3482 {
3483 struct dhcp_opt *opts, *cp, **up;
3484 struct dhcp_netid *id, *next;
3485
3486 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
3487 {
3488 cp = opts->next;
3489
3490 if (opts->flags & DHOPT_BANK)
3491 {
73a08a24
SK
3492 if ((opts->flags & DHOPT_VENDOR))
3493 free(opts->u.vendor_class);
824af85b
SK
3494 free(opts->val);
3495 for (id = opts->netid; id; id = next)
3496 {
3497 next = id->next;
3498 free(id->net);
3499 free(id);
3500 }
3501 *up = opts->next;
3502 free(opts);
3503 }
3504 else
3505 up = &opts->next;
3506 }
3507
28866e95
SK
3508 daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
3509 for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
3510 if (!(hf->flags & AH_INACTIVE))
3511 {
395eb719
SK
3512 if (one_file(hf->fname, LOPT_OPTS))
3513 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
28866e95 3514 }
824af85b
SK
3515 }
3516}
7622fc06 3517#endif
824af85b 3518
5aabfc78 3519void read_opts(int argc, char **argv, char *compile_opts)
849a8357 3520{
824af85b 3521 char *buff = opt_malloc(MAXDNAME);
28866e95 3522 int option, conffile_opt = '7', testmode = 0;
c4a7f90e 3523 char *arg, *conffile = CONFFILE;
849a8357
SK
3524
3525 opterr = 0;
5aabfc78 3526
824af85b 3527 daemon = opt_malloc(sizeof(struct daemon));
849a8357
SK
3528 memset(daemon, 0, sizeof(struct daemon));
3529 daemon->namebuff = buff;
3530
3531 /* Set defaults - everything else is zero or NULL */
3532 daemon->cachesize = CACHESIZ;
208b65c5 3533 daemon->ftabsize = FTABSIZ;
849a8357 3534 daemon->port = NAMESERVER_PORT;
9e038946
SK
3535 daemon->dhcp_client_port = DHCP_CLIENT_PORT;
3536 daemon->dhcp_server_port = DHCP_SERVER_PORT;
849a8357
SK
3537 daemon->default_resolv.is_default = 1;
3538 daemon->default_resolv.name = RESOLVFILE;
3539 daemon->resolv_files = &daemon->default_resolv;
3540 daemon->username = CHUSER;
849a8357
SK
3541 daemon->runfile = RUNFILE;
3542 daemon->dhcp_max = MAXLEASES;
832af0ba 3543 daemon->tftp_max = TFTP_MAX_CONNECTIONS;
849a8357
SK
3544 daemon->edns_pktsz = EDNS_PKTSZ;
3545 daemon->log_fac = -1;
5aabfc78
SK
3546 add_txt("version.bind", "dnsmasq-" VERSION );
3547 add_txt("authors.bind", "Simon Kelley");
3548 add_txt("copyright.bind", COPYRIGHT);
849a8357
SK
3549
3550 while (1)
3551 {
26128d27 3552#ifdef HAVE_GETOPT_LONG
849a8357 3553 option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
26128d27 3554#else
849a8357 3555 option = getopt(argc, argv, OPTSTRING);
26128d27 3556#endif
849a8357
SK
3557
3558 if (option == -1)
28866e95 3559 {
572b41eb
SK
3560 for (; optind < argc; optind++)
3561 {
3562 unsigned char *c = (unsigned char *)argv[optind];
3563 for (; *c != 0; c++)
3564 if (!isspace(*c))
3565 die(_("junk found in command line"), NULL, EC_BADCONF);
3566 }
28866e95
SK
3567 break;
3568 }
3569
849a8357
SK
3570 /* Copy optarg so that argv doesn't get changed */
3571 if (optarg)
3572 {
3573 strncpy(buff, optarg, MAXDNAME);
3574 buff[MAXDNAME-1] = 0;
3575 arg = buff;
9e4abcb5 3576 }
849a8357
SK
3577 else
3578 arg = NULL;
9e4abcb5 3579
849a8357 3580 /* command-line only stuff */
7622fc06
SK
3581 if (option == LOPT_TEST)
3582 testmode = 1;
3583 else if (option == 'w')
849a8357 3584 {
7622fc06 3585#ifdef HAVE_DHCP
4cb1b320 3586 if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
7622fc06 3587 display_opts();
4cb1b320
SK
3588#ifdef HAVE_DHCP6
3589 else if (argc == 3 && strcmp(argv[2], "dhcp6") == 0)
3590 display_opts6();
7622fc06 3591#endif
4cb1b320 3592 else
7622fc06 3593#endif
4cb1b320
SK
3594 do_usage();
3595
849a8357
SK
3596 exit(0);
3597 }
3598 else if (option == 'v')
3599 {
3600 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
c72daea8 3601 printf(_("Compile time options: %s\n\n"), compile_opts);
849a8357
SK
3602 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
3603 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
824af85b 3604 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
849a8357
SK
3605 exit(0);
3606 }
3607 else if (option == 'C')
3608 {
28866e95 3609 conffile_opt = 0; /* file must exist */
824af85b 3610 conffile = opt_string_alloc(arg);
849a8357
SK
3611 }
3612 else
3613 {
3614#ifdef HAVE_GETOPT_LONG
c4a7f90e 3615 if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
849a8357 3616#else
c4a7f90e 3617 if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
849a8357 3618#endif
c4a7f90e 3619 die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
849a8357
SK
3620 }
3621 }
3622
3623 if (conffile)
28866e95 3624 one_file(conffile, conffile_opt);
849a8357 3625
1a6bca81 3626 /* port might not be known when the address is parsed - fill in here */
3be34541 3627 if (daemon->servers)
9e4abcb5
SK
3628 {
3629 struct server *tmp;
3be34541 3630 for (tmp = daemon->servers; tmp; tmp = tmp->next)
9e4abcb5
SK
3631 if (!(tmp->flags & SERV_HAS_SOURCE))
3632 {
3633 if (tmp->source_addr.sa.sa_family == AF_INET)
3be34541 3634 tmp->source_addr.in.sin_port = htons(daemon->query_port);
9e4abcb5
SK
3635#ifdef HAVE_IPV6
3636 else if (tmp->source_addr.sa.sa_family == AF_INET6)
3be34541 3637 tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
5aabfc78
SK
3638#endif
3639 }
9e4abcb5
SK
3640 }
3641
3be34541 3642 if (daemon->if_addrs)
9e4abcb5
SK
3643 {
3644 struct iname *tmp;
3be34541 3645 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
9e4abcb5 3646 if (tmp->addr.sa.sa_family == AF_INET)
3be34541 3647 tmp->addr.in.sin_port = htons(daemon->port);
9e4abcb5
SK
3648#ifdef HAVE_IPV6
3649 else if (tmp->addr.sa.sa_family == AF_INET6)
3be34541 3650 tmp->addr.in6.sin6_port = htons(daemon->port);
9e4abcb5
SK
3651#endif /* IPv6 */
3652 }
3653
f6b7dc47 3654 /* only one of these need be specified: the other defaults to the host-name */
28866e95 3655 if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
9e4abcb5 3656 {
0a852541
SK
3657 struct mx_srv_record *mx;
3658
9e4abcb5 3659 if (gethostname(buff, MAXDNAME) == -1)
5aabfc78 3660 die(_("cannot get host-name: %s"), NULL, EC_MISC);
f6b7dc47 3661
0a852541
SK
3662 for (mx = daemon->mxnames; mx; mx = mx->next)
3663 if (!mx->issrv && hostname_isequal(mx->name, buff))
3664 break;
3665
28866e95 3666 if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
de37951c 3667 {
824af85b 3668 mx = opt_malloc(sizeof(struct mx_srv_record));
91dccd09
SK
3669 mx->next = daemon->mxnames;
3670 mx->issrv = 0;
3671 mx->target = NULL;
824af85b 3672 mx->name = opt_string_alloc(buff);
91dccd09 3673 daemon->mxnames = mx;
f6b7dc47 3674 }
9e4abcb5 3675
3be34541 3676 if (!daemon->mxtarget)
824af85b 3677 daemon->mxtarget = opt_string_alloc(buff);
0a852541
SK
3678
3679 for (mx = daemon->mxnames; mx; mx = mx->next)
3680 if (!mx->issrv && !mx->target)
3681 mx->target = daemon->mxtarget;
9e4abcb5 3682 }
f6b7dc47 3683
28866e95 3684 if (!option_bool(OPT_NO_RESOLV) &&
208b65c5
SK
3685 daemon->resolv_files &&
3686 daemon->resolv_files->next &&
28866e95 3687 option_bool(OPT_NO_POLL))
5aabfc78 3688 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
de37951c 3689
28866e95 3690 if (option_bool(OPT_RESOLV_DOMAIN))
de37951c
SK
3691 {
3692 char *line;
849a8357
SK
3693 FILE *f;
3694
28866e95 3695 if (option_bool(OPT_NO_RESOLV) ||
208b65c5
SK
3696 !daemon->resolv_files ||
3697 (daemon->resolv_files)->next)
5aabfc78 3698 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
de37951c 3699
3be34541 3700 if (!(f = fopen((daemon->resolv_files)->name, "r")))
5aabfc78 3701 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
de37951c
SK
3702
3703 while ((line = fgets(buff, MAXDNAME, f)))
3704 {
3705 char *token = strtok(line, " \t\n\r");
3706
3707 if (!token || strcmp(token, "search") != 0)
3708 continue;
3709
3710 if ((token = strtok(NULL, " \t\n\r")) &&
1f15b81d 3711 (daemon->domain_suffix = canonicalise_opt(token)))
de37951c
SK
3712 break;
3713 }
3be34541 3714
de37951c 3715 fclose(f);
8a911ccc 3716
3be34541 3717 if (!daemon->domain_suffix)
5aabfc78 3718 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
de37951c 3719 }
3d8df260
SK
3720
3721 if (daemon->domain_suffix)
3722 {
3723 /* add domain for any srv record without one. */
3724 struct mx_srv_record *srv;
de37951c 3725
3d8df260
SK
3726 for (srv = daemon->mxnames; srv; srv = srv->next)
3727 if (srv->issrv &&
3728 strchr(srv->name, '.') &&
3729 strchr(srv->name, '.') == strrchr(srv->name, '.'))
3730 {
3731 strcpy(buff, srv->name);
3732 strcat(buff, ".");
3733 strcat(buff, daemon->domain_suffix);
3734 free(srv->name);
824af85b 3735 srv->name = opt_string_alloc(buff);
3d8df260
SK
3736 }
3737 }
28866e95 3738 else if (option_bool(OPT_DHCP_FQDN))
9009d746 3739 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
7622fc06
SK
3740
3741 if (testmode)
3742 {
3743 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
3744 exit(0);
3745 }
849a8357 3746}