1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   This program is free software; you can redistribute it and/or modify
4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   it under the terms of the GNU General Public License as published by
5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   the Free Software Foundation; version 2 dated June, 1991, or
6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   (at your option) version 3 dated 29 June, 2007.
7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   This program is distributed in the hope that it will be useful,
9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   but WITHOUT ANY WARRANTY; without even the implied warranty of
10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   GNU General Public License for more details.
12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   You should have received a copy of the GNU General Public License
14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   along with this program.  If not, see <http://www.gnu.org/licenses/>.
15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/
16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* define this to get facilitynames */
18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define SYSLOG_NAMES
19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h"
20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include <setjmp.h>
21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic volatile int mem_recover = 0;
23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic jmp_buf mem_jmp;
24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void one_file(char *file, int nest, int hard_opt);
25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Solaris headers don't have facility names. */
27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOLARIS_NETWORK
28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic const struct {
29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *c_name;
30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned int c_val;
31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}  facilitynames[] = {
32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "kern",   LOG_KERN },
33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "user",   LOG_USER },
34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "mail",   LOG_MAIL },
35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "daemon", LOG_DAEMON },
36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "auth",   LOG_AUTH },
37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "syslog", LOG_SYSLOG },
38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "lpr",    LOG_LPR },
39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "news",   LOG_NEWS },
40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "uucp",   LOG_UUCP },
41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "audit",  LOG_AUDIT },
42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "cron",   LOG_CRON },
43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local0", LOG_LOCAL0 },
44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local1", LOG_LOCAL1 },
45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local2", LOG_LOCAL2 },
46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local3", LOG_LOCAL3 },
47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local4", LOG_LOCAL4 },
48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local5", LOG_LOCAL5 },
49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local6", LOG_LOCAL6 },
50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "local7", LOG_LOCAL7 },
51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { NULL, 0 }
52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat};
53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_GETOPT_LONG
56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct myoption {
57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  const char *name;
58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int has_arg;
59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int *flag;
60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int val;
61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat};
62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#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:"
65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* options which don't have a one-char version */
67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_RELOAD    256
68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_NO_NAMES  257
69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_TFTP      258
70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_SECURE    259
71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_PREFIX    260
72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_PTR       261
73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_BRIDGE    262
74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_TFTP_MAX  263
75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_FORCE     264
76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_NOBLOCK   265
77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_LOG_OPTS  266
78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_MAX_LOGS  267
79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_CIRCUIT   268
80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_REMOTE    269
81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_SUBSCR    270
82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_INTNAME   271
83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_BANK      272
84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_DHCP_HOST 273
85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_APREF     274
86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_OVERRIDE  275
87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_TFTPPORTS 276
88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_REBIND    277
89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_NOLAST    278
90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_OPTS      279
91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_DHCP_OPTS 280
92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_MATCH     281
93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_BROADCAST 282
94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_NEGTTL    283
95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_ALTPORT   284
96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_SCRIPTUSR 285
97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_LOCAL     286
98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_NAPTR     287
99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_MINPORT   288
100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_DHCP_FQDN 289
101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_CNAME     290
102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_PXE_PROMT 291
103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_PXE_SERV  292
104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define LOPT_TEST      293
105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_GETOPT_LONG
107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic const struct option opts[] =
108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic const struct myoption opts[] =
110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  {
112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "version", 0, 0, 'v' },
113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-hosts", 0, 0, 'h' },
114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-poll", 0, 0, 'n' },
115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "help", 0, 0, 'w' },
116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-daemon", 0, 0, 'd' },
117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "log-queries", 0, 0, 'q' },
118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "user", 2, 0, 'u' },
119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "group", 2, 0, 'g' },
120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "resolv-file", 2, 0, 'r' },
121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "mx-host", 1, 0, 'm' },
122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "mx-target", 1, 0, 't' },
123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "cache-size", 2, 0, 'c' },
124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "port", 1, 0, 'p' },
125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-leasefile", 2, 0, 'l' },
126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-lease", 1, 0, 'l' },
127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-host", 1, 0, 'G' },
128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-range", 1, 0, 'F' },
129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-option", 1, 0, 'O' },
130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-boot", 1, 0, 'M' },
131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "domain", 1, 0, 's' },
132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "domain-suffix", 1, 0, 's' },
133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "interface", 1, 0, 'i' },
134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "listen-address", 1, 0, 'a' },
135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "bogus-priv", 0, 0, 'b' },
136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "bogus-nxdomain", 1, 0, 'B' },
137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "selfmx", 0, 0, 'e' },
138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "filterwin2k", 0, 0, 'f' },
139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "pid-file", 2, 0, 'x' },
140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "strict-order", 0, 0, 'o' },
141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "server", 1, 0, 'S' },
142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "local", 1, 0, LOPT_LOCAL },
143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "address", 1, 0, 'A' },
144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "conf-file", 2, 0, 'C' },
145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-resolv", 0, 0, 'R' },
146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "expand-hosts", 0, 0, 'E' },
147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "localmx", 0, 0, 'L' },
148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "local-ttl", 1, 0, 'T' },
149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-negcache", 0, 0, 'N' },
150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "addn-hosts", 1, 0, 'H' },
151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "query-port", 1, 0, 'Q' },
152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "except-interface", 1, 0, 'I' },
153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-dhcp-interface", 1, 0, '2' },
154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "domain-needed", 0, 0, 'D' },
155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-lease-max", 1, 0, 'X' },
156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "bind-interfaces", 0, 0, 'z' },
157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "read-ethers", 0, 0, 'Z' },
158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "alias", 1, 0, 'V' },
159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-vendorclass", 1, 0, 'U' },
160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-userclass", 1, 0, 'j' },
161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-ignore", 1, 0, 'J' },
162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "edns-packet-max", 1, 0, 'P' },
163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "keep-in-foreground", 0, 0, 'k' },
164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-authoritative", 0, 0, 'K' },
165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "srv-host", 1, 0, 'W' },
166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "localise-queries", 0, 0, 'y' },
167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "txt-record", 1, 0, 'Y' },
168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "enable-dbus", 0, 0, '1' },
169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "bootp-dynamic", 2, 0, '3' },
170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-mac", 1, 0, '4' },
171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "no-ping", 0, 0, '5' },
172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-script", 1, 0, '6' },
173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "conf-dir", 1, 0, '7' },
174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "log-facility", 1, 0 ,'8' },
175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "leasefile-ro", 0, 0, '9' },
176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dns-forward-max", 1, 0, '0' },
177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "clear-on-reload", 0, 0, LOPT_RELOAD },
178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "enable-tftp", 0, 0, LOPT_TFTP },
180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "tftp-secure", 0, 0, LOPT_SECURE },
181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "tftp-unique-root", 0, 0, LOPT_APREF },
182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "tftp-root", 1, 0, LOPT_PREFIX },
183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "tftp-max", 1, 0, LOPT_TFTP_MAX },
184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "ptr-record", 1, 0, LOPT_PTR },
185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "naptr-record", 1, 0, LOPT_NAPTR },
186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "bridge-interface", 1, 0 , LOPT_BRIDGE },
187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-option-force", 1, 0, LOPT_FORCE },
188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "log-async", 2, 0, LOPT_MAX_LOGS },
191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "interface-name", 1, 0, LOPT_INTNAME },
195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "stop-dns-rebind", 0, 0, LOPT_REBIND },
200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "all-servers", 0, 0, LOPT_NOLAST },
201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-match", 1, 0, LOPT_MATCH },
202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-broadcast", 1, 0, LOPT_BROADCAST },
203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "neg-ttl", 1, 0, LOPT_NEGTTL },
204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "min-port", 1, 0, LOPT_MINPORT },
207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "cname", 1, 0, LOPT_CNAME },
209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "pxe-service", 1, 0, LOPT_PXE_SERV },
211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { "test", 0, 0, LOPT_TEST },
212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { NULL, 0, 0, 0 }
213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  };
214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* These must have more the one '1' bit */
216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define ARG_DUP       3
217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define ARG_ONE       5
218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define ARG_USED_CL   7
219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define ARG_USED_FILE 9
220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct {
222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int opt;
223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned int rept;
224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char * const flagdesc;
225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char * const desc;
226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char * const arg;
227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} usage[] = {
228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'a', ARG_DUP, "ipaddr",  gettext_noop("Specify local address(es) to listen on."), NULL },
229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL },
244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'j', ARG_DUP, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'U', ARG_DUP, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL },
288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_MATCH, ARG_DUP, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { 0, 0, NULL, NULL, NULL }
327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat};
328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* makes options which take a list of addresses */
331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define OT_ADDR_LIST 0x80
332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* DHCP-internal options, for logging. not valid in config file */
333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define OT_INTERNAL 0x40
334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define OT_NAME 0x20
335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic const struct {
337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *name;
338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned char val, size;
339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} opttab[] = {
340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "netmask", 1, OT_ADDR_LIST },
341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "time-offset", 2, 4 },
342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "router", 3, OT_ADDR_LIST  },
343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "dns-server", 6, OT_ADDR_LIST },
344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "log-server", 7, OT_ADDR_LIST },
345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "lpr-server", 9, OT_ADDR_LIST },
346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "hostname", 12, OT_INTERNAL | OT_NAME },
347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "boot-file-size", 13, 2 },
348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "domain-name", 15, OT_NAME },
349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "swap-server", 16, OT_ADDR_LIST },
350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "root-path", 17, 0 },
351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "extension-path", 18, 0 },
352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "ip-forward-enable", 19, 1 },
353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "non-local-source-routing", 20, 1 },
354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "policy-filter", 21, OT_ADDR_LIST },
355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "max-datagram-reassembly", 22, 2 },
356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "default-ttl", 23, 1 },
357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "mtu", 26, 2 },
358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "all-subnets-local", 27, 1 },
359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "router-discovery", 31, 1 },
361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "router-solicitation", 32, OT_ADDR_LIST },
362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "static-route", 33, OT_ADDR_LIST },
363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "trailer-encapsulation", 34, 1 },
364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "arp-timeout", 35, 4 },
365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "ethernet-encap", 36, 1 },
366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "tcp-ttl", 37, 1 },
367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "tcp-keepalive", 38, 4 },
368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "nis-domain", 40, 0 },
369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "nis-server", 41, OT_ADDR_LIST },
370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "ntp-server", 42, OT_ADDR_LIST },
371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "vendor-encap", 43, OT_INTERNAL },
372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "netbios-ns", 44, OT_ADDR_LIST },
373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "netbios-dd", 45, OT_ADDR_LIST },
374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "netbios-nodetype", 46, 1 },
375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "netbios-scope", 47, 0 },
376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "x-windows-fs", 48, OT_ADDR_LIST },
377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "x-windows-dm", 49, OT_ADDR_LIST },
378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "lease-time", 51, OT_INTERNAL },
380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "option-overload", 52, OT_INTERNAL },
381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "message-type", 53, OT_INTERNAL, },
382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "parameter-request", 55, OT_INTERNAL },
384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "message", 56, OT_INTERNAL },
385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "max-message-size", 57, OT_INTERNAL },
386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "T1", 58, OT_INTERNAL },
387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "T2", 59, OT_INTERNAL },
388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "vendor-class", 60, 0 },
389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "client-id", 61,OT_INTERNAL },
390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "nis+-domain", 64, 0 },
391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "nis+-server", 65, OT_ADDR_LIST },
392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "tftp-server", 66, 0 },
393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "bootfile-name", 67, 0 },
394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "mobile-ip-home", 68, OT_ADDR_LIST },
395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "smtp-server", 69, OT_ADDR_LIST },
396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "pop3-server", 70, OT_ADDR_LIST },
397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "nntp-server", 71, OT_ADDR_LIST },
398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "irc-server", 74, OT_ADDR_LIST },
399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "user-class", 77, 0 },
400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "FQDN", 81, OT_INTERNAL },
401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "agent-id", 82, OT_INTERNAL },
402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "client-arch", 93, 2 },
403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "client-interface-id", 94, 0 },
404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "client-machine-id", 97, 0 },
405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "subnet-select", 118, OT_INTERNAL },
406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "domain-search", 119, 0 },
407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "sip-server", 120, 0 },
408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "classless-static-route", 121, 0 },
409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  { NULL, 0, 0 }
411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat};
412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatchar *option_string(unsigned char opt, int *is_ip, int *is_name)
414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i;
416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0; opttab[i].name; i++)
418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (opttab[i].val == opt)
419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (is_ip)
421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  *is_ip = !!(opttab[i].size & OT_ADDR_LIST);
422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (is_name)
423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  *is_name = !!(opttab[i].size & OT_NAME);
424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return opttab[i].name;
425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return NULL;
428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* We hide metacharaters in quoted strings by mapping them into the ASCII control
433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   following sequence so that they map to themselves: it is therefore possible to call
435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   unhide_metas repeatedly on string without breaking things.
436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   couple of other places.
438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   Note that space is included here so that
439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   --dhcp-option=3, string
440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   has five characters, whilst
441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   --dhcp-option=3," string"
442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   has six.
443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/
444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char hide_meta(char c)
448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned int i;
450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0; i < (sizeof(meta) - 1); i++)
452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (c == meta[i])
453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      return (char)i;
454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return c;
456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char unhide_meta(char cr)
459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned int c = cr;
461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (c < (sizeof(meta) - 1))
463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    cr = meta[c];
464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return cr;
466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void unhide_metas(char *cp)
469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (cp)
471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for(; *cp; cp++)
472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      *cp = unhide_meta(*cp);
473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void *opt_malloc(size_t size)
476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  void *ret;
478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (mem_recover)
480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      ret = whine_malloc(size);
482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!ret)
483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	longjmp(mem_jmp, 1);
484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    ret = safe_malloc(size);
487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return ret;
489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *opt_string_alloc(char *cp)
492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *ret = NULL;
494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (cp && strlen(cp) != 0)
496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      ret = opt_malloc(strlen(cp)+1);
498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      strcpy(ret, cp);
499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* restore hidden metachars */
501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      unhide_metas(ret);
502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return ret;
505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* find next comma, split string with zero and eliminate spaces.
509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   return start of string following comma */
510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *split_chr(char *s, char c)
512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *comma, *p;
514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!s || !(comma = strchr(s, c)))
516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return NULL;
517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  p = comma;
519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  *comma = ' ';
520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (; isspace((int)*comma); comma++);
522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (; (p >= s) && isspace((int)*p); p--)
524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    *p = 0;
525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return comma;
527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *split(char *s)
530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return split_chr(s, ',');
532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *canonicalise_opt(char *s)
535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *ret;
537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int nomem;
538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!s)
540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 0;
541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unhide_metas(s);
543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(ret = canonicalise(s, &nomem)) && nomem)
544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (mem_recover)
546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	longjmp(mem_jmp, 1);
547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("could not get memory"), NULL, EC_NOMEM);
549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return ret;
552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int atoi_check(char *a, int *res)
555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *p;
557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!a)
559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 0;
560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unhide_metas(a);
562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (p = a; *p; p++)
564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     if (*p < '0' || *p > '9')
565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       return 0;
566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  *res = atoi(a);
568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int atoi_check16(char *a, int *res)
572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(atoi_check(a, res)) ||
574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      *res < 0 ||
575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      *res > 0xffff)
576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 0;
577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void add_txt(char *name, char *txt)
582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  size_t len = strlen(txt);
584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct txt_record *r = opt_malloc(sizeof(struct txt_record));
585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  r->name = opt_string_alloc(name);
587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  r->next = daemon->txt;
588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->txt = r;
589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  r->class = C_CHAOS;
590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  r->txt = opt_malloc(len+1);
591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  r->len = len+1;
592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  *(r->txt) = len;
593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  memcpy((r->txt)+1, txt, len);
594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void do_usage(void)
597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char buff[100];
599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i, j;
600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct {
602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    char handle;
603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    int val;
604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  } tab[] = {
605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { '$', CACHESIZ },
606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { '*', EDNS_PKTSZ },
607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { '&', MAXLEASES },
608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { '!', FTABSIZ },
609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { '#', TFTP_MAX_CONNECTIONS },
610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    { '\0', 0 }
611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  };
612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  printf(_("Usage: dnsmasq [options]\n\n"));
614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_GETOPT_LONG
615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  printf(_("Use short options only on the command line.\n"));
616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  printf(_("Valid options are:\n"));
618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0; usage[i].opt != 0; i++)
620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      char *desc = usage[i].flagdesc;
622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      char *eq = "=";
623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!desc || *desc == '[')
625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	eq = "";
626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!desc)
628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	desc = "";
629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for ( j = 0; opts[j].name; j++)
631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (opts[j].val == usage[i].opt)
632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (usage[i].opt < 256)
634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	sprintf(buff, "-%c, ", usage[i].opt);
635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	sprintf(buff, "    ");
637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      printf("%-36.36s", buff);
640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (usage[i].arg)
642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
643ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  strcpy(buff, usage[i].arg);
644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (j = 0; tab[j].handle; j++)
645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (tab[j].handle == *(usage[i].arg))
646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      sprintf(buff, "%d", tab[j].val);
647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      printf(_(usage[i].desc), buff);
649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      printf("\n");
650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void display_opts(void)
655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i;
657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  printf(_("Known DHCP options:\n"));
659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0; opttab[i].name; i++)
661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (!(opttab[i].size & OT_INTERNAL))
662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      printf("%3d %s\n", opttab[i].val, opttab[i].name);
663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* This is too insanely large to keep in-line in the switch */
666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *parse_dhcp_opt(char *arg, int flags)
667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char lenchar = 0, *cp;
670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *comma = NULL, *problem = NULL;
672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct dhcp_netid *np = NULL;
673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned char opt_len = 0;
674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  new->len = 0;
676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  new->flags = flags;
677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  new->netid = NULL;
678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  new->val = NULL;
679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  new->opt = 0;
680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (arg)
682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      comma = split(arg);
684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (cp = arg; *cp; cp++)
686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (*cp < '0' || *cp > '9')
687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
688ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
689ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!*cp)
690ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
691ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->opt = atoi(arg);
692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  opt_len = 0;
693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (strstr(arg, "option:") == arg)
697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (i = 0; opttab[i].name; i++)
699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!(opttab[i].size & OT_INTERNAL) &&
700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		strcasecmp(opttab[i].name, arg+7) == 0)
701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->opt = opttab[i].val;
703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		opt_len = opttab[i].size;
704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* option:<optname> must follow tag and vendor string. */
707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
708ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (strstr(arg, "vendor:") == arg)
710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->flags |= DHOPT_VENDOR;
713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (strstr(arg, "encap:") == arg)
715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->u.encap = atoi(arg+6);
717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->flags |= DHOPT_ENCAPSULATE;
718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->netid = opt_malloc(sizeof (struct dhcp_netid));
722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* allow optional "net:" for consistency */
723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (strstr(arg, "net:") == arg)
724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->netid->net = opt_string_alloc(arg+4);
725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->netid->net = opt_string_alloc(arg);
727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->netid->next = np;
728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  np = new->netid;
729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      arg = comma;
732ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
733ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
734ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (new->opt == 0)
735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    problem = _("bad dhcp-option");
736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (comma)
737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
738ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* characterise the value */
739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      char c;
740ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      is_addr = is_hex = is_dec = is_string = 1;
741ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      addrs = digs = 1;
742ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      dots = 0;
743ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (cp = comma; (c = *cp); cp++)
744ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (c == ',')
745ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
746ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    addrs++;
747ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    is_dec = is_hex = 0;
748ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
749ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (c == ':')
750ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
751ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    digs++;
752ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    is_dec = is_addr = 0;
753ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
754ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (c == '/')
755ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
756ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    is_dec = is_hex = 0;
757ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (cp == comma) /* leading / means a pathname */
758ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      is_addr = 0;
759ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
760ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (c == '.')
761ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
762ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    is_dec = is_hex = 0;
763ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    dots++;
764ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
765ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (c == '-')
766ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  is_hex = is_addr = 0;
767ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (c == ' ')
768ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  is_dec = is_hex = 0;
769ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (!(c >='0' && c <= '9'))
770ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
771ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    is_addr = 0;
772ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (cp[1] == 0 && is_dec &&
773ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		(c == 'b' || c == 's' || c == 'i'))
774ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
775ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		lenchar = c;
776ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		*cp = 0;
777ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
778ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
779ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      is_dec = 0;
780ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!((c >='A' && c <= 'F') ||
781ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  (c >='a' && c <= 'f') ||
782ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  (c == '*' && (flags & DHOPT_MATCH))))
783ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      is_hex = 0;
784ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
785ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
786ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* We know that some options take addresses */
787ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
788ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (opt_len & OT_ADDR_LIST)
789ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
790ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  is_string = is_dec = is_hex = 0;
791ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!is_addr || dots == 0)
792ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    problem = _("bad IP address");
793ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
794ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
795ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (is_hex && digs > 1)
796ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
797ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->len = digs;
798ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->val = opt_malloc(new->len);
799ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
800ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->flags |= DHOPT_HEX;
801ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
802ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (is_dec)
803ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
804ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  int i, val = atoi(comma);
805ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* assume numeric arg is 1 byte except for
806ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     options where it is known otherwise.
807ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     For vendor class option, we have to hack. */
808ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (opt_len != 0)
809ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = opt_len;
810ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (val & 0xffff0000)
811ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 4;
812ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (val & 0xff00)
813ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 2;
814ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
815ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 1;
816ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
817ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (lenchar == 'b')
818ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 1;
819ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (lenchar == 's')
820ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 2;
821ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (lenchar == 'i')
822ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 4;
823ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
824ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->val = opt_malloc(new->len);
825ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (i=0; i<new->len; i++)
826ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->val[i] = val>>((new->len - i - 1)*8);
827ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
828ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (is_addr)
829ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
830ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  struct in_addr in;
831ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  unsigned char *op;
832ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  char *slash;
833ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* max length of address/subnet descriptor is five bytes,
834ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     add one for the option 120 enc byte too */
835ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->val = op = opt_malloc((5 * addrs) + 1);
836ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->flags |= DHOPT_ADDR;
837ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
838ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!(new->flags & DHOPT_ENCAPSULATE) && new->opt == 120)
839ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
840ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *(op++) = 1; /* RFC 3361 "enc byte" */
841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->flags &= ~DHOPT_ADDR;
842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  while (addrs--)
844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      cp = comma;
846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      comma = split(cp);
847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      slash = split_chr(cp, '/');
848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      in.s_addr = inet_addr(cp);
849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (!slash)
850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  memcpy(op, &in, INADDRSZ);
852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  op += INADDRSZ;
853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  unsigned char *p = (unsigned char *)&in;
857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  int netsize = atoi(slash);
858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  *op++ = netsize;
859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (netsize > 0)
860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *op++ = *p++;
861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (netsize > 8)
862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *op++ = *p++;
863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (netsize > 16)
864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *op++ = *p++;
865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (netsize > 24)
866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *op++ = *p++;
867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->len = op - new->val;
871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (is_string)
873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* text arg */
875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((new->opt == 119 || new->opt == 120) && !(new->flags & DHOPT_ENCAPSULATE))
876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* dns search, RFC 3397, or SIP, RFC 3361 */
878ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      unsigned char *q, *r, *tail;
879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      unsigned char *p, *m = NULL, *newp;
880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      size_t newlen, len = 0;
881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      int header_size = (new->opt == 119) ? 0 : 1;
882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      arg = comma;
884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      comma = split(arg);
885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      while (arg && *arg)
887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  char *dom;
889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (!(dom = arg = canonicalise_opt(arg)))
890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      problem = _("bad domain in dhcp-option");
892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      break;
893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  newp = opt_malloc(len + strlen(arg) + 2 + header_size);
896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (m)
897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    memcpy(newp, m, header_size + len);
898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  m = newp;
899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  p = m + header_size;
900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  q = p + len;
901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  /* add string on the end in RFC1035 format */
903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  while (*arg)
904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      unsigned char *cp = q++;
906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      int j;
907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      for (j = 0; *arg && (*arg != '.'); arg++, j++)
908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			*q++ = *arg;
909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      *cp = j;
910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if (*arg)
911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			arg++;
912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  *q++ = 0;
914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  free(dom);
915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  /* Now tail-compress using earlier names. */
917ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  newlen = q - p;
918ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  for (tail = p + len; *tail; tail += (*tail) + 1)
919ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    for (r = p; r - p < (int)len; r += (*r) + 1)
920ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if (strcmp((char *)r, (char *)tail) == 0)
921ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			{
922ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  PUTSHORT((r - p) | 0xc000, tail);
923ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  newlen = tail - p;
924ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  goto end;
925ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
926ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		end:
927ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  len = newlen;
928ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
929ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  arg = comma;
930ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  comma = split(arg);
931ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
932ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
933ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* RFC 3361, enc byte is zero for names */
934ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (new->opt == 120)
935ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		m[0] = 0;
936ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->len = (int) len + header_size;
937ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->val = m;
938ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
939ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
940ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
941ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->len = strlen(comma);
942ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* keep terminating zero on string */
943ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->val = (unsigned char *)opt_string_alloc(comma);
944ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->flags |= DHOPT_STRING;
945ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
946ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
947ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
948ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
949ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if ((new->len > 255) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
950ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    problem = _("dhcp-option too long");
951ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
952ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!problem)
953ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
954ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (flags == DHOPT_MATCH)
955ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
956ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
957ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      !new->netid ||
958ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->netid->next)
959ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    problem = _("illegal dhcp-match");
960ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
961ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
962ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->next = daemon->dhcp_match;
963ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      daemon->dhcp_match = new;
964ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
965ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
966ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
967ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
968ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->next = daemon->dhcp_opts;
969ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->dhcp_opts = new;
970ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
971ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
972ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
973ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return problem;
974ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
975ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
976ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
977ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
978ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *one_opt(int option, char *arg, char *gen_prob, int nest)
979ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
980ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i;
981ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *comma, *problem = NULL;;
982ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
983ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (option == '?')
984ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return gen_prob;
985ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
986ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i=0; usage[i].opt != 0; i++)
987ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (usage[i].opt == option)
988ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
989ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 int rept = usage[i].rept;
990ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
991ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 if (nest == 0)
992ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
993ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     /* command line */
994ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     if (rept == ARG_USED_CL)
995ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       return _("illegal repeated flag");
996ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     if (rept == ARG_ONE)
997ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       usage[i].rept = ARG_USED_CL;
998ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
999ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 else
1000ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
1001ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     /* allow file to override command line */
1002ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     if (rept == ARG_USED_FILE)
1003ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       return _("illegal repeated keyword");
1004ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     if (rept == ARG_USED_CL || rept == ARG_ONE)
1005ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       usage[i].rept = ARG_USED_FILE;
1006ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
1007ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1008ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
1009ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
1010ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     daemon->options |= rept;
1011ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     return NULL;
1012ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
1013ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1014ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 break;
1015ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1016ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1017ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  switch (option)
1018ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1019ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'C': /* --conf-file */
1020ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1021ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *file = opt_string_alloc(arg);
1022ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (file)
1023ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1024ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    one_file(file, nest, 0);
1025ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    free(file);
1026ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1027ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1028ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1029ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1030ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '7': /* --conf-dir */
1031ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1032ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	DIR *dir_stream;
1033ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dirent *ent;
1034ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *directory, *path;
1035ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct list {
1036ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  char *suffix;
1037ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  struct list *next;
1038ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	} *ignore_suffix = NULL, *li;
1039ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1040ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
1041ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(directory = opt_string_alloc(arg)))
1042ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
1043ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1044ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for (arg = comma; arg; arg = comma)
1045ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1046ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    comma = split(arg);
1047ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    li = opt_malloc(sizeof(struct list));
1048ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    li->next = ignore_suffix;
1049ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    ignore_suffix = li;
1050ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* Have to copy: buffer is overwritten */
1051ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    li->suffix = opt_string_alloc(arg);
1052ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  };
1053ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1054ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(dir_stream = opendir(directory)))
1055ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  die(_("cannot access directory %s: %s"), directory, EC_FILE);
1056ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1057ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while ((ent = readdir(dir_stream)))
1058ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1059ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    size_t len = strlen(ent->d_name);
1060ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct stat buf;
1061ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1062ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* ignore emacs backups and dotfiles */
1063ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (len == 0 ||
1064ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		ent->d_name[len - 1] == '~' ||
1065ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
1066ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		ent->d_name[0] == '.')
1067ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      continue;
1068ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1069ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    for (li = ignore_suffix; li; li = li->next)
1070ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1071ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		/* check for proscribed suffices */
1072ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		size_t ls = strlen(li->suffix);
1073ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (len > ls &&
1074ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
1075ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  break;
1076ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1077ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (li)
1078ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      continue;
1079ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1080ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    path = opt_malloc(strlen(directory) + len + 2);
1081ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strcpy(path, directory);
1082ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strcat(path, "/");
1083ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strcat(path, ent->d_name);
1084ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1085ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (stat(path, &buf) == -1)
1086ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      die(_("cannot access %s: %s"), path, EC_FILE);
1087ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* only reg files allowed. */
1088ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!S_ISREG(buf.st_mode))
1089ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      continue;
1090ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1091ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* dir is one level, so files must be readable */
1092ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    one_file(path, nest + 1, 0);
1093ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    free(path);
1094ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1095ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1096ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	closedir(dir_stream);
1097ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	free(directory);
1098ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for(; ignore_suffix; ignore_suffix = li)
1099ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    li = ignore_suffix->next;
1101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    free(ignore_suffix->suffix);
1102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    free(ignore_suffix);
1103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '8': /* --log-facility */
1109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* may be a filename */
1110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (strchr(arg, '/'))
1111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->log_file = opt_string_alloc(arg);
1112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
11135658bcb797978c3472335d93554405aba8236f66San Mehat	{
11145658bcb797978c3472335d93554405aba8236f66San Mehat#ifdef __ANDROID__
11155658bcb797978c3472335d93554405aba8236f66San Mehat	    problem = "Android does not support log facilities";
11165658bcb797978c3472335d93554405aba8236f66San Mehat#else
1117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (i = 0; facilitynames[i].c_name; i++)
1118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (hostname_isequal((char *)facilitynames[i].c_name, arg))
1119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      break;
1120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (facilitynames[i].c_name)
1122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->log_fac = facilitynames[i].c_val;
1123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
1124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    problem = "bad log facility";
11255658bcb797978c3472335d93554405aba8236f66San Mehat#endif
1126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'x': /* --pid-file */
1130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->runfile = opt_string_alloc(arg);
1131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_DHCP_HOST: /* --dhcp-hostfile */
1134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->dhcp_hosts_file)
1135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	problem = _("only one dhcp-hostsfile allowed");
1136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
1137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->dhcp_hosts_file = opt_string_alloc(arg);
1138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
1141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->dhcp_opts_file)
1142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	problem = _("only one dhcp-optsfile allowed");
1143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
1144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->dhcp_opts_file = opt_string_alloc(arg);
1145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'r': /* --resolv-file */
1148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *name = opt_string_alloc(arg);
1150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct resolvc *new, *list = daemon->resolv_files;
1151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (list && list->is_default)
1153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* replace default resolv file - possibly with nothing */
1155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (name)
1156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		list->is_default = 0;
1158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		list->name = name;
1159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
1161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      list = NULL;
1162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (name)
1164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new = opt_malloc(sizeof(struct resolvc));
1166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = list;
1167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->name = name;
1168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->is_default = 0;
1169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->mtime = 0;
1170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->logged = 0;
1171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    list = new;
1172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->resolv_files = list;
1174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'm':  /* --mx-host */
1178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int pref = 1;
1180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct mx_srv_record *new;
1181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *name, *target = NULL;
1182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((comma = split(arg)))
1184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *prefstr;
1186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
1187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      problem = _("bad MX preference");
1188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(name = canonicalise_opt(arg)) ||
1191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    (comma && !(target = canonicalise_opt(comma))))
1192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  problem = _("bad MX name");
1193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new = opt_malloc(sizeof(struct mx_srv_record));
1195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->mxnames;
1196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->mxnames = new;
1197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->issrv = 0;
1198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->name = name;
1199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->target = target; /* may be NULL */
1200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->weight = pref;
1201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 't': /*  --mx-target */
1205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!(daemon->mxtarget = canonicalise_opt(arg)))
1206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	problem = _("bad MX target");
1207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
1210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'l':  /* --dhcp-leasefile */
1211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->lease_file = opt_string_alloc(arg);
1212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '6': /* --dhcp-script */
1215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  if defined(NO_FORK)
1216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      problem = _("cannot run scripts under uClinux");
1217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  elif !defined(HAVE_SCRIPT)
1218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  else
1220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->lease_change_command = opt_string_alloc(arg);
1221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  endif
1222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'H': /* --addn-hosts */
1226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
1228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	static int hosts_index = 1;
1229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->fname = opt_string_alloc(arg);
1230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->index = hosts_index++;
1231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->flags = 0;
1232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->addn_hosts;
1233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->addn_hosts = new;
1234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 's': /* --domain */
1238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (strcmp (arg, "#") == 0)
1239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->options |= OPT_RESOLV_DOMAIN;
1240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
1241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  char *d;
1243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  comma = split(arg);
1244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!(d = canonicalise_opt(arg)))
1245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    option = '?';
1246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
1247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (comma)
1249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
1251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  unhide_metas(comma);
1252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if ((arg = split_chr(comma, '/')))
1253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      int mask;
1255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  !atoi_check(arg, &mask))
1257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			option = '?';
1258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else
1259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			{
1260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  mask = (1 << (32 - mask)) - 1;
1261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
1262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  new->end.s_addr = new->start.s_addr | htonl(mask);
1263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
1264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  else if ((arg = split(comma)))
1266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
1268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
1269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			option = '?';
1270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    option = '?';
1273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  new->domain = d;
1275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  new->next = daemon->cond_domain;
1276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  daemon->cond_domain = new;
1277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
1279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->domain_suffix = d;
1280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'u':  /* --user */
1285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->username = opt_string_alloc(arg);
1286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'g':  /* --group */
1289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->groupname = opt_string_alloc(arg);
1290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->group_set = 1;
1291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
1294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_SCRIPTUSR: /* --scriptuser */
1295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->scriptuser = opt_string_alloc(arg);
1296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'i':  /* --interface */
1300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      do {
1301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct iname *new = opt_malloc(sizeof(struct iname));
1302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
1303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->if_names;
1304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->if_names = new;
1305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* new->name may be NULL if someone does
1306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   "interface=" to disable all interfaces except loop. */
1307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->name = opt_string_alloc(arg);
1308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->isloop = new->used = 0;
1309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	arg = comma;
1310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      } while (arg);
1311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'I':  /* --except-interface */
1314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '2':  /* --no-dhcp-interface */
1315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      do {
1316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct iname *new = opt_malloc(sizeof(struct iname));
1317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
1318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->name = opt_string_alloc(arg);
1319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (option == 'I')
1320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->if_except;
1322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->if_except = new;
1323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->dhcp_except;
1327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->dhcp_except = new;
1328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	arg = comma;
1330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      } while (arg);
1331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'B':  /* --bogus-nxdomain */
1334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct in_addr addr;
1336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	unhide_metas(arg);
1337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
1340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    baddr->next = daemon->bogus_addr;
1341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->bogus_addr = baddr;
1342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    baddr->addr = addr;
1343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?'; /* error */
1346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'a':  /* --listen-address */
1350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      do {
1351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct iname *new = opt_malloc(sizeof(struct iname));
1352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
1353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	unhide_metas(arg);
1354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->if_addrs;
1355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
1356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->addr.sa.sa_family = AF_INET;
1358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN
1359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->addr.in.sin_len = sizeof(new->addr.in);
1360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
1363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
1364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->addr.sa.sa_family = AF_INET6;
1366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->addr.in6.sin6_flowinfo = 0;
1367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->addr.in6.sin6_scope_id = 0;
1368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN
1369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->addr.in6.sin6_len = sizeof(new->addr.in6);
1370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    option = '?'; /* error */
1376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    break;
1377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->if_addrs = new;
1380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	arg = comma;
1381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      } while (arg);
1382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'S':        /*  --server */
1385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_LOCAL: /*  --local */
1386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'A':        /*  --address */
1387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct server *serv, *newlist = NULL;
1389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	unhide_metas(arg);
1391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (arg && *arg == '/')
1393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *end;
1395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    arg++;
1396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    while ((end = split_chr(arg, '/')))
1397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		char *domain = NULL;
1399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		/* # matches everything and becomes a zero length domain string */
1400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (strcmp(arg, "#") == 0)
1401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  domain = "";
1402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
1403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  option = '?';
1404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		serv = opt_malloc(sizeof(struct server));
1405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		memset(serv, 0, sizeof(struct server));
1406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		serv->next = newlist;
1407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist = serv;
1408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		serv->domain = domain;
1409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
1410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		arg = end;
1411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!newlist)
1413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		option = '?';
1415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
1416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    newlist = opt_malloc(sizeof(struct server));
1422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    memset(newlist, 0, sizeof(struct server));
1423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (option == 'A')
1426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    newlist->flags |= SERV_LITERAL_ADDRESS;
1428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!(newlist->flags & SERV_TYPE))
1429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      option = '?';
1430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!arg || !*arg)
1433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    newlist->flags |= SERV_NO_ADDR; /* no server */
1435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (newlist->flags & SERV_LITERAL_ADDRESS)
1436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      option = '?';
1437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    int source_port = 0, serv_port = NAMESERVER_PORT;
1441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *portno, *source;
1442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if ((source = split_chr(arg, '@')) && /* is there a source. */
1444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		(portno = split_chr(source, '#')) &&
1445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		!atoi_check16(portno, &source_port))
1446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      problem = _("bad port");
1447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if ((portno = split_chr(arg, '#')) && /* is there a port no. */
1449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		!atoi_check16(portno, &serv_port))
1450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      problem = _("bad port");
1451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
1453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->addr.in.sin_port = htons(serv_port);
1455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->source_addr.in.sin_port = htons(source_port);
1456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
1457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN
1458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
1459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (source)
1461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    newlist->flags |= SERV_HAS_SOURCE;
1463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
1464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      {
1465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(SO_BINDTODEVICE)
1466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			strncpy(newlist->interface, source, IF_NAMESIZE);
1468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
1469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			problem = _("interface binding not supported");
1470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      }
1472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		else
1474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
1475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
1477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
1478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->addr.in6.sin6_port = htons(serv_port);
1480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->source_addr.in6.sin6_port = htons(source_port);
1481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
1482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN
1483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
1484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (source)
1486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     newlist->flags |= SERV_HAS_SOURCE;
1488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
1489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      {
1490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(SO_BINDTODEVICE)
1491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			newlist->source_addr.in6.sin6_addr = in6addr_any;
1492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			strncpy(newlist->interface, source, IF_NAMESIZE);
1493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
1494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			problem = _("interface binding not supported");
1495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      }
1497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		else
1499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  newlist->source_addr.in6.sin6_addr = in6addr_any;
1500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
1503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      option = '?'; /* error */
1504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	serv = newlist;
1508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while (serv->next)
1509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    serv->next->flags = serv->flags;
1511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    serv->next->addr = serv->addr;
1512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    serv->next->source_addr = serv->source_addr;
1513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    serv = serv->next;
1514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	serv->next = daemon->servers;
1516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->servers = newlist;
1517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'c':  /* --cache-size */
1521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int size;
1523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!atoi_check(arg, &size))
1525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
1526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* zero is OK, and means no caching. */
1529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (size < 0)
1531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      size = 0;
1532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else if (size > 10000)
1533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      size = 10000;
1534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->cachesize = size;
1536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'p':  /* --port */
1541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!atoi_check16(arg, &daemon->port))
1542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_MINPORT:  /* --min-port */
1546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!atoi_check16(arg, &daemon->min_port))
1547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '0':  /* --dns-forward-max */
1551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!atoi_check(arg, &daemon->ftabsize))
1552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_MAX_LOGS:  /* --log-async */
1556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->max_logs = LOG_MAX; /* default */
1557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (arg && !atoi_check(arg, &daemon->max_logs))
1558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (daemon->max_logs > 100)
1560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->max_logs = 100;
1561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'P': /* --edns-packet-max */
1564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int i;
1566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!atoi_check(arg, &i))
1567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
1568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->edns_pktsz = (unsigned short)i;
1569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'Q':  /* --query-port */
1573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!atoi_check16(arg, &daemon->query_port))
1574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* if explicitly set to zero, use single OS ephemeral port
1576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 and disable random ports */
1577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->query_port == 0)
1578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->osport = 1;
1579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'T':         /* --local-ttl */
1582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_NEGTTL: /* --neg-ttl */
1583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int ttl;
1585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!atoi_check(arg, &ttl))
1586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
1587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (option == LOPT_NEGTTL)
1588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->neg_ttl = (unsigned long)ttl;
1589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->local_ttl = (unsigned long)ttl;
1591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
1595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'X': /* --dhcp-lease-max */
1596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!atoi_check(arg, &daemon->dhcp_max))
1597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
1602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_TFTP_MAX:  /*  --tftp-max */
1603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!atoi_check(arg, &daemon->tftp_max))
1604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = '?';
1605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_PREFIX: /* --tftp-prefix */
1608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->tftp_prefix = opt_string_alloc(arg);
1609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_TFTPPORTS: /* --tftp-port-range */
1612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!(comma = split(arg)) ||
1613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  !atoi_check16(arg, &daemon->start_tftp_port) ||
1614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  !atoi_check16(comma, &daemon->end_tftp_port))
1615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	problem = _("bad port range");
1616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->start_tftp_port > daemon->end_tftp_port)
1618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  int tmp = daemon->start_tftp_port;
1620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->start_tftp_port = daemon->end_tftp_port;
1621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->end_tftp_port = tmp;
1622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_BRIDGE:   /* --bridge-interface */
1628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
1630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(comma = split(arg)))
1631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    problem = _("bad bridge-interface");
1633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    break;
1634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	strncpy(new->iface, arg, IF_NAMESIZE);
1637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->alias = NULL;
1638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->bridges;
1639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->bridges = new;
1640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	do {
1642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  arg = comma;
1643ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  comma = split(arg);
1644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (strlen(arg) != 0)
1645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
1647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      b->next = new->alias;
1648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->alias = b;
1649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      strncpy(b->iface, arg, IF_NAMESIZE);
1650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	} while (comma);
1652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
1657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'F':  /* --dhcp-range */
1658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int k, leasepos = 2;
1660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
1661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
1662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->dhcp;
1664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->lease_time = DEFLEASE;
1665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->addr_epoch = 0;
1666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->netmask.s_addr = 0;
1667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->broadcast.s_addr = 0;
1668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->router.s_addr = 0;
1669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->netid.net = NULL;
1670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->filter = NULL;
1671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->flags = 0;
1672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	gen_prob = _("bad dhcp-range");
1674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!arg)
1676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    option = '?';
1678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    break;
1679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while(1)
1682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    for (cp = arg; *cp; cp++)
1684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (!(*cp == ' ' || *cp == '.' ||  (*cp >='0' && *cp <= '9')))
1685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
1686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (*cp != ',' && (comma = split(arg)))
1688ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1689ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (strstr(arg, "net:") == arg)
1690ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1691ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
1692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    tt->net = opt_string_alloc(arg+4);
1693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    tt->next = new->filter;
1694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    new->filter = tt;
1695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		else
1697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if (new->netid.net)
1699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      problem = _("only one netid tag allowed");
1700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    else
1701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      new->netid.net = opt_string_alloc(arg);
1702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		arg = comma;
1704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
1706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		a[0] = arg;
1708ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
1709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for (k = 1; k < 5; k++)
1713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!(a[k] = split(a[k-1])))
1714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    break;
1715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
1717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
1718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (strcmp(a[1], "static") == 0)
1719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->end = new->start;
1721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->flags |= CONTEXT_STATIC;
1722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (strcmp(a[1], "proxy") == 0)
1724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->end = new->start;
1726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->flags |= CONTEXT_PROXY;
1727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
1729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
1730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
1732ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1733ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct in_addr tmp = new->start;
1734ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->start = new->end;
1735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->end = tmp;
1736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1738ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (option != '?' && k >= 3 && strchr(a[2], '.') &&
1739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
1740ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1741ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->flags |= CONTEXT_NETMASK;
1742ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    leasepos = 3;
1743ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!is_same_net(new->start, new->end, new->netmask))
1744ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      problem = _("inconsistent DHCP range");
1745ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1746ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->dhcp = new;
1747ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1748ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (k >= 4 && strchr(a[3], '.') &&
1749ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
1750ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1751ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->flags |= CONTEXT_BRDCAST;
1752ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    leasepos = 4;
1753ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1754ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1755ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (k >= leasepos+1)
1756ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1757ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (strcmp(a[leasepos], "infinite") == 0)
1758ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->lease_time = 0xffffffff;
1759ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
1760ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1761ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		int fac = 1;
1762ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (strlen(a[leasepos]) > 0)
1763ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1764ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    switch (a[leasepos][strlen(a[leasepos]) - 1])
1765ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      {
1766ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'd':
1767ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'D':
1768ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			fac *= 24;
1769ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			/* fall though */
1770ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'h':
1771ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'H':
1772ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			fac *= 60;
1773ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			/* fall through */
1774ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'm':
1775ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'M':
1776ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			fac *= 60;
1777ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			/* fall through */
1778ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 's':
1779ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      case 'S':
1780ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			a[leasepos][strlen(a[leasepos]) - 1] = 0;
1781ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      }
1782ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1783ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    new->lease_time = atoi(a[leasepos]) * fac;
1784ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    /* Leases of a minute or less confuse
1785ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       some clients, notably Apple's */
1786ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if (new->lease_time < 120)
1787ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      new->lease_time = 120;
1788ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1789ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1790ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1791ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1792ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1793ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1794ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_BANK:
1795ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'G':  /* --dhcp-host */
1796ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1797ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int j, k = 0;
1798ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
1799ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dhcp_config *new;
1800ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct in_addr in;
1801ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1802ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new = opt_malloc(sizeof(struct dhcp_config));
1803ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1804ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->dhcp_conf;
1805ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
1806ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->hwaddr = NULL;
1807ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1808ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((a[0] = arg))
1809ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (k = 1; k < 6; k++)
1810ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!(a[k] = split(a[k-1])))
1811ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      break;
1812ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1813ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for (j = 0; j < k; j++)
1814ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
1815ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1816ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      char *arg = a[j];
1817ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1818ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if ((arg[0] == 'i' || arg[0] == 'I') &&
1819ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  (arg[1] == 'd' || arg[1] == 'D') &&
1820ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  arg[2] == ':')
1821ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1822ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (arg[3] == '*')
1823ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    new->flags |= CONFIG_NOCLID;
1824ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  else
1825ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1826ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      int len;
1827ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      arg += 3; /* dump id: */
1828ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if (strchr(arg, ':'))
1829ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
1830ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else
1831ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			{
1832ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  unhide_metas(arg);
1833ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  len = (int) strlen(arg);
1834ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
1835ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1836ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if ((new->clid = opt_malloc(len)))
1837ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			{
1838ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  new->flags |= CONFIG_CLID;
1839ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  new->clid_len = len;
1840ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  memcpy(new->clid, arg, len);
1841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
1842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else if (strstr(arg, "net:") == arg)
1845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  int len = strlen(arg + 4) + 1;
1847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if ((new->netid.net = opt_malloc(len)))
1848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      new->flags |= CONFIG_NETID;
1850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      strcpy(new->netid.net, arg+4);
1851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      unhide_metas(new->netid.net);
1852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
1855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
1857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  newhw->next = new->hwaddr;
1858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  new->hwaddr = newhw;
1859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
1860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat						&newhw->wildcard_mask, &newhw->hwaddr_type);
1861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
1864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->addr = in;
1866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->flags |= CONFIG_ADDR;
1867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
1869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      char *cp, *lastp = NULL, last = 0;
1871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      int fac = 1;
1872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (strlen(a[j]) > 1)
1874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  lastp = a[j] + strlen(a[j]) - 1;
1876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  last = *lastp;
1877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  switch (last)
1878ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'd':
1880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'D':
1881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      fac *= 24;
1882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      /* fall through */
1883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'h':
1884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'H':
1885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      fac *= 60;
1886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      /* fall through */
1887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'm':
1888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'M':
1889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      fac *= 60;
1890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      /* fall through */
1891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 's':
1892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    case 'S':
1893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      *lastp = 0;
1894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      for (cp = a[j]; *cp; cp++)
1898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (!isdigit((int)*cp) && *cp != ' ')
1899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  break;
1900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (*cp)
1902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (lastp)
1904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *lastp = last;
1905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (strcmp(a[j], "infinite") == 0)
1906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      new->lease_time = 0xffffffff;
1908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      new->flags |= CONFIG_TIME;
1909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  else if (strcmp(a[j], "ignore") == 0)
1911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    new->flags |= CONFIG_DISABLE;
1912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  else
1913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
1914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if (!(new->hostname = canonicalise_opt(a[j])) ||
1915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  !legal_hostname(new->hostname))
1916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			problem = _("bad DHCP host name");
1917ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else
1918ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			new->flags |= CONFIG_NAME;
1919ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      new->domain = NULL;
1920ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
1921ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1922ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
1923ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1924ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  new->lease_time = atoi(a[j]) * fac;
1925ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  /* Leases of a minute or less confuse
1926ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     some clients, notably Apple's */
1927ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (new->lease_time < 120)
1928ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    new->lease_time = 120;
1929ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  new->flags |= CONFIG_TIME;
1930ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1931ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1932ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1933ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->dhcp_conf = new;
1934ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1935ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1936ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1937ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'O':           /* --dhcp-option */
1938ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_FORCE:    /* --dhcp-option-force */
1939ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_OPTS:
1940ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_MATCH:    /* --dhcp-match */
1941ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      problem = parse_dhcp_opt(arg,
1942ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			       option == LOPT_FORCE ? DHOPT_FORCE :
1943ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			       (option == LOPT_MATCH ? DHOPT_MATCH :
1944ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			       (option == LOPT_OPTS ? DHOPT_BANK : 0)));
1945ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
1946ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1947ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'M': /* --dhcp-boot */
1948ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
1949ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dhcp_netid *id = NULL;
1950ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while (arg && strstr(arg, "net:") == arg)
1951ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1952ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
1953ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    newid->next = id;
1954ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    id = newid;
1955ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    comma = split(arg);
1956ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    newid->net = opt_string_alloc(arg+4);
1957ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    arg = comma;
1958ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  };
1959ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1960ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!arg)
1961ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
1962ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
1963ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
1964ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *dhcp_file, *dhcp_sname = NULL;
1965ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct in_addr dhcp_next_server;
1966ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    comma = split(arg);
1967ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    dhcp_file = opt_string_alloc(arg);
1968ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    dhcp_next_server.s_addr = 0;
1969ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (comma)
1970ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1971ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		arg = comma;
1972ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		comma = split(arg);
1973ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		dhcp_sname = opt_string_alloc(arg);
1974ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (comma)
1975ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1976ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    unhide_metas(comma);
1977ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
1978ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      option = '?';
1979ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1980ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1981ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (option != '?')
1982ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
1983ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
1984ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->file = dhcp_file;
1985ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->sname = dhcp_sname;
1986ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->next_server = dhcp_next_server;
1987ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->netid = id;
1988ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->next = daemon->boot_config;
1989ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->boot_config = new;
1990ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
1991ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
1992ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1993ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
1994ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
1995ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1996ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_PXE_PROMT:  /* --pxe-prompt */
1997ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       {
1998ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
1999ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 int timeout;
2000ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2001ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 new->netid = NULL;
2002ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 new->opt = 10; /* PXE_MENU_PROMPT */
2003ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2004ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 while (arg && strstr(arg, "net:") == arg)
2005ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
2006ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2007ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     comma = split(arg);
2008ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     nn->next = new->netid;
2009ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->netid = nn;
2010ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     nn->net = opt_string_alloc(arg+4);
2011ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     arg = comma;
2012ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
2013ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2014ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 if (!arg)
2015ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   option = '?';
2016ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 else
2017ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
2018ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     comma = split(arg);
2019ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     unhide_metas(arg);
2020ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->len = strlen(arg) + 1;
2021ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->val = opt_malloc(new->len);
2022ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     memcpy(new->val + 1, arg, new->len - 1);
2023ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2024ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->u.vendor_class = (unsigned char *)"PXEClient";
2025ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->flags = DHOPT_VENDOR;
2026ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2027ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     if (comma && atoi_check(comma, &timeout))
2028ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       *(new->val) = timeout;
2029ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     else
2030ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       *(new->val) = 255;
2031ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2032ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->next = daemon->dhcp_opts;
2033ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     daemon->dhcp_opts = new;
2034ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     daemon->enable_pxe = 1;
2035ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
2036ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2037ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 break;
2038ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       }
2039ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2040ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_PXE_SERV:  /* --pxe-service */
2041ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       {
2042ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
2043ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2044ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
2045ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 static int boottype = 32768;
2046ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2047ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 new->netid = NULL;
2048ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 new->server.s_addr = 0;
2049ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2050ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 while (arg && strstr(arg, "net:") == arg)
2051ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
2052ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
2053ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     comma = split(arg);
2054ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     nn->next = new->netid;
2055ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     new->netid = nn;
2056ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     nn->net = opt_string_alloc(arg+4);
2057ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     arg = comma;
2058ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
2059ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2060ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 if (arg && (comma = split(arg)))
2061ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
2062ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     for (i = 0; CSA[i]; i++)
2063ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       if (strcasecmp(CSA[i], arg) == 0)
2064ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 break;
2065ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2066ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     if (CSA[i] || atoi_check(arg, &i))
2067ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       {
2068ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 arg = comma;
2069ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 comma = split(arg);
2070ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2071ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 new->CSA = i;
2072ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 new->menu = opt_string_alloc(arg);
2073ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2074ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 if (comma)
2075ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		   {
2076ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     arg = comma;
2077ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     comma = split(arg);
2078ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     if (atoi_check(arg, &i))
2079ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       {
2080ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 new->type = i;
2081ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 new->basename = NULL;
2082ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       }
2083ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     else
2084ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       {
2085ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 new->type = boottype++;
2086ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 new->basename = opt_string_alloc(arg);
2087ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       }
2088ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2089ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
2090ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       option = '?';
2091ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2092ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     /* Order matters */
2093ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     new->next = NULL;
2094ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     if (!daemon->pxe_services)
2095ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       daemon->pxe_services = new;
2096ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     else
2097ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       {
2098ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 struct pxe_service *s;
2099ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 for (s = daemon->pxe_services; s->next; s = s->next);
2100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			 s->next = new;
2101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		       }
2102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     daemon->enable_pxe = 1;
2104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		     break;
2105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		   }
2106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       }
2107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
2108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 option = '?';
2110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 break;
2111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       }
2112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '4':  /* --dhcp-mac */
2114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(comma = split(arg)))
2116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
2117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
2120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (strstr(arg, "net:") == arg)
2121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->netid.net = opt_string_alloc(arg+4);
2122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
2123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->netid.net = opt_string_alloc(arg);
2124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    unhide_metas(comma);
2125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
2126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->dhcp_macs;
2127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->dhcp_macs = new;
2128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
2131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'U':           /* --dhcp-vendorclass */
2133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'j':           /* --dhcp-userclass */
2134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_CIRCUIT:  /* --dhcp-circuitid */
2135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_REMOTE:   /* --dhcp-remoteid */
2136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_SUBSCR:   /* --dhcp-subscrid */
2137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(comma = split(arg)))
2139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
2140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *p;
2143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    int dig = 0;
2144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
2145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (strstr(arg, "net:") == arg)
2146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->netid.net = opt_string_alloc(arg+4);
2147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
2148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      new->netid.net = opt_string_alloc(arg);
2149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* check for hex string - must digits may include : must not have nothing else,
2150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       only allowed for agent-options. */
2151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    for (p = comma; *p; p++)
2152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (isxdigit((int)*p))
2153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		dig = 1;
2154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else if (*p != ':')
2155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    unhide_metas(comma);
2157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (option == 'U' || option == 'j' || *p || !dig)
2158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
2159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->len = strlen(comma);
2160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->data = opt_malloc(new->len);
2161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		memcpy(new->data, comma, new->len);
2162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
2163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
2164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
2165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
2166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->data = opt_malloc(new->len);
2167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		memcpy(new->data, comma, new->len);
2168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
2169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    switch (option)
2171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
2172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      case 'j':
2173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->match_type = MATCH_USER;
2174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      case 'U':
2176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->match_type = MATCH_VENDOR;
2177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      case LOPT_CIRCUIT:
2179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->match_type = MATCH_CIRCUIT;
2180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      case LOPT_REMOTE:
2182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->match_type = MATCH_REMOTE;
2183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      case LOPT_SUBSCR:
2185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->match_type = MATCH_SUBSCRIBER;
2186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
2188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->dhcp_vendors;
2189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->dhcp_vendors = new;
2190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_ALTPORT:   /* --dhcp-alternate-port */
2195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!arg)
2196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
2198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
2199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
2201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  comma = split(arg);
2203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
2204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
2205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    problem = _("invalid port number");
2206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!comma)
2207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->dhcp_client_port = daemon->dhcp_server_port+1;
2208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      break;
2210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'J':            /* --dhcp-ignore */
2212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_NO_NAMES:  /* --dhcp-ignore-names */
2213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_BROADCAST: /* --dhcp-broadcast */
2214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case '3':            /* --bootp-dynamic */
2215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
2217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct dhcp_netid *list = NULL;
2218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (option == 'J')
2219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->dhcp_ignore;
2221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->dhcp_ignore = new;
2222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (option == LOPT_BROADCAST)
2224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->force_broadcast;
2226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->force_broadcast = new;
2227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (option == '3')
2229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->bootp_dynamic;
2231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->bootp_dynamic = new;
2232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->dhcp_ignore_names;
2236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->dhcp_ignore_names = new;
2237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while (arg) {
2240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
2241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  comma = split(arg);
2242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  member->next = list;
2243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  list = member;
2244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (strstr(arg, "net:") == arg)
2245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    member->net = opt_string_alloc(arg+4);
2246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
2247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    member->net = opt_string_alloc(arg);
2248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  arg = comma;
2249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->list = list;
2252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
2255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'V':  /* --alias */
2257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *dash, *a[3] = { NULL, NULL, NULL };
2259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int k = 0;
2260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct doctor *new = opt_malloc(sizeof(struct doctor));
2261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->doctors;
2262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->doctors = new;
2263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->mask.s_addr = 0xffffffff;
2264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->end.s_addr = 0;
2265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((a[0] = arg))
2267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (k = 1; k < 3; k++)
2268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (!(a[k] = split(a[k-1])))
2270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      unhide_metas(a[k]);
2272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	dash = split_chr(a[0], '-');
2275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((k < 2) ||
2277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
2278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
2279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
2280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (k == 3)
2282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  new->mask.s_addr = inet_addr(a[2]);
2283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (dash &&
2285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
2286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     !is_same_net(new->in, new->end, new->mask) ||
2287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
2288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  problem = _("invalid alias range");
2289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_INTNAME:  /* --interface-name */
2294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct interface_name *new, **up;
2296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *domain = NULL;
2297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
2299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!comma || !(domain = canonicalise_opt(arg)))
2301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  problem = _("bad interface name");
2302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new = opt_malloc(sizeof(struct interface_name));
2304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = NULL;
2305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* Add to the end of the list, so that first name
2306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   of an interface is used for PTR lookups. */
2307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for (up = &daemon->int_names; *up; up = &((*up)->next));
2308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	*up = new;
2309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->name = domain;
2310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->intr = opt_string_alloc(comma);
2311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_CNAME: /* --cname */
2315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct cname *new;
2317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(comma = split(arg)))
2319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  option = '?';
2320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *alias = canonicalise_opt(arg);
2323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    char *target = canonicalise_opt(comma);
2324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!alias || !target)
2326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      problem = _("bad CNAME");
2327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else
2328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
2329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		for (new = daemon->cnames; new; new = new->next)
2330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (hostname_isequal(new->alias, arg))
2331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    problem = _("duplicate CNAME");
2332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new = opt_malloc(sizeof(struct cname));
2333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->next = daemon->cnames;
2334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->cnames = new;
2335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->alias = alias;
2336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		new->target = target;
2337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
2338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_PTR:  /* --ptr-record */
2343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct ptr_record *new;
2345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *dom, *target = NULL;
2346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
2348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(dom = canonicalise_opt(arg)) ||
2350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    (comma && !(target = canonicalise_opt(comma))))
2351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  problem = _("bad PTR record");
2352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new = opt_malloc(sizeof(struct ptr_record));
2355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->ptr;
2356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->ptr = new;
2357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->name = dom;
2358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->ptr = target;
2359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case LOPT_NAPTR: /* --naptr-record */
2364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int k = 0;
2367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct naptr *new;
2368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int order, pref;
2369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *name, *replace = NULL;
2370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((a[0] = arg))
2372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (k = 1; k < 7; k++)
2373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!(a[k] = split(a[k-1])))
2374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      break;
2375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (k < 6 ||
2378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    !(name = canonicalise_opt(a[0])) ||
2379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    !atoi_check16(a[1], &order) ||
2380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    !atoi_check16(a[2], &pref) ||
2381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    (k == 7 && !(replace = canonicalise_opt(a[6]))))
2382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  problem = _("bad NAPTR record");
2383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new = opt_malloc(sizeof(struct naptr));
2386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->next = daemon->naptr;
2387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    daemon->naptr = new;
2388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->name = name;
2389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->flags = opt_string_alloc(a[3]);
2390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->services = opt_string_alloc(a[4]);
2391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->regexp = opt_string_alloc(a[5]);
2392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->replace = replace;
2393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->order = order;
2394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->pref = pref;
2395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'Y':  /* --txt-record */
2400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct txt_record *new;
2402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	unsigned char *p, *q;
2403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((comma = split(arg)))
2405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  comma--;
2406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	gen_prob = _("TXT record string too long");
2408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ((q = (unsigned char *)comma))
2410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  while (1)
2411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      size_t len;
2413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if ((p = (unsigned char *)strchr((char*)q+1, ',')))
2414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if ((len = p - q - 1) > 255)
2416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    option = '?';
2417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  *q = len;
2418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  for (q = q+1; q < p; q++)
2419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *q = unhide_meta(*q);
2420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
2422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if ((len = strlen((char *)q+1)) > 255)
2424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    option = '?';
2425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  *q = len;
2426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  for (q = q+1; *q; q++)
2427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    *q = unhide_meta(*q);
2428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  break;
2429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new = opt_malloc(sizeof(struct txt_record));
2433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->txt;
2434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->txt = new;
2435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->class = C_IN;
2436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (comma)
2437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = q - ((unsigned char *)comma);
2439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->txt = opt_malloc(new->len);
2440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    memcpy(new->txt, comma, new->len);
2441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
2443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    static char empty[] = "";
2445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->len = 1;
2446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    new->txt = empty;
2447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* ensure arg is terminated */
2450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (comma)
2451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  *comma = 0;
2452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(new->name = canonicalise_opt(arg)))
2454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    problem = _("bad TXT record");
2456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    break;
2457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case 'W':  /* --srv-host */
2463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
2464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	int port = 1, priority = 0, weight = 0;
2465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	char *name, *target = NULL;
2466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	struct mx_srv_record *new;
2467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	comma = split(arg);
2469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(name = canonicalise_opt(arg)))
2471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  problem = _("bad SRV record");
2472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (comma)
2474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    arg = comma;
2476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    comma = split(arg);
2477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (!(target = canonicalise_opt(arg))
2478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat)	      problem = _("bad SRV target");
2479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (comma)
2481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
2482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		arg = comma;
2483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		comma = split(arg);
2484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (!atoi_check16(arg, &port))
2485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  problem = _("invalid port number");
2486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (comma)
2488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
2489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    arg = comma;
2490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    comma = split(arg);
2491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if (!atoi_check16(arg, &priority))
2492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      problem = _("invalid priority");
2493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if (comma)
2495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      {
2496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			arg = comma;
2497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			comma = split(arg);
2498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			if (!atoi_check16(arg, &weight))
2499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			  problem = _("invalid weight");
2500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      }
2501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
2502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
2503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new = opt_malloc(sizeof(struct mx_srv_record));
2506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->next = daemon->mxnames;
2507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->mxnames = new;
2508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->issrv = 1;
2509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->name = name;
2510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->target = target;
2511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->srvport = port;
2512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->priority = priority;
2513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	new->weight = weight;
2514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
2516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    default:
2518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (problem)
2523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return problem;
2524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (option == '?')
2526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return gen_prob;
2527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return NULL;
2529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
2530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void one_file(char *file, int nest, int hard_opt)
2532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
2533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  volatile int lineno = 0;
2534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i, option;
2535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  FILE *f;
2536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *p, *arg, *start, *buff = daemon->namebuff;
2537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  static struct fileread {
2538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    dev_t dev;
2539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    ino_t ino;
2540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    struct fileread *next;
2541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  } *filesread = NULL;
2542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct stat statbuf;
2543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* ignore repeated files. */
2545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (hard_opt == 0 && stat(file, &statbuf) == 0)
2546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct fileread *r;
2548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (r = filesread; r; r = r->next)
2550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
2551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  return;
2552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      r = safe_malloc(sizeof(struct fileread));
2554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      r->next = filesread;
2555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      filesread = r;
2556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      r->dev = statbuf.st_dev;
2557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      r->ino = statbuf.st_ino;
2558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (nest > 20)
2561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("files nested too deep in %s"), file, EC_BADCONF);
2562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(f = fopen(file, "r")))
2564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (errno == ENOENT && nest == 0)
2566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return; /* No conffile, all done. */
2567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
2568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  char *str = _("cannot read %s: %s");
2570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (hard_opt != 0)
2571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      my_syslog(LOG_ERR, str, file, strerror(errno));
2573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      return;
2574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
2576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    die(str, file, EC_FILE);
2577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (fgets(buff, MAXDNAME, f))
2581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int white;
2583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      unsigned int lastquote;
2584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      char *errmess;
2585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Memory allocation failure longjmps here if mem_recover == 1 */
2587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (hard_opt)
2588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (setjmp(mem_jmp))
2590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    continue;
2591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mem_recover = 1;
2592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      lineno++;
2595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      errmess = NULL;
2596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Implement quotes, inside quotes we allow \\ \" \n and \t
2598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 metacharacters get hidden also strip comments */
2599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (white = 1, lastquote = 0, p = buff; *p; p++)
2601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (*p == '"')
2603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      memmove(p, p+1, strlen(p+1)+1);
2605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      for(; *p && *p != '"'; p++)
2606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (*p == '\\' && strchr("\"tnebr\\", p[1]))
2608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    {
2609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      if (p[1] == 't')
2610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			p[1] = '\t';
2611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else if (p[1] == 'n')
2612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			p[1] = '\n';
2613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else if (p[1] == 'b')
2614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			p[1] = '\b';
2615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else if (p[1] == 'r')
2616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			p[1] = '\r';
2617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      else if (p[1] == 'e') /* escape */
2618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			p[1] = '\033';
2619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      memmove(p, p+1, strlen(p+1)+1);
2620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    }
2621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  *p = hide_meta(*p);
2622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (*p == '"')
2624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  memmove(p, p+1, strlen(p+1)+1);
2626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  lastquote = p - buff;
2627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
2629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  errmess = _("missing \"");
2631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  goto oops;
2632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (white && *p == '#')
2636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *p = 0;
2638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      break;
2639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  white = isspace((int)unhide_meta(*p));
2641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2643ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* fgets gets end of line char too. */
2644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1])))
2645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	buff[strlen(buff)-1] = 0;
2646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (*buff == 0)
2648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	continue;
2649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (hard_opt != 0)
2651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	arg = buff;
2652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if ((p=strchr(buff, '=')))
2653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* allow spaces around "=" */
2655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  arg = p+1;
2656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (; p >= buff && (isspace((int)*p) || *p == '='); p--)
2657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    *p = 0;
2658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
2660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	arg = NULL;
2661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (hard_opt != 0)
2663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	option = hard_opt;
2664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
2665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* skip leading space */
2667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (start = buff; *start && isspace((int)*start); start++);
2668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  for (option = 0, i = 0; opts[i].name; i++)
2670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (strcmp(opts[i].name, start) == 0)
2671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
2672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		option = opts[i].val;
2673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
2674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
2675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!option)
2677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    errmess = _("bad option");
2678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (opts[i].has_arg == 0 && arg)
2679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    errmess = _("extraneous parameter");
2680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (opts[i].has_arg == 1 && !arg)
2681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    errmess = _("missing parameter");
2682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!errmess)
2685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (arg)
2687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    for (; isspace((int)*arg); arg++);
2688ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2689ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  errmess = one_opt(option, arg, _("error"), nest + 1);
2690ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2691ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (errmess)
2693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	oops:
2695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
2696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (hard_opt != 0)
2697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    my_syslog(LOG_ERR, buff, file);
2698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
2699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    die(buff, file, EC_BADCONF);
2700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  mem_recover = 1;
2704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  fclose(f);
2705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
2706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
2708ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid reread_dhcp(void)
2709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
2710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp_hosts_file)
2711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct dhcp_config *configs, *cp, **up;
2713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* remove existing... */
2715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
2716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  cp = configs->next;
2718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (configs->flags & CONFIG_BANK)
2720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      struct hwaddr_config *mac, *tmp;
2722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      for (mac = configs->hwaddr; mac; mac = tmp)
2724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  tmp = mac->next;
2726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  free(mac);
2727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (configs->flags & CONFIG_CLID)
2729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		free(configs->clid);
2730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (configs->flags & CONFIG_NETID)
2731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		free(configs->netid.net);
2732ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (configs->flags & CONFIG_NAME)
2733ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		free(configs->hostname);
2734ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *up = configs->next;
2737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      free(configs);
2738ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
2740ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    up = &configs->next;
2741ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2742ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2743ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
2744ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
2745ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2746ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2747ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp_opts_file)
2748ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2749ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct dhcp_opt *opts, *cp, **up;
2750ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct dhcp_netid *id, *next;
2751ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2752ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
2753ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2754ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  cp = opts->next;
2755ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2756ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (opts->flags & DHOPT_BANK)
2757ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
2758ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if ((opts->flags & DHOPT_VENDOR))
2759ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		free(opts->u.vendor_class);
2760ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      free(opts->val);
2761ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      for (id = opts->netid; id; id = next)
2762ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
2763ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  next = id->next;
2764ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  free(id->net);
2765ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  free(id);
2766ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
2767ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *up = opts->next;
2768ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      free(opts);
2769ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
2770ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
2771ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    up = &opts->next;
2772ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2773ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2774ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
2775ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
2776ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2777ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
2778ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
2779ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2780ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid read_opts(int argc, char **argv, char *compile_opts)
2781ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
2782ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *buff = opt_malloc(MAXDNAME);
2783ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int option, nest = 0, testmode = 0;
2784ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *errmess, *arg, *conffile = CONFFILE;
2785ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2786ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  opterr = 0;
2787ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2788ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon = opt_malloc(sizeof(struct daemon));
2789ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  memset(daemon, 0, sizeof(struct daemon));
2790ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->namebuff = buff;
2791ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2792ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* Set defaults - everything else is zero or NULL */
2793ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->cachesize = CACHESIZ;
2794ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->ftabsize = FTABSIZ;
2795ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->port = NAMESERVER_PORT;
2796ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->dhcp_client_port = DHCP_CLIENT_PORT;
2797ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->dhcp_server_port = DHCP_SERVER_PORT;
2798ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->default_resolv.is_default = 1;
2799ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->default_resolv.name = RESOLVFILE;
2800ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->resolv_files = &daemon->default_resolv;
2801ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->username = CHUSER;
2802ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->runfile =  RUNFILE;
2803ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->dhcp_max = MAXLEASES;
2804ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->tftp_max = TFTP_MAX_CONNECTIONS;
2805ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->edns_pktsz = EDNS_PKTSZ;
2806ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->log_fac = -1;
2807ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  add_txt("version.bind", "dnsmasq-" VERSION );
2808ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  add_txt("authors.bind", "Simon Kelley");
2809ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  add_txt("copyright.bind", COPYRIGHT);
2810ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2811ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (1)
2812ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2813ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_GETOPT_LONG
2814ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
2815ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
2816ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      option = getopt(argc, argv, OPTSTRING);
2817ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
2818ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2819ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (option == -1)
2820ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
2821ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2822ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Copy optarg so that argv doesn't get changed */
2823ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (optarg)
2824ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2825ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  strncpy(buff, optarg, MAXDNAME);
2826ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  buff[MAXDNAME-1] = 0;
2827ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  arg = buff;
2828ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2829ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
2830ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	arg = NULL;
2831ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2832ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* command-line only stuff */
2833ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (option == LOPT_TEST)
2834ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	testmode = 1;
2835ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (option == 'w')
2836ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2837ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (argc != 3 ||  strcmp(argv[2], "dhcp") != 0)
2838ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    do_usage();
2839ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
2840ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
2841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    display_opts();
2842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
2843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  exit(0);
2844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (option == 'v')
2846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  printf(_("Dnsmasq version %s  %s\n"), VERSION, COPYRIGHT);
2848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  printf(_("Compile time options %s\n\n"), compile_opts);
2849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
2850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
2851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
2852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat          exit(0);
2853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        }
2854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (option == 'C')
2855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  conffile = opt_string_alloc(arg);
2857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  nest++;
2858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
2860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_GETOPT_LONG
2862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  errmess = one_opt(option, arg, _("try --help"), 0);
2863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
2864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  errmess = one_opt(option, arg, _("try -w"), 0);
2865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
2866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (errmess)
2867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    die(_("bad command line options: %s"), errmess, EC_BADCONF);
2868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (conffile)
2872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    one_file(conffile, nest, 0);
2873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* port might not be known when the address is parsed - fill in here */
2875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->servers)
2876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct server *tmp;
2878ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (tmp = daemon->servers; tmp; tmp = tmp->next)
2879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!(tmp->flags & SERV_HAS_SOURCE))
2880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (tmp->source_addr.sa.sa_family == AF_INET)
2882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      tmp->source_addr.in.sin_port = htons(daemon->query_port);
2883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
2884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    else if (tmp->source_addr.sa.sa_family == AF_INET6)
2885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
2886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
2887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->if_addrs)
2891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct iname *tmp;
2893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
2894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (tmp->addr.sa.sa_family == AF_INET)
2895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  tmp->addr.in.sin_port = htons(daemon->port);
2896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
2897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else if (tmp->addr.sa.sa_family == AF_INET6)
2898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  tmp->addr.in6.sin6_port = htons(daemon->port);
2899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif /* IPv6 */
2900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* only one of these need be specified: the other defaults to the host-name */
2903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
2904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct mx_srv_record *mx;
2906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (gethostname(buff, MAXDNAME) == -1)
2908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("cannot get host-name: %s"), NULL, EC_MISC);
2909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (mx = daemon->mxnames; mx; mx = mx->next)
2911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!mx->issrv && hostname_isequal(mx->name, buff))
2912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
2913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
2915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mx = opt_malloc(sizeof(struct mx_srv_record));
2917ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mx->next = daemon->mxnames;
2918ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mx->issrv = 0;
2919ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mx->target = NULL;
2920ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mx->name = opt_string_alloc(buff);
2921ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->mxnames = mx;
2922ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2923ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2924ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!daemon->mxtarget)
2925ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->mxtarget = opt_string_alloc(buff);
2926ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2927ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (mx = daemon->mxnames; mx; mx = mx->next)
2928ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!mx->issrv && !mx->target)
2929ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  mx->target = daemon->mxtarget;
2930ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2931ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2932ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(daemon->options & OPT_NO_RESOLV) &&
2933ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->resolv_files &&
2934ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->resolv_files->next &&
2935ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      (daemon->options & OPT_NO_POLL))
2936ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
2937ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2938ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_RESOLV_DOMAIN)
2939ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2940ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      char *line;
2941ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FILE *f;
2942ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2943ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((daemon->options & OPT_NO_RESOLV) ||
2944ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  !daemon->resolv_files ||
2945ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  (daemon->resolv_files)->next)
2946ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
2947ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2948ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!(f = fopen((daemon->resolv_files)->name, "r")))
2949ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
2950ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2951ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      while ((line = fgets(buff, MAXDNAME, f)))
2952ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
2953ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  char *token = strtok(line, " \t\n\r");
2954ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2955ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!token || strcmp(token, "search") != 0)
2956ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    continue;
2957ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2958ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((token = strtok(NULL, " \t\n\r")) &&
2959ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      (daemon->domain_suffix = canonicalise_opt(token)))
2960ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    break;
2961ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
2962ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2963ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      fclose(f);
2964ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2965ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!daemon->domain_suffix)
2966ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
2967ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2968ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2969ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->domain_suffix)
2970ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2971ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       /* add domain for any srv record without one. */
2972ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct mx_srv_record *srv;
2973ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2974ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (srv = daemon->mxnames; srv; srv = srv->next)
2975ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (srv->issrv &&
2976ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strchr(srv->name, '.') &&
2977ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strchr(srv->name, '.') == strrchr(srv->name, '.'))
2978ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
2979ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strcpy(buff, srv->name);
2980ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strcat(buff, ".");
2981ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    strcat(buff, daemon->domain_suffix);
2982ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    free(srv->name);
2983ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    srv->name = opt_string_alloc(buff);
2984ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
2985ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2986ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (daemon->options & OPT_DHCP_FQDN)
2987ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
2988ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
2989ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (testmode)
2990ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
2991ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
2992ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      exit(0);
2993ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
2994ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
2995