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