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