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