]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/option.c
1 /* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 /* define this to get facilitynames */
22 static volatile int mem_recover
= 0;
23 static jmp_buf mem_jmp
;
24 static void one_file(char *file
, int hard_opt
);
26 /* Solaris headers don't have facility names. */
27 #ifdef HAVE_SOLARIS_NETWORK
35 { "daemon", LOG_DAEMON
},
37 { "syslog", LOG_SYSLOG
},
41 { "audit", LOG_AUDIT
},
43 { "local0", LOG_LOCAL0
},
44 { "local1", LOG_LOCAL1
},
45 { "local2", LOG_LOCAL2
},
46 { "local3", LOG_LOCAL3
},
47 { "local4", LOG_LOCAL4
},
48 { "local5", LOG_LOCAL5
},
49 { "local6", LOG_LOCAL6
},
50 { "local7", LOG_LOCAL7
},
55 #ifndef HAVE_GETOPT_LONG
64 #define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
66 /* options which don't have a one-char version */
67 #define LOPT_RELOAD 256
68 #define LOPT_NO_NAMES 257
70 #define LOPT_SECURE 259
71 #define LOPT_PREFIX 260
73 #define LOPT_BRIDGE 262
74 #define LOPT_TFTP_MAX 263
75 #define LOPT_FORCE 264
76 #define LOPT_NOBLOCK 265
77 #define LOPT_LOG_OPTS 266
78 #define LOPT_MAX_LOGS 267
79 #define LOPT_CIRCUIT 268
80 #define LOPT_REMOTE 269
81 #define LOPT_SUBSCR 270
82 #define LOPT_INTNAME 271
84 #define LOPT_DHCP_HOST 273
85 #define LOPT_APREF 274
86 #define LOPT_OVERRIDE 275
87 #define LOPT_TFTPPORTS 276
88 #define LOPT_REBIND 277
89 #define LOPT_NOLAST 278
91 #define LOPT_DHCP_OPTS 280
92 #define LOPT_MATCH 281
93 #define LOPT_BROADCAST 282
94 #define LOPT_NEGTTL 283
95 #define LOPT_ALTPORT 284
96 #define LOPT_SCRIPTUSR 285
97 #define LOPT_LOCAL 286
98 #define LOPT_NAPTR 287
99 #define LOPT_MINPORT 288
100 #define LOPT_DHCP_FQDN 289
101 #define LOPT_CNAME 290
102 #define LOPT_PXE_PROMT 291
103 #define LOPT_PXE_SERV 292
104 #define LOPT_TEST 293
105 #define LOPT_TAG_IF 294
106 #define LOPT_PROXY 295
107 #define LOPT_GEN_NAMES 296
108 #define LOPT_MAXTTL 297
109 #define LOPT_NO_REBIND 298
110 #define LOPT_LOC_REBND 299
111 #define LOPT_ADD_MAC 300
112 #define LOPT_DNSSEC 301
113 #define LOPT_INCR_ADDR 302
114 #define LOPT_CONNTRACK 303
115 #define LOPT_FQDN 304
116 #define LOPT_LUASCRIPT 305
118 #ifdef HAVE_GETOPT_LONG
119 static const struct option opts
[] =
121 static const struct myoption opts
[] =
124 { "version", 0, 0, 'v' },
125 { "no-hosts", 0, 0, 'h' },
126 { "no-poll", 0, 0, 'n' },
127 { "help", 0, 0, 'w' },
128 { "no-daemon", 0, 0, 'd' },
129 { "log-queries", 0, 0, 'q' },
130 { "user", 2, 0, 'u' },
131 { "group", 2, 0, 'g' },
132 { "resolv-file", 2, 0, 'r' },
133 { "mx-host", 1, 0, 'm' },
134 { "mx-target", 1, 0, 't' },
135 { "cache-size", 2, 0, 'c' },
136 { "port", 1, 0, 'p' },
137 { "dhcp-leasefile", 2, 0, 'l' },
138 { "dhcp-lease", 1, 0, 'l' },
139 { "dhcp-host", 1, 0, 'G' },
140 { "dhcp-range", 1, 0, 'F' },
141 { "dhcp-option", 1, 0, 'O' },
142 { "dhcp-boot", 1, 0, 'M' },
143 { "domain", 1, 0, 's' },
144 { "domain-suffix", 1, 0, 's' },
145 { "interface", 1, 0, 'i' },
146 { "listen-address", 1, 0, 'a' },
147 { "bogus-priv", 0, 0, 'b' },
148 { "bogus-nxdomain", 1, 0, 'B' },
149 { "selfmx", 0, 0, 'e' },
150 { "filterwin2k", 0, 0, 'f' },
151 { "pid-file", 2, 0, 'x' },
152 { "strict-order", 0, 0, 'o' },
153 { "server", 1, 0, 'S' },
154 { "local", 1, 0, LOPT_LOCAL
},
155 { "address", 1, 0, 'A' },
156 { "conf-file", 2, 0, 'C' },
157 { "no-resolv", 0, 0, 'R' },
158 { "expand-hosts", 0, 0, 'E' },
159 { "localmx", 0, 0, 'L' },
160 { "local-ttl", 1, 0, 'T' },
161 { "no-negcache", 0, 0, 'N' },
162 { "addn-hosts", 1, 0, 'H' },
163 { "query-port", 1, 0, 'Q' },
164 { "except-interface", 1, 0, 'I' },
165 { "no-dhcp-interface", 1, 0, '2' },
166 { "domain-needed", 0, 0, 'D' },
167 { "dhcp-lease-max", 1, 0, 'X' },
168 { "bind-interfaces", 0, 0, 'z' },
169 { "read-ethers", 0, 0, 'Z' },
170 { "alias", 1, 0, 'V' },
171 { "dhcp-vendorclass", 1, 0, 'U' },
172 { "dhcp-userclass", 1, 0, 'j' },
173 { "dhcp-ignore", 1, 0, 'J' },
174 { "edns-packet-max", 1, 0, 'P' },
175 { "keep-in-foreground", 0, 0, 'k' },
176 { "dhcp-authoritative", 0, 0, 'K' },
177 { "srv-host", 1, 0, 'W' },
178 { "localise-queries", 0, 0, 'y' },
179 { "txt-record", 1, 0, 'Y' },
180 { "enable-dbus", 0, 0, '1' },
181 { "bootp-dynamic", 2, 0, '3' },
182 { "dhcp-mac", 1, 0, '4' },
183 { "no-ping", 0, 0, '5' },
184 { "dhcp-script", 1, 0, '6' },
185 { "conf-dir", 1, 0, '7' },
186 { "log-facility", 1, 0 ,'8' },
187 { "leasefile-ro", 0, 0, '9' },
188 { "dns-forward-max", 1, 0, '0' },
189 { "clear-on-reload", 0, 0, LOPT_RELOAD
},
190 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES
},
191 { "enable-tftp", 2, 0, LOPT_TFTP
},
192 { "tftp-secure", 0, 0, LOPT_SECURE
},
193 { "tftp-unique-root", 0, 0, LOPT_APREF
},
194 { "tftp-root", 1, 0, LOPT_PREFIX
},
195 { "tftp-max", 1, 0, LOPT_TFTP_MAX
},
196 { "ptr-record", 1, 0, LOPT_PTR
},
197 { "naptr-record", 1, 0, LOPT_NAPTR
},
198 { "bridge-interface", 1, 0 , LOPT_BRIDGE
},
199 { "dhcp-option-force", 1, 0, LOPT_FORCE
},
200 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK
},
201 { "log-dhcp", 0, 0, LOPT_LOG_OPTS
},
202 { "log-async", 2, 0, LOPT_MAX_LOGS
},
203 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT
},
204 { "dhcp-remoteid", 1, 0, LOPT_REMOTE
},
205 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR
},
206 { "interface-name", 1, 0, LOPT_INTNAME
},
207 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST
},
208 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS
},
209 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE
},
210 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS
},
211 { "stop-dns-rebind", 0, 0, LOPT_REBIND
},
212 { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND
},
213 { "all-servers", 0, 0, LOPT_NOLAST
},
214 { "dhcp-match", 1, 0, LOPT_MATCH
},
215 { "dhcp-broadcast", 2, 0, LOPT_BROADCAST
},
216 { "neg-ttl", 1, 0, LOPT_NEGTTL
},
217 { "max-ttl", 1, 0, LOPT_MAXTTL
},
218 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT
},
219 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR
},
220 { "min-port", 1, 0, LOPT_MINPORT
},
221 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN
},
222 { "cname", 1, 0, LOPT_CNAME
},
223 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT
},
224 { "pxe-service", 1, 0, LOPT_PXE_SERV
},
225 { "test", 0, 0, LOPT_TEST
},
226 { "tag-if", 1, 0, LOPT_TAG_IF
},
227 { "dhcp-proxy", 2, 0, LOPT_PROXY
},
228 { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES
},
229 { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND
},
230 { "add-mac", 0, 0, LOPT_ADD_MAC
},
231 { "proxy-dnssec", 0, 0, LOPT_DNSSEC
},
232 { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR
},
233 { "conntrack", 0, 0, LOPT_CONNTRACK
},
234 { "dhcp-client-update", 0, 0, LOPT_FQDN
},
235 { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT
},
240 #define ARG_DUP OPT_LAST
241 #define ARG_ONE OPT_LAST + 1
242 #define ARG_USED_CL OPT_LAST + 2
243 #define ARG_USED_FILE OPT_LAST + 3
248 char * const flagdesc
;
252 { 'a', ARG_DUP
, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL
},
253 { 'A', ARG_DUP
, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL
},
254 { 'b', OPT_BOGUSPRIV
, NULL
, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL
},
255 { 'B', ARG_DUP
, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL
},
256 { 'c', ARG_ONE
, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
257 { 'C', ARG_DUP
, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE
},
258 { 'd', OPT_DEBUG
, NULL
, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL
},
259 { 'D', OPT_NODOTS_LOCAL
, NULL
, gettext_noop("Do NOT forward queries with no domain part."), NULL
},
260 { 'e', OPT_SELFMX
, NULL
, gettext_noop("Return self-pointing MX records for local hosts."), NULL
},
261 { 'E', OPT_EXPAND
, NULL
, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL
},
262 { 'f', OPT_FILTER
, NULL
, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL
},
263 { 'F', ARG_DUP
, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL
},
264 { 'g', ARG_ONE
, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP
},
265 { 'G', ARG_DUP
, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL
},
266 { LOPT_DHCP_HOST
, ARG_DUP
, "<filename>", gettext_noop("Read DHCP host specs from file."), NULL
},
267 { LOPT_DHCP_OPTS
, ARG_DUP
, "<filename>", gettext_noop("Read DHCP option specs from file."), NULL
},
268 { LOPT_TAG_IF
, ARG_DUP
, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL
},
269 { 'h', OPT_NO_HOSTS
, NULL
, gettext_noop("Do NOT load %s file."), HOSTSFILE
},
270 { 'H', ARG_DUP
, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE
},
271 { 'i', ARG_DUP
, "interface", gettext_noop("Specify interface(s) to listen on."), NULL
},
272 { 'I', ARG_DUP
, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL
},
273 { 'j', ARG_DUP
, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL
},
274 { LOPT_CIRCUIT
, ARG_DUP
, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL
},
275 { LOPT_REMOTE
, ARG_DUP
, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL
},
276 { LOPT_SUBSCR
, ARG_DUP
, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL
},
277 { 'J', ARG_DUP
, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL
},
278 { LOPT_BROADCAST
, ARG_DUP
, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL
},
279 { 'k', OPT_NO_FORK
, NULL
, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL
},
280 { 'K', OPT_AUTHORITATIVE
, NULL
, gettext_noop("Assume we are the only DHCP server on the local network."), NULL
},
281 { 'l', ARG_ONE
, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE
},
282 { 'L', OPT_LOCALMX
, NULL
, gettext_noop("Return MX records for local hosts."), NULL
},
283 { 'm', ARG_DUP
, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL
},
284 { 'M', ARG_DUP
, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL
},
285 { 'n', OPT_NO_POLL
, NULL
, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE
},
286 { 'N', OPT_NO_NEG
, NULL
, gettext_noop("Do NOT cache failed search results."), NULL
},
287 { 'o', OPT_ORDER
, NULL
, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE
},
288 { 'O', ARG_DUP
, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL
},
289 { LOPT_FORCE
, ARG_DUP
, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL
},
290 { 'p', ARG_ONE
, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL
},
291 { 'P', ARG_ONE
, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
292 { 'q', OPT_LOG
, NULL
, gettext_noop("Log DNS queries."), NULL
},
293 { 'Q', ARG_ONE
, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL
},
294 { 'R', OPT_NO_RESOLV
, NULL
, gettext_noop("Do NOT read resolv.conf."), NULL
},
295 { 'r', ARG_DUP
, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE
},
296 { 'S', ARG_DUP
, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL
},
297 { LOPT_LOCAL
, ARG_DUP
, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL
},
298 { 's', ARG_DUP
, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL
},
299 { 't', ARG_ONE
, "host_name", gettext_noop("Specify default target in an MX record."), NULL
},
300 { 'T', ARG_ONE
, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL
},
301 { LOPT_NEGTTL
, ARG_ONE
, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL
},
302 { LOPT_MAXTTL
, ARG_ONE
, "time", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL
},
303 { 'u', ARG_ONE
, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER
},
304 { 'U', ARG_DUP
, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL
},
305 { 'v', 0, NULL
, gettext_noop("Display dnsmasq version and copyright information."), NULL
},
306 { 'V', ARG_DUP
, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL
},
307 { 'W', ARG_DUP
, "name,target,...", gettext_noop("Specify a SRV record."), NULL
},
308 { 'w', 0, NULL
, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL
},
309 { 'x', ARG_ONE
, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE
},
310 { 'X', ARG_ONE
, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
311 { 'y', OPT_LOCALISE
, NULL
, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL
},
312 { 'Y', ARG_DUP
, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL
},
313 { LOPT_PTR
, ARG_DUP
, "name,target", gettext_noop("Specify PTR DNS record."), NULL
},
314 { LOPT_INTNAME
, ARG_DUP
, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL
},
315 { 'z', OPT_NOWILD
, NULL
, gettext_noop("Bind only to interfaces in use."), NULL
},
316 { 'Z', OPT_ETHERS
, NULL
, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE
},
317 { '1', OPT_DBUS
, NULL
, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL
},
318 { '2', ARG_DUP
, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL
},
319 { '3', ARG_DUP
, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL
},
320 { '4', ARG_DUP
, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL
},
321 { LOPT_BRIDGE
, ARG_DUP
, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL
},
322 { '5', OPT_NO_PING
, NULL
, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL
},
323 { '6', ARG_ONE
, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL
},
324 { '7', ARG_DUP
, "path", gettext_noop("Read configuration from all the files in this directory."), NULL
},
325 { '8', ARG_ONE
, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL
},
326 { '9', OPT_LEASE_RO
, NULL
, gettext_noop("Do not use leasefile."), NULL
},
327 { '0', ARG_ONE
, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
328 { LOPT_RELOAD
, OPT_RELOAD
, NULL
, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE
},
329 { LOPT_NO_NAMES
, ARG_DUP
, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL
},
330 { LOPT_OVERRIDE
, OPT_NO_OVERRIDE
, NULL
, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL
},
331 { LOPT_TFTP
, ARG_DUP
, "[=<interface>]", gettext_noop("Enable integrated read-only TFTP server."), NULL
},
332 { LOPT_PREFIX
, ARG_ONE
, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL
},
333 { LOPT_APREF
, OPT_TFTP_APREF
, NULL
, gettext_noop("Add client IP address to tftp-root."), NULL
},
334 { LOPT_SECURE
, OPT_TFTP_SECURE
, NULL
, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL
},
335 { LOPT_TFTP_MAX
, ARG_ONE
, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
336 { LOPT_NOBLOCK
, OPT_TFTP_NOBLOCK
, NULL
, gettext_noop("Disable the TFTP blocksize extension."), NULL
},
337 { LOPT_TFTPPORTS
, ARG_ONE
, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL
},
338 { LOPT_LOG_OPTS
, OPT_LOG_OPTS
, NULL
, gettext_noop("Extra logging for DHCP."), NULL
},
339 { LOPT_MAX_LOGS
, ARG_ONE
, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL
},
340 { LOPT_REBIND
, OPT_NO_REBIND
, NULL
, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL
},
341 { LOPT_LOC_REBND
, OPT_LOCAL_REBIND
, NULL
, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL
},
342 { LOPT_NO_REBIND
, ARG_DUP
, "/domain/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL
},
343 { LOPT_NOLAST
, OPT_ALL_SERVERS
, NULL
, gettext_noop("Always perform DNS queries to all servers."), NULL
},
344 { LOPT_MATCH
, ARG_DUP
, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL
},
345 { LOPT_ALTPORT
, ARG_ONE
, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL
},
346 { LOPT_SCRIPTUSR
, ARG_ONE
, "<username>", gettext_noop("Run lease-change script as this user."), NULL
},
347 { LOPT_NAPTR
, ARG_DUP
, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL
},
348 { LOPT_MINPORT
, ARG_ONE
, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL
},
349 { LOPT_DHCP_FQDN
, OPT_DHCP_FQDN
, NULL
, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL
},
350 { LOPT_GEN_NAMES
, ARG_DUP
, "[=tag:<tag>]...", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL
},
351 { LOPT_PROXY
, ARG_DUP
, "[=<ip_address>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL
},
352 { LOPT_CNAME
, ARG_DUP
, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL
},
353 { LOPT_PXE_PROMT
, ARG_DUP
, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL
},
354 { LOPT_PXE_SERV
, ARG_DUP
, "<service>", gettext_noop("Boot service for PXE menu."), NULL
},
355 { LOPT_TEST
, 0, NULL
, gettext_noop("Check configuration syntax."), NULL
},
356 { LOPT_ADD_MAC
, OPT_ADD_MAC
, NULL
, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL
},
357 { LOPT_DNSSEC
, OPT_DNSSEC
, NULL
, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL
},
358 { LOPT_INCR_ADDR
, OPT_CONSEC_ADDR
, NULL
, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL
},
359 { LOPT_CONNTRACK
, OPT_CONNTRACK
, NULL
, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL
},
360 { LOPT_FQDN
, OPT_FQDN_UPDATE
, NULL
, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL
},
361 { LOPT_LUASCRIPT
, ARG_DUP
, "luascript", gettext_noop("Specify path to Lua script (no default)."), NULL
},
362 { 0, 0, NULL
, NULL
, NULL
}
366 #define OT_ADDR_LIST 0x80
367 #define OT_RFC1035_NAME 0x40
368 #define OT_INTERNAL 0x20
372 static const struct {
374 unsigned char val
, size
;
376 { "netmask", 1, OT_ADDR_LIST
},
377 { "time-offset", 2, 4 },
378 { "router", 3, OT_ADDR_LIST
},
379 { "dns-server", 6, OT_ADDR_LIST
},
380 { "log-server", 7, OT_ADDR_LIST
},
381 { "lpr-server", 9, OT_ADDR_LIST
},
382 { "hostname", 12, OT_INTERNAL
| OT_NAME
},
383 { "boot-file-size", 13, 2 },
384 { "domain-name", 15, OT_NAME
},
385 { "swap-server", 16, OT_ADDR_LIST
},
386 { "root-path", 17, OT_NAME
},
387 { "extension-path", 18, OT_NAME
},
388 { "ip-forward-enable", 19, 1 },
389 { "non-local-source-routing", 20, 1 },
390 { "policy-filter", 21, OT_ADDR_LIST
},
391 { "max-datagram-reassembly", 22, 2 },
392 { "default-ttl", 23, 1 },
394 { "all-subnets-local", 27, 1 },
395 { "broadcast", 28, OT_INTERNAL
| OT_ADDR_LIST
},
396 { "router-discovery", 31, 1 },
397 { "router-solicitation", 32, OT_ADDR_LIST
},
398 { "static-route", 33, OT_ADDR_LIST
},
399 { "trailer-encapsulation", 34, 1 },
400 { "arp-timeout", 35, 4 },
401 { "ethernet-encap", 36, 1 },
402 { "tcp-ttl", 37, 1 },
403 { "tcp-keepalive", 38, 4 },
404 { "nis-domain", 40, OT_NAME
},
405 { "nis-server", 41, OT_ADDR_LIST
},
406 { "ntp-server", 42, OT_ADDR_LIST
},
407 { "vendor-encap", 43, OT_INTERNAL
},
408 { "netbios-ns", 44, OT_ADDR_LIST
},
409 { "netbios-dd", 45, OT_ADDR_LIST
},
410 { "netbios-nodetype", 46, 1 },
411 { "netbios-scope", 47, 0 },
412 { "x-windows-fs", 48, OT_ADDR_LIST
},
413 { "x-windows-dm", 49, OT_ADDR_LIST
},
414 { "requested-address", 50, OT_INTERNAL
| OT_ADDR_LIST
},
415 { "lease-time", 51, OT_INTERNAL
},
416 { "option-overload", 52, OT_INTERNAL
},
417 { "message-type", 53, OT_INTERNAL
, },
418 { "server-identifier", 54, OT_INTERNAL
| OT_ADDR_LIST
},
419 { "parameter-request", 55, OT_INTERNAL
},
420 { "message", 56, OT_INTERNAL
},
421 { "max-message-size", 57, OT_INTERNAL
},
422 { "T1", 58, OT_INTERNAL
},
423 { "T2", 59, OT_INTERNAL
},
424 { "vendor-class", 60, 0 },
425 { "client-id", 61,OT_INTERNAL
},
426 { "nis+-domain", 64, OT_NAME
},
427 { "nis+-server", 65, OT_ADDR_LIST
},
428 { "tftp-server", 66, OT_NAME
},
429 { "bootfile-name", 67, OT_NAME
},
430 { "mobile-ip-home", 68, OT_ADDR_LIST
},
431 { "smtp-server", 69, OT_ADDR_LIST
},
432 { "pop3-server", 70, OT_ADDR_LIST
},
433 { "nntp-server", 71, OT_ADDR_LIST
},
434 { "irc-server", 74, OT_ADDR_LIST
},
435 { "user-class", 77, 0 },
436 { "FQDN", 81, OT_INTERNAL
},
437 { "agent-id", 82, OT_INTERNAL
},
438 { "client-arch", 93, 2 },
439 { "client-interface-id", 94, 0 },
440 { "client-machine-id", 97, 0 },
441 { "subnet-select", 118, OT_INTERNAL
},
442 { "domain-search", 119, OT_RFC1035_NAME
},
443 { "sip-server", 120, 0 },
444 { "classless-static-route", 121, 0 },
445 { "vendor-id-encap", 125, 0 },
446 { "server-ip-address", 255, OT_ADDR_LIST
}, /* special, internal only, sets siaddr */
450 char *option_string(unsigned char opt
, int *is_ip
, int *is_name
)
454 for (i
= 0; opttab
[i
].name
; i
++)
455 if (opttab
[i
].val
== opt
)
458 *is_ip
= !!(opttab
[i
].size
& OT_ADDR_LIST
);
460 *is_name
= !!(opttab
[i
].size
& OT_NAME
);
461 return opttab
[i
].name
;
469 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
470 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
471 following sequence so that they map to themselves: it is therefore possible to call
472 unhide_metas repeatedly on string without breaking things.
473 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
474 couple of other places.
475 Note that space is included here so that
476 --dhcp-option=3, string
477 has five characters, whilst
478 --dhcp-option=3," string"
482 static const char meta
[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
484 static char hide_meta(char c
)
488 for (i
= 0; i
< (sizeof(meta
) - 1); i
++)
495 static char unhide_meta(char cr
)
499 if (c
< (sizeof(meta
) - 1))
505 static void unhide_metas(char *cp
)
509 *cp
= unhide_meta(*cp
);
512 static void *opt_malloc(size_t size
)
518 ret
= whine_malloc(size
);
523 ret
= safe_malloc(size
);
528 static char *opt_string_alloc(char *cp
)
532 if (cp
&& strlen(cp
) != 0)
534 ret
= opt_malloc(strlen(cp
)+1);
537 /* restore hidden metachars */
545 /* find next comma, split string with zero and eliminate spaces.
546 return start of string following comma */
548 static char *split_chr(char *s
, char c
)
552 if (!s
|| !(comma
= strchr(s
, c
)))
558 for (; *comma
== ' '; comma
++);
560 for (; (p
>= s
) && *p
== ' '; p
--)
566 static char *split(char *s
)
568 return split_chr(s
, ',');
571 static char *canonicalise_opt(char *s
)
580 if (!(ret
= canonicalise(s
, &nomem
)) && nomem
)
585 die(_("could not get memory"), NULL
, EC_NOMEM
);
591 static int atoi_check(char *a
, int *res
)
601 if (*p
< '0' || *p
> '9')
608 static int atoi_check16(char *a
, int *res
)
610 if (!(atoi_check(a
, res
)) ||
618 static void add_txt(char *name
, char *txt
)
620 size_t len
= strlen(txt
);
621 struct txt_record
*r
= opt_malloc(sizeof(struct txt_record
));
623 r
->name
= opt_string_alloc(name
);
624 r
->next
= daemon
->txt
;
627 r
->txt
= opt_malloc(len
+1);
630 memcpy((r
->txt
)+1, txt
, len
);
633 static void do_usage(void)
646 { '#', TFTP_MAX_CONNECTIONS
},
650 printf(_("Usage: dnsmasq [options]\n\n"));
651 #ifndef HAVE_GETOPT_LONG
652 printf(_("Use short options only on the command line.\n"));
654 printf(_("Valid options are:\n"));
656 for (i
= 0; usage
[i
].opt
!= 0; i
++)
658 char *desc
= usage
[i
].flagdesc
;
661 if (!desc
|| *desc
== '[')
667 for ( j
= 0; opts
[j
].name
; j
++)
668 if (opts
[j
].val
== usage
[i
].opt
)
670 if (usage
[i
].opt
< 256)
671 sprintf(buff
, "-%c, ", usage
[i
].opt
);
675 sprintf(buff
+4, "--%s%s%s", opts
[j
].name
, eq
, desc
);
676 printf("%-40.40s", buff
);
680 strcpy(buff
, usage
[i
].arg
);
681 for (j
= 0; tab
[j
].handle
; j
++)
682 if (tab
[j
].handle
== *(usage
[i
].arg
))
683 sprintf(buff
, "%d", tab
[j
].val
);
685 printf(_(usage
[i
].desc
), buff
);
691 static void display_opts(void)
695 printf(_("Known DHCP options:\n"));
697 for (i
= 0; opttab
[i
].name
; i
++)
698 if (!(opttab
[i
].size
& OT_INTERNAL
))
699 printf("%3d %s\n", opttab
[i
].val
, opttab
[i
].name
);
702 static int is_tag_prefix(char *arg
)
704 if (arg
&& (strstr(arg
, "net:") == arg
|| strstr(arg
, "tag:") == arg
))
710 static char *set_prefix(char *arg
)
712 if (strstr(arg
, "set:") == arg
)
718 /* This is too insanely large to keep in-line in the switch */
719 static char *parse_dhcp_opt(char *arg
, int flags
)
721 struct dhcp_opt
*new = opt_malloc(sizeof(struct dhcp_opt
));
722 char lenchar
= 0, *cp
;
723 int i
, addrs
, digs
, is_addr
, is_hex
, is_dec
, is_string
, dots
;
724 char *comma
= NULL
, *problem
= NULL
;
725 struct dhcp_netid
*np
= NULL
;
726 unsigned char opt_len
= 0;
738 for (cp
= arg
; *cp
; cp
++)
739 if (*cp
< '0' || *cp
> '9')
744 new->opt
= atoi(arg
);
749 if (strstr(arg
, "option:") == arg
)
751 for (i
= 0; opttab
[i
].name
; i
++)
752 if (!(opttab
[i
].size
& OT_INTERNAL
) &&
753 strcasecmp(opttab
[i
].name
, arg
+7) == 0)
755 new->opt
= opttab
[i
].val
;
756 opt_len
= opttab
[i
].size
;
759 /* option:<optname> must follow tag and vendor string. */
762 else if (strstr(arg
, "vendor:") == arg
)
764 new->u
.vendor_class
= (unsigned char *)opt_string_alloc(arg
+7);
765 new->flags
|= DHOPT_VENDOR
;
767 else if (strstr(arg
, "encap:") == arg
)
769 new->u
.encap
= atoi(arg
+6);
770 new->flags
|= DHOPT_ENCAPSULATE
;
772 else if (strstr(arg
, "vi-encap:") == arg
)
774 new->u
.encap
= atoi(arg
+9);
775 new->flags
|= DHOPT_RFC3925
;
776 if (flags
== DHOPT_MATCH
)
778 new->opt
= 1; /* avoid error below */
784 new->netid
= opt_malloc(sizeof (struct dhcp_netid
));
785 /* allow optional "net:" or "tag:" for consistency */
786 if (is_tag_prefix(arg
))
787 new->netid
->net
= opt_string_alloc(arg
+4);
789 new->netid
->net
= opt_string_alloc(set_prefix(arg
));
790 new->netid
->next
= np
;
798 !(new->flags
& (DHOPT_VENDOR
| DHOPT_ENCAPSULATE
| DHOPT_RFC3925
)))
799 for (i
= 0; opttab
[i
].name
; i
++)
800 if (new->opt
== opttab
[i
].val
)
802 opt_len
= opttab
[i
].size
;
803 if (opt_len
& OT_INTERNAL
)
808 /* option may be missing with rfc3925 match */
810 problem
= _("bad dhcp-option");
813 /* characterise the value */
816 is_addr
= is_hex
= is_dec
= is_string
= 1;
819 for (cp
= comma
; (c
= *cp
); cp
++)
828 is_dec
= is_addr
= 0;
833 if (cp
== comma
) /* leading / means a pathname */
842 is_hex
= is_addr
= 0;
845 else if (!(c
>='0' && c
<= '9'))
848 if (cp
[1] == 0 && is_dec
&&
849 (c
== 'b' || c
== 's' || c
== 'i'))
856 if (!((c
>='A' && c
<= 'F') ||
857 (c
>='a' && c
<= 'f') ||
858 (c
== '*' && (flags
& DHOPT_MATCH
))))
865 is_dec
= is_addr
= 0;
867 /* We know that some options take addresses */
868 if (opt_len
& OT_ADDR_LIST
)
870 is_string
= is_dec
= is_hex
= 0;
871 if (!is_addr
|| dots
== 0)
872 problem
= _("bad IP address");
875 else if (opt_len
& (OT_NAME
| OT_RFC1035_NAME
))
876 is_addr
= is_dec
= is_hex
= 0;
878 if (is_hex
&& digs
> 1)
881 new->val
= opt_malloc(new->len
);
882 parse_hex(comma
, new->val
, digs
, (flags
& DHOPT_MATCH
) ? &new->u
.wildcard_mask
: NULL
, NULL
);
883 new->flags
|= DHOPT_HEX
;
887 int i
, val
= atoi(comma
);
888 /* assume numeric arg is 1 byte except for
889 options where it is known otherwise.
890 For vendor class option, we have to hack. */
893 else if (val
& 0xffff0000)
895 else if (val
& 0xff00)
902 else if (lenchar
== 's')
904 else if (lenchar
== 'i')
907 new->val
= opt_malloc(new->len
);
908 for (i
=0; i
<new->len
; i
++)
909 new->val
[i
] = val
>>((new->len
- i
- 1)*8);
916 /* max length of address/subnet descriptor is five bytes,
917 add one for the option 120 enc byte too */
918 new->val
= op
= opt_malloc((5 * addrs
) + 1);
919 new->flags
|= DHOPT_ADDR
;
921 if (!(new->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)) &&
922 new->opt
== OPTION_SIP_SERVER
)
924 *(op
++) = 1; /* RFC 3361 "enc byte" */
925 new->flags
&= ~DHOPT_ADDR
;
931 slash
= split_chr(cp
, '/');
932 in
.s_addr
= inet_addr(cp
);
935 memcpy(op
, &in
, INADDRSZ
);
940 unsigned char *p
= (unsigned char *)&in
;
941 int netsize
= atoi(slash
);
951 new->flags
&= ~DHOPT_ADDR
; /* cannot re-write descriptor format */
954 new->len
= op
- new->val
;
959 if ((new->opt
== OPTION_DOMAIN_SEARCH
|| new->opt
== OPTION_SIP_SERVER
) &&
960 !(new->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)))
962 /* dns search, RFC 3397, or SIP, RFC 3361 */
963 unsigned char *q
, *r
, *tail
;
964 unsigned char *p
, *m
= NULL
, *newp
;
965 size_t newlen
, len
= 0;
966 int header_size
= (new->opt
== OPTION_DOMAIN_SEARCH
) ? 0 : 1;
973 char *in
, *dom
= NULL
;
975 /* Allow "." as an empty domain */
976 if (strcmp (arg
, ".") != 0)
978 if (!(dom
= canonicalise_opt(arg
)))
980 problem
= _("bad domain in dhcp-option");
983 domlen
= strlen(dom
) + 2;
986 newp
= opt_malloc(len
+ domlen
+ header_size
);
989 memcpy(newp
, m
, header_size
+ len
);
996 /* add string on the end in RFC1035 format */
997 for (in
= dom
; in
&& *in
;)
999 unsigned char *cp
= q
++;
1001 for (j
= 0; *in
&& (*in
!= '.'); in
++, j
++)
1010 /* Now tail-compress using earlier names. */
1012 for (tail
= p
+ len
; *tail
; tail
+= (*tail
) + 1)
1013 for (r
= p
; r
- p
< (int)len
; r
+= (*r
) + 1)
1014 if (strcmp((char *)r
, (char *)tail
) == 0)
1016 PUTSHORT((r
- p
) | 0xc000, tail
);
1027 /* RFC 3361, enc byte is zero for names */
1028 if (new->opt
== OPTION_SIP_SERVER
)
1030 new->len
= (int) len
+ header_size
;
1035 new->len
= strlen(comma
);
1036 /* keep terminating zero on string */
1037 new->val
= (unsigned char *)opt_string_alloc(comma
);
1038 new->flags
|= DHOPT_STRING
;
1043 if ((new->len
> 255) ||
1044 (new->len
> 253 && (new->flags
& (DHOPT_VENDOR
| DHOPT_ENCAPSULATE
))) ||
1045 (new->len
> 250 && (new->flags
& DHOPT_RFC3925
)))
1046 problem
= _("dhcp-option too long");
1050 if (flags
== DHOPT_MATCH
)
1052 if ((new->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
)) ||
1055 problem
= _("illegal dhcp-match");
1058 new->next
= daemon
->dhcp_match
;
1059 daemon
->dhcp_match
= new;
1064 new->next
= daemon
->dhcp_opts
;
1065 daemon
->dhcp_opts
= new;
1074 void set_option_bool(unsigned int opt
)
1077 daemon
->options
|= 1u << opt
;
1079 daemon
->options2
|= 1u << (opt
- 32);
1082 static char *one_opt(int option
, char *arg
, char *gen_prob
, int command_line
)
1085 char *comma
, *problem
= NULL
;;
1090 for (i
=0; usage
[i
].opt
!= 0; i
++)
1091 if (usage
[i
].opt
== option
)
1093 int rept
= usage
[i
].rept
;
1098 if (rept
== ARG_USED_CL
)
1099 return _("illegal repeated flag");
1100 if (rept
== ARG_ONE
)
1101 usage
[i
].rept
= ARG_USED_CL
;
1105 /* allow file to override command line */
1106 if (rept
== ARG_USED_FILE
)
1107 return _("illegal repeated keyword");
1108 if (rept
== ARG_USED_CL
|| rept
== ARG_ONE
)
1109 usage
[i
].rept
= ARG_USED_FILE
;
1112 if (rept
!= ARG_DUP
&& rept
!= ARG_ONE
&& rept
!= ARG_USED_CL
)
1114 set_option_bool(rept
);
1123 case 'C': /* --conf-file */
1125 char *file
= opt_string_alloc(arg
);
1134 case '7': /* --conf-dir */
1138 char *directory
, *path
;
1142 } *ignore_suffix
= NULL
, *li
;
1145 if (!(directory
= opt_string_alloc(arg
)))
1148 for (arg
= comma
; arg
; arg
= comma
)
1151 li
= opt_malloc(sizeof(struct list
));
1152 li
->next
= ignore_suffix
;
1154 /* Have to copy: buffer is overwritten */
1155 li
->suffix
= opt_string_alloc(arg
);
1158 if (!(dir_stream
= opendir(directory
)))
1159 die(_("cannot access directory %s: %s"), directory
, EC_FILE
);
1161 while ((ent
= readdir(dir_stream
)))
1163 size_t len
= strlen(ent
->d_name
);
1166 /* ignore emacs backups and dotfiles */
1168 ent
->d_name
[len
- 1] == '~' ||
1169 (ent
->d_name
[0] == '#' && ent
->d_name
[len
- 1] == '#') ||
1170 ent
->d_name
[0] == '.')
1173 for (li
= ignore_suffix
; li
; li
= li
->next
)
1175 /* check for proscribed suffices */
1176 size_t ls
= strlen(li
->suffix
);
1178 strcmp(li
->suffix
, &ent
->d_name
[len
- ls
]) == 0)
1184 path
= opt_malloc(strlen(directory
) + len
+ 2);
1185 strcpy(path
, directory
);
1187 strcat(path
, ent
->d_name
);
1189 if (stat(path
, &buf
) == -1)
1190 die(_("cannot access %s: %s"), path
, EC_FILE
);
1191 /* only reg files allowed. */
1192 if (!S_ISREG(buf
.st_mode
))
1195 /* files must be readable */
1200 closedir(dir_stream
);
1202 for(; ignore_suffix
; ignore_suffix
= li
)
1204 li
= ignore_suffix
->next
;
1205 free(ignore_suffix
->suffix
);
1206 free(ignore_suffix
);
1212 case '8': /* --log-facility */
1213 /* may be a filename */
1214 if (strchr(arg
, '/') || strcmp (arg
, "-") == 0)
1215 daemon
->log_file
= opt_string_alloc(arg
);
1219 problem
= _("setting log facility is not possible under Android");
1221 for (i
= 0; facilitynames
[i
].c_name
; i
++)
1222 if (hostname_isequal((char *)facilitynames
[i
].c_name
, arg
))
1225 if (facilitynames
[i
].c_name
)
1226 daemon
->log_fac
= facilitynames
[i
].c_val
;
1228 problem
= _("bad log facility");
1233 case 'x': /* --pid-file */
1234 daemon
->runfile
= opt_string_alloc(arg
);
1237 case 'r': /* --resolv-file */
1239 char *name
= opt_string_alloc(arg
);
1240 struct resolvc
*new, *list
= daemon
->resolv_files
;
1242 if (list
&& list
->is_default
)
1244 /* replace default resolv file - possibly with nothing */
1247 list
->is_default
= 0;
1255 new = opt_malloc(sizeof(struct resolvc
));
1258 new->is_default
= 0;
1263 daemon
->resolv_files
= list
;
1267 case 'm': /* --mx-host */
1270 struct mx_srv_record
*new;
1271 char *name
, *target
= NULL
;
1273 if ((comma
= split(arg
)))
1276 if ((prefstr
= split(comma
)) && !atoi_check16(prefstr
, &pref
))
1277 problem
= _("bad MX preference");
1280 if (!(name
= canonicalise_opt(arg
)) ||
1281 (comma
&& !(target
= canonicalise_opt(comma
))))
1282 problem
= _("bad MX name");
1284 new = opt_malloc(sizeof(struct mx_srv_record
));
1285 new->next
= daemon
->mxnames
;
1286 daemon
->mxnames
= new;
1289 new->target
= target
; /* may be NULL */
1294 case 't': /* --mx-target */
1295 if (!(daemon
->mxtarget
= canonicalise_opt(arg
)))
1296 problem
= _("bad MX target");
1300 case 'l': /* --dhcp-leasefile */
1301 daemon
->lease_file
= opt_string_alloc(arg
);
1304 /* Sorry about the gross pre-processor abuse */
1305 case '6': /* --dhcp-script */
1306 case LOPT_LUASCRIPT
: /* --dhcp-luascript */
1307 # if defined(NO_FORK)
1308 problem
= _("cannot run scripts under uClinux");
1309 # elif !defined(HAVE_SCRIPT)
1310 problem
= _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1312 if (option
== LOPT_LUASCRIPT
)
1313 # if !defined(HAVE_LUASCRIPT)
1314 problem
= _("recompile with HAVE_LUASCRIPT defined to enable Lua scripts");
1316 daemon
->luascript
= opt_string_alloc(arg
);
1319 daemon
->lease_change_command
= opt_string_alloc(arg
);
1322 #endif /* HAVE_DHCP */
1324 case LOPT_DHCP_HOST
: /* --dhcp-hostfile */
1325 case LOPT_DHCP_OPTS
: /* --dhcp-optsfile */
1326 case 'H': /* --addn-hosts */
1328 struct hostsfile
*new = opt_malloc(sizeof(struct hostsfile
));
1329 static int hosts_index
= 1;
1330 new->fname
= opt_string_alloc(arg
);
1331 new->index
= hosts_index
++;
1335 new->next
= daemon
->addn_hosts
;
1336 daemon
->addn_hosts
= new;
1338 else if (option
== LOPT_DHCP_HOST
)
1340 new->next
= daemon
->dhcp_hosts_file
;
1341 daemon
->dhcp_hosts_file
= new;
1343 else if (option
== LOPT_DHCP_OPTS
)
1345 new->next
= daemon
->dhcp_opts_file
;
1346 daemon
->dhcp_opts_file
= new;
1351 case 's': /* --domain */
1352 if (strcmp (arg
, "#") == 0)
1353 set_option_bool(OPT_RESOLV_DOMAIN
);
1358 if (!(d
= canonicalise_opt(arg
)))
1364 struct cond_domain
*new = safe_malloc(sizeof(struct cond_domain
));
1367 unhide_metas(comma
);
1368 if ((netpart
= split_chr(comma
, '/')))
1371 arg
= split(netpart
);
1372 if ((new->start
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1 ||
1373 !atoi_check(netpart
, &msize
))
1377 mask
= (1 << (32 - msize
)) - 1;
1378 new->start
.s_addr
= ntohl(htonl(new->start
.s_addr
) & ~mask
);
1379 new->end
.s_addr
= new->start
.s_addr
| htonl(mask
);
1382 /* generate the equivalent of
1384 local=/xxx.yyy.zzz.in-addr.arpa/ */
1386 if (strcmp(arg
, "local") != 0 ||
1387 (msize
!= 8 && msize
!= 16 && msize
!= 24))
1391 struct server
*serv
= opt_malloc(sizeof(struct server
));
1392 in_addr_t a
= ntohl(new->start
.s_addr
) >> 8;
1395 memset(serv
, 0, sizeof(struct server
));
1397 serv
->flags
= SERV_HAS_DOMAIN
| SERV_NO_ADDR
;
1398 serv
->next
= daemon
->servers
;
1399 daemon
->servers
= serv
;
1401 serv
= opt_malloc(sizeof(struct server
));
1402 memset(serv
, 0, sizeof(struct server
));
1403 p
= serv
->domain
= opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
1406 p
+= sprintf(p
, "%d.", a
& 0xff);
1409 p
+= sprintf(p
, "%d.", a
& 0xff);
1411 p
+= sprintf(p
, "%d.in-addr.arpa", a
& 0xff);
1413 serv
->flags
= SERV_HAS_DOMAIN
| SERV_NO_ADDR
;
1414 serv
->next
= daemon
->servers
;
1415 daemon
->servers
= serv
;
1420 else if ((arg
= split(comma
)))
1422 if ((new->start
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1 ||
1423 (new->end
.s_addr
= inet_addr(arg
)) == (in_addr_t
)-1)
1426 else if ((new->start
.s_addr
= new->end
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
1430 new->next
= daemon
->cond_domain
;
1431 daemon
->cond_domain
= new;
1434 daemon
->domain_suffix
= d
;
1439 case 'u': /* --user */
1440 daemon
->username
= opt_string_alloc(arg
);
1443 case 'g': /* --group */
1444 daemon
->groupname
= opt_string_alloc(arg
);
1445 daemon
->group_set
= 1;
1449 case LOPT_SCRIPTUSR
: /* --scriptuser */
1450 daemon
->scriptuser
= opt_string_alloc(arg
);
1454 case 'i': /* --interface */
1456 struct iname
*new = opt_malloc(sizeof(struct iname
));
1458 new->next
= daemon
->if_names
;
1459 daemon
->if_names
= new;
1460 /* new->name may be NULL if someone does
1461 "interface=" to disable all interfaces except loop. */
1462 new->name
= opt_string_alloc(arg
);
1463 new->isloop
= new->used
= 0;
1468 case 'I': /* --except-interface */
1469 case '2': /* --no-dhcp-interface */
1471 struct iname
*new = opt_malloc(sizeof(struct iname
));
1473 new->name
= opt_string_alloc(arg
);
1476 new->next
= daemon
->if_except
;
1477 daemon
->if_except
= new;
1481 new->next
= daemon
->dhcp_except
;
1482 daemon
->dhcp_except
= new;
1488 case 'B': /* --bogus-nxdomain */
1490 struct in_addr addr
;
1492 if (arg
&& (addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
)-1)
1494 struct bogus_addr
*baddr
= opt_malloc(sizeof(struct bogus_addr
));
1495 baddr
->next
= daemon
->bogus_addr
;
1496 daemon
->bogus_addr
= baddr
;
1500 option
= '?'; /* error */
1504 case 'a': /* --listen-address */
1506 struct iname
*new = opt_malloc(sizeof(struct iname
));
1509 new->next
= daemon
->if_addrs
;
1510 if (arg
&& (new->addr
.in
.sin_addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
)-1)
1512 new->addr
.sa
.sa_family
= AF_INET
;
1513 #ifdef HAVE_SOCKADDR_SA_LEN
1514 new->addr
.in
.sin_len
= sizeof(new->addr
.in
);
1518 else if (arg
&& inet_pton(AF_INET6
, arg
, &new->addr
.in6
.sin6_addr
) > 0)
1520 new->addr
.sa
.sa_family
= AF_INET6
;
1521 new->addr
.in6
.sin6_flowinfo
= 0;
1522 new->addr
.in6
.sin6_scope_id
= 0;
1523 #ifdef HAVE_SOCKADDR_SA_LEN
1524 new->addr
.in6
.sin6_len
= sizeof(new->addr
.in6
);
1530 option
= '?'; /* error */
1534 daemon
->if_addrs
= new;
1539 case 'S': /* --server */
1540 case LOPT_LOCAL
: /* --local */
1541 case 'A': /* --address */
1542 case LOPT_NO_REBIND
: /* --rebind-domain-ok */
1544 struct server
*serv
, *newlist
= NULL
;
1548 if (arg
&& (*arg
== '/' || option
== LOPT_NO_REBIND
))
1550 int rebind
= !(*arg
== '/');
1554 while (rebind
|| (end
= split_chr(arg
, '/')))
1556 char *domain
= NULL
;
1557 /* elide leading dots - they are implied in the search algorithm */
1558 while (*arg
== '.') arg
++;
1559 /* # matches everything and becomes a zero length domain string */
1560 if (strcmp(arg
, "#") == 0)
1562 else if (strlen (arg
) != 0 && !(domain
= canonicalise_opt(arg
)))
1564 serv
= opt_malloc(sizeof(struct server
));
1565 memset(serv
, 0, sizeof(struct server
));
1566 serv
->next
= newlist
;
1568 serv
->domain
= domain
;
1569 serv
->flags
= domain
? SERV_HAS_DOMAIN
: SERV_FOR_NODOTS
;
1583 newlist
= opt_malloc(sizeof(struct server
));
1584 memset(newlist
, 0, sizeof(struct server
));
1589 newlist
->flags
|= SERV_LITERAL_ADDRESS
;
1590 if (!(newlist
->flags
& SERV_TYPE
))
1593 else if (option
== LOPT_NO_REBIND
)
1594 newlist
->flags
|= SERV_NO_REBIND
;
1598 if (!(newlist
->flags
& SERV_NO_REBIND
))
1599 newlist
->flags
|= SERV_NO_ADDR
; /* no server */
1600 if (newlist
->flags
& SERV_LITERAL_ADDRESS
)
1604 else if (strcmp(arg
, "#") == 0)
1606 newlist
->flags
|= SERV_USE_RESOLV
; /* treat in ordinary way */
1607 if (newlist
->flags
& SERV_LITERAL_ADDRESS
)
1612 int source_port
= 0, serv_port
= NAMESERVER_PORT
;
1613 char *portno
, *source
;
1615 int scope_index
= 0;
1619 if ((source
= split_chr(arg
, '@')) && /* is there a source. */
1620 (portno
= split_chr(source
, '#')) &&
1621 !atoi_check16(portno
, &source_port
))
1622 problem
= _("bad port");
1624 if ((portno
= split_chr(arg
, '#')) && /* is there a port no. */
1625 !atoi_check16(portno
, &serv_port
))
1626 problem
= _("bad port");
1629 scope_id
= split_chr(arg
, '%');
1632 if ((newlist
->addr
.in
.sin_addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
) -1)
1634 newlist
->addr
.in
.sin_port
= htons(serv_port
);
1635 newlist
->source_addr
.in
.sin_port
= htons(source_port
);
1636 newlist
->addr
.sa
.sa_family
= newlist
->source_addr
.sa
.sa_family
= AF_INET
;
1637 #ifdef HAVE_SOCKADDR_SA_LEN
1638 newlist
->source_addr
.in
.sin_len
= newlist
->addr
.in
.sin_len
= sizeof(struct sockaddr_in
);
1642 newlist
->flags
|= SERV_HAS_SOURCE
;
1643 if ((newlist
->source_addr
.in
.sin_addr
.s_addr
= inet_addr(source
)) == (in_addr_t
) -1)
1645 #if defined(SO_BINDTODEVICE)
1646 newlist
->source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
1647 strncpy(newlist
->interface
, source
, IF_NAMESIZE
- 1);
1649 problem
= _("interface binding not supported");
1654 newlist
->source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
1657 else if (inet_pton(AF_INET6
, arg
, &newlist
->addr
.in6
.sin6_addr
) > 0)
1659 if (scope_id
&& (scope_index
= if_nametoindex(scope_id
)) == 0)
1660 problem
= _("bad interface name");
1662 newlist
->addr
.in6
.sin6_port
= htons(serv_port
);
1663 newlist
->addr
.in6
.sin6_scope_id
= scope_index
;
1664 newlist
->source_addr
.in6
.sin6_port
= htons(source_port
);
1665 newlist
->source_addr
.in6
.sin6_scope_id
= 0;
1666 newlist
->addr
.sa
.sa_family
= newlist
->source_addr
.sa
.sa_family
= AF_INET6
;
1667 newlist
->addr
.in6
.sin6_flowinfo
= newlist
->source_addr
.in6
.sin6_flowinfo
= 0;
1668 #ifdef HAVE_SOCKADDR_SA_LEN
1669 newlist
->addr
.in6
.sin6_len
= newlist
->source_addr
.in6
.sin6_len
= sizeof(newlist
->addr
.in6
);
1673 newlist
->flags
|= SERV_HAS_SOURCE
;
1674 if (inet_pton(AF_INET6
, source
, &newlist
->source_addr
.in6
.sin6_addr
) == 0)
1676 #if defined(SO_BINDTODEVICE)
1677 newlist
->source_addr
.in6
.sin6_addr
= in6addr_any
;
1678 strncpy(newlist
->interface
, source
, IF_NAMESIZE
- 1);
1680 problem
= _("interface binding not supported");
1685 newlist
->source_addr
.in6
.sin6_addr
= in6addr_any
;
1689 option
= '?'; /* error */
1695 serv
->next
->flags
= serv
->flags
;
1696 serv
->next
->addr
= serv
->addr
;
1697 serv
->next
->source_addr
= serv
->source_addr
;
1700 serv
->next
= daemon
->servers
;
1701 daemon
->servers
= newlist
;
1705 case 'c': /* --cache-size */
1709 if (!atoi_check(arg
, &size
))
1713 /* zero is OK, and means no caching. */
1717 else if (size
> 10000)
1720 daemon
->cachesize
= size
;
1725 case 'p': /* --port */
1726 if (!atoi_check16(arg
, &daemon
->port
))
1730 case LOPT_MINPORT
: /* --min-port */
1731 if (!atoi_check16(arg
, &daemon
->min_port
))
1735 case '0': /* --dns-forward-max */
1736 if (!atoi_check(arg
, &daemon
->ftabsize
))
1740 case LOPT_MAX_LOGS
: /* --log-async */
1741 daemon
->max_logs
= LOG_MAX
; /* default */
1742 if (arg
&& !atoi_check(arg
, &daemon
->max_logs
))
1744 else if (daemon
->max_logs
> 100)
1745 daemon
->max_logs
= 100;
1748 case 'P': /* --edns-packet-max */
1751 if (!atoi_check(arg
, &i
))
1753 daemon
->edns_pktsz
= (unsigned short)i
;
1757 case 'Q': /* --query-port */
1758 if (!atoi_check16(arg
, &daemon
->query_port
))
1760 /* if explicitly set to zero, use single OS ephemeral port
1761 and disable random ports */
1762 if (daemon
->query_port
== 0)
1766 case 'T': /* --local-ttl */
1767 case LOPT_NEGTTL
: /* --neg-ttl */
1768 case LOPT_MAXTTL
: /* --max-ttl */
1771 if (!atoi_check(arg
, &ttl
))
1773 else if (option
== LOPT_NEGTTL
)
1774 daemon
->neg_ttl
= (unsigned long)ttl
;
1775 else if (option
== LOPT_MAXTTL
)
1776 daemon
->max_ttl
= (unsigned long)ttl
;
1778 daemon
->local_ttl
= (unsigned long)ttl
;
1783 case 'X': /* --dhcp-lease-max */
1784 if (!atoi_check(arg
, &daemon
->dhcp_max
))
1790 case LOPT_TFTP
: /* --enable-tftp */
1793 struct interface_list
*new = opt_malloc(sizeof(struct interface_list
));
1794 new->interface
= opt_string_alloc(arg
);
1795 new->next
= daemon
->tftp_interfaces
;
1796 daemon
->tftp_interfaces
= new;
1799 daemon
->tftp_unlimited
= 1;
1802 case LOPT_TFTP_MAX
: /* --tftp-max */
1803 if (!atoi_check(arg
, &daemon
->tftp_max
))
1807 case LOPT_PREFIX
: /* --tftp-prefix */
1811 struct tftp_prefix
*new = opt_malloc(sizeof(struct tftp_prefix
));
1812 new->interface
= opt_string_alloc(comma
);
1813 new->prefix
= opt_string_alloc(arg
);
1814 new->next
= daemon
->if_prefix
;
1815 daemon
->if_prefix
= new;
1818 daemon
->tftp_prefix
= opt_string_alloc(arg
);
1821 case LOPT_TFTPPORTS
: /* --tftp-port-range */
1822 if (!(comma
= split(arg
)) ||
1823 !atoi_check16(arg
, &daemon
->start_tftp_port
) ||
1824 !atoi_check16(comma
, &daemon
->end_tftp_port
))
1825 problem
= _("bad port range");
1827 if (daemon
->start_tftp_port
> daemon
->end_tftp_port
)
1829 int tmp
= daemon
->start_tftp_port
;
1830 daemon
->start_tftp_port
= daemon
->end_tftp_port
;
1831 daemon
->end_tftp_port
= tmp
;
1837 case LOPT_BRIDGE
: /* --bridge-interface */
1839 struct dhcp_bridge
*new = opt_malloc(sizeof(struct dhcp_bridge
));
1840 if (!(comma
= split(arg
)) || strlen(arg
) > IF_NAMESIZE
- 1 )
1842 problem
= _("bad bridge-interface");
1846 strcpy(new->iface
, arg
);
1848 new->next
= daemon
->bridges
;
1849 daemon
->bridges
= new;
1854 if (strlen(arg
) != 0 && strlen(arg
) <= IF_NAMESIZE
- 1)
1856 struct dhcp_bridge
*b
= opt_malloc(sizeof(struct dhcp_bridge
));
1857 b
->next
= new->alias
;
1859 strcpy(b
->iface
, arg
);
1867 case 'F': /* --dhcp-range */
1869 int k
, leasepos
= 2;
1870 char *cp
, *a
[5] = { NULL
, NULL
, NULL
, NULL
, NULL
};
1871 struct dhcp_context
*new = opt_malloc(sizeof(struct dhcp_context
));
1873 new->next
= daemon
->dhcp
;
1874 new->lease_time
= DEFLEASE
;
1875 new->addr_epoch
= 0;
1876 new->netmask
.s_addr
= 0;
1877 new->broadcast
.s_addr
= 0;
1878 new->router
.s_addr
= 0;
1879 new->local
.s_addr
= 0;
1880 new->netid
.net
= NULL
;
1883 new->interface
= NULL
;
1885 gen_prob
= _("bad dhcp-range");
1895 for (cp
= arg
; *cp
; cp
++)
1896 if (!(*cp
== ' ' || *cp
== '.' || (*cp
>='0' && *cp
<= '9')))
1899 if (*cp
!= ',' && (comma
= split(arg
)))
1901 if (strstr(arg
, "interface:") == arg
)
1902 new->interface
= opt_string_alloc(arg
+10);
1903 else if (is_tag_prefix(arg
))
1905 struct dhcp_netid
*tt
= opt_malloc(sizeof (struct dhcp_netid
));
1906 tt
->net
= opt_string_alloc(arg
+4);
1907 tt
->next
= new->filter
;
1913 problem
= _("only one tag allowed");
1914 else if (strstr(arg
, "set:") == arg
)
1915 new->netid
.net
= opt_string_alloc(arg
+4);
1917 new->netid
.net
= opt_string_alloc(arg
);
1928 for (k
= 1; k
< 5; k
++)
1929 if (!(a
[k
] = split(a
[k
-1])))
1932 if ((k
< 2) || ((new->start
.s_addr
= inet_addr(a
[0])) == (in_addr_t
)-1))
1934 else if (strcmp(a
[1], "static") == 0)
1936 new->end
= new->start
;
1937 new->flags
|= CONTEXT_STATIC
;
1939 else if (strcmp(a
[1], "proxy") == 0)
1941 new->end
= new->start
;
1942 new->flags
|= CONTEXT_PROXY
;
1944 else if ((new->end
.s_addr
= inet_addr(a
[1])) == (in_addr_t
)-1)
1947 if (ntohl(new->start
.s_addr
) > ntohl(new->end
.s_addr
))
1949 struct in_addr tmp
= new->start
;
1950 new->start
= new->end
;
1954 if (option
!= '?' && k
>= 3 && strchr(a
[2], '.') &&
1955 ((new->netmask
.s_addr
= inet_addr(a
[2])) != (in_addr_t
)-1))
1957 new->flags
|= CONTEXT_NETMASK
;
1959 if (!is_same_net(new->start
, new->end
, new->netmask
))
1960 problem
= _("inconsistent DHCP range");
1964 if (k
>= 4 && strchr(a
[3], '.') &&
1965 ((new->broadcast
.s_addr
= inet_addr(a
[3])) != (in_addr_t
)-1))
1967 new->flags
|= CONTEXT_BRDCAST
;
1971 if (k
>= leasepos
+1)
1973 if (strcmp(a
[leasepos
], "infinite") == 0)
1974 new->lease_time
= 0xffffffff;
1978 if (strlen(a
[leasepos
]) > 0)
1980 switch (a
[leasepos
][strlen(a
[leasepos
]) - 1])
1996 a
[leasepos
][strlen(a
[leasepos
]) - 1] = 0;
1999 new->lease_time
= atoi(a
[leasepos
]) * fac
;
2000 /* Leases of a minute or less confuse
2001 some clients, notably Apple's */
2002 if (new->lease_time
< 120)
2003 new->lease_time
= 120;
2011 case 'G': /* --dhcp-host */
2014 char *a
[6] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
2015 struct dhcp_config
*new;
2018 new = opt_malloc(sizeof(struct dhcp_config
));
2020 new->next
= daemon
->dhcp_conf
;
2021 new->flags
= (option
== LOPT_BANK
) ? CONFIG_BANK
: 0;
2026 for (k
= 1; k
< 6; k
++)
2027 if (!(a
[k
] = split(a
[k
-1])))
2030 for (j
= 0; j
< k
; j
++)
2031 if (strchr(a
[j
], ':')) /* ethernet address, netid or binary CLID */
2035 if ((arg
[0] == 'i' || arg
[0] == 'I') &&
2036 (arg
[1] == 'd' || arg
[1] == 'D') &&
2040 new->flags
|= CONFIG_NOCLID
;
2044 arg
+= 3; /* dump id: */
2045 if (strchr(arg
, ':'))
2046 len
= parse_hex(arg
, (unsigned char *)arg
, -1, NULL
, NULL
);
2050 len
= (int) strlen(arg
);
2054 problem
= _("bad hex constant");
2055 else if ((new->clid
= opt_malloc(len
)))
2057 new->flags
|= CONFIG_CLID
;
2058 new->clid_len
= len
;
2059 memcpy(new->clid
, arg
, len
);
2063 /* dhcp-host has strange backwards-compat needs. */
2064 else if (strstr(arg
, "net:") == arg
|| strstr(arg
, "set:") == arg
)
2066 struct dhcp_netid
*newtag
= opt_malloc(sizeof(struct dhcp_netid
));
2067 struct dhcp_netid_list
*newlist
= opt_malloc(sizeof(struct dhcp_netid_list
));
2068 newtag
->net
= opt_malloc(strlen(arg
+ 4) + 1);
2069 newlist
->next
= new->netid
;
2070 new->netid
= newlist
;
2071 newlist
->list
= newtag
;
2072 strcpy(newtag
->net
, arg
+4);
2073 unhide_metas(newtag
->net
);
2075 else if (strstr(arg
, "tag:") == arg
)
2076 problem
= _("cannot match tags in --dhcp-host");
2079 struct hwaddr_config
*newhw
= opt_malloc(sizeof(struct hwaddr_config
));
2080 if ((newhw
->hwaddr_len
= parse_hex(a
[j
], newhw
->hwaddr
, DHCP_CHADDR_MAX
,
2081 &newhw
->wildcard_mask
, &newhw
->hwaddr_type
)) == -1)
2082 problem
= _("bad hex constant");
2086 newhw
->next
= new->hwaddr
;
2087 new->hwaddr
= newhw
;
2091 else if (strchr(a
[j
], '.') && (in
.s_addr
= inet_addr(a
[j
])) != (in_addr_t
)-1)
2094 new->flags
|= CONFIG_ADDR
;
2098 char *cp
, *lastp
= NULL
, last
= 0;
2101 if (strlen(a
[j
]) > 1)
2103 lastp
= a
[j
] + strlen(a
[j
]) - 1;
2125 for (cp
= a
[j
]; *cp
; cp
++)
2126 if (!isdigit((unsigned char)*cp
) && *cp
!= ' ')
2133 if (strcmp(a
[j
], "infinite") == 0)
2135 new->lease_time
= 0xffffffff;
2136 new->flags
|= CONFIG_TIME
;
2138 else if (strcmp(a
[j
], "ignore") == 0)
2139 new->flags
|= CONFIG_DISABLE
;
2142 if (!(new->hostname
= canonicalise_opt(a
[j
])) ||
2143 !legal_hostname(new->hostname
))
2144 problem
= _("bad DHCP host name");
2146 new->flags
|= CONFIG_NAME
;
2152 new->lease_time
= atoi(a
[j
]) * fac
;
2153 /* Leases of a minute or less confuse
2154 some clients, notably Apple's */
2155 if (new->lease_time
< 120)
2156 new->lease_time
= 120;
2157 new->flags
|= CONFIG_TIME
;
2161 daemon
->dhcp_conf
= new;
2165 case LOPT_TAG_IF
: /* --tag-if */
2167 struct tag_if
*new = opt_malloc(sizeof(struct tag_if
));
2173 /* preserve order */
2174 if (!daemon
->tag_if
)
2175 daemon
->tag_if
= new;
2179 for (tmp
= daemon
->tag_if
; tmp
->next
; tmp
= tmp
->next
);
2197 struct dhcp_netid
*newtag
= opt_malloc(sizeof(struct dhcp_netid
));
2198 newtag
->net
= opt_malloc(len
- 3);
2199 strcpy(newtag
->net
, arg
+4);
2200 unhide_metas(newtag
->net
);
2202 if (strstr(arg
, "set:") == arg
)
2204 struct dhcp_netid_list
*newlist
= opt_malloc(sizeof(struct dhcp_netid_list
));
2205 newlist
->next
= new->set
;
2207 newlist
->list
= newtag
;
2209 else if (strstr(arg
, "tag:") == arg
)
2211 newtag
->next
= new->tag
;
2225 problem
= _("bad tag-if");
2231 case 'O': /* --dhcp-option */
2232 case LOPT_FORCE
: /* --dhcp-option-force */
2234 case LOPT_MATCH
: /* --dhcp-match */
2235 problem
= parse_dhcp_opt(arg
,
2236 option
== LOPT_FORCE
? DHOPT_FORCE
:
2237 (option
== LOPT_MATCH
? DHOPT_MATCH
:
2238 (option
== LOPT_OPTS
? DHOPT_BANK
: 0)));
2241 case 'M': /* --dhcp-boot */
2243 struct dhcp_netid
*id
= NULL
;
2244 while (is_tag_prefix(arg
))
2246 struct dhcp_netid
*newid
= opt_malloc(sizeof(struct dhcp_netid
));
2250 newid
->net
= opt_string_alloc(arg
+4);
2258 char *dhcp_file
, *dhcp_sname
= NULL
, *tftp_sname
= NULL
;
2259 struct in_addr dhcp_next_server
;
2261 dhcp_file
= opt_string_alloc(arg
);
2262 dhcp_next_server
.s_addr
= 0;
2267 dhcp_sname
= opt_string_alloc(arg
);
2270 unhide_metas(comma
);
2271 if ((dhcp_next_server
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1) {
2274 * The user may have specified the tftp hostname here.
2275 * save it so that it can be resolved/looked up during
2276 * actual dhcp_reply().
2279 tftp_sname
= opt_string_alloc(comma
);
2280 dhcp_next_server
.s_addr
= 0;
2286 struct dhcp_boot
*new = opt_malloc(sizeof(struct dhcp_boot
));
2287 new->file
= dhcp_file
;
2288 new->sname
= dhcp_sname
;
2289 new->tftp_sname
= tftp_sname
;
2290 new->next_server
= dhcp_next_server
;
2292 new->next
= daemon
->boot_config
;
2293 daemon
->boot_config
= new;
2300 case LOPT_PXE_PROMT
: /* --pxe-prompt */
2302 struct dhcp_opt
*new = opt_malloc(sizeof(struct dhcp_opt
));
2306 new->opt
= 10; /* PXE_MENU_PROMPT */
2308 while (is_tag_prefix(arg
))
2310 struct dhcp_netid
*nn
= opt_malloc(sizeof (struct dhcp_netid
));
2312 nn
->next
= new->netid
;
2314 nn
->net
= opt_string_alloc(arg
+4);
2324 new->len
= strlen(arg
) + 1;
2325 new->val
= opt_malloc(new->len
);
2326 memcpy(new->val
+ 1, arg
, new->len
- 1);
2328 new->u
.vendor_class
= (unsigned char *)"PXEClient";
2329 new->flags
= DHOPT_VENDOR
;
2331 if (comma
&& atoi_check(comma
, &timeout
))
2332 *(new->val
) = timeout
;
2336 new->next
= daemon
->dhcp_opts
;
2337 daemon
->dhcp_opts
= new;
2338 daemon
->enable_pxe
= 1;
2344 case LOPT_PXE_SERV
: /* --pxe-service */
2346 struct pxe_service
*new = opt_malloc(sizeof(struct pxe_service
));
2347 char *CSA
[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2348 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL
};
2349 static int boottype
= 32768;
2352 new->server
.s_addr
= 0;
2354 while (is_tag_prefix(arg
))
2356 struct dhcp_netid
*nn
= opt_malloc(sizeof (struct dhcp_netid
));
2358 nn
->next
= new->netid
;
2360 nn
->net
= opt_string_alloc(arg
+4);
2364 if (arg
&& (comma
= split(arg
)))
2366 for (i
= 0; CSA
[i
]; i
++)
2367 if (strcasecmp(CSA
[i
], arg
) == 0)
2370 if (CSA
[i
] || atoi_check(arg
, &i
))
2376 new->menu
= opt_string_alloc(arg
);
2380 new->type
= 0; /* local boot */
2381 new->basename
= NULL
;
2387 if (atoi_check(arg
, &i
))
2390 new->basename
= NULL
;
2394 new->type
= boottype
++;
2395 new->basename
= opt_string_alloc(arg
);
2398 if (comma
&& (new->server
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
2404 if (!daemon
->pxe_services
)
2405 daemon
->pxe_services
= new;
2408 struct pxe_service
*s
;
2409 for (s
= daemon
->pxe_services
; s
->next
; s
= s
->next
);
2413 daemon
->enable_pxe
= 1;
2423 case '4': /* --dhcp-mac */
2425 if (!(comma
= split(arg
)))
2429 struct dhcp_mac
*new = opt_malloc(sizeof(struct dhcp_mac
));
2430 new->netid
.net
= opt_string_alloc(set_prefix(arg
));
2431 unhide_metas(comma
);
2432 new->hwaddr_len
= parse_hex(comma
, new->hwaddr
, DHCP_CHADDR_MAX
, &new->mask
, &new->hwaddr_type
);
2433 if (new->hwaddr_len
== -1)
2437 new->next
= daemon
->dhcp_macs
;
2438 daemon
->dhcp_macs
= new;
2444 case 'U': /* --dhcp-vendorclass */
2445 case 'j': /* --dhcp-userclass */
2446 case LOPT_CIRCUIT
: /* --dhcp-circuitid */
2447 case LOPT_REMOTE
: /* --dhcp-remoteid */
2448 case LOPT_SUBSCR
: /* --dhcp-subscrid */
2450 if (!(comma
= split(arg
)))
2456 struct dhcp_vendor
*new = opt_malloc(sizeof(struct dhcp_vendor
));
2457 new->netid
.net
= opt_string_alloc(set_prefix(arg
));
2458 /* check for hex string - must digits may include : must not have nothing else,
2459 only allowed for agent-options. */
2460 for (p
= (unsigned char *)comma
; *p
; p
++)
2465 unhide_metas(comma
);
2466 if (option
== 'U' || option
== 'j' || *p
|| !dig
)
2468 new->len
= strlen(comma
);
2469 new->data
= opt_malloc(new->len
);
2470 memcpy(new->data
, comma
, new->len
);
2474 new->len
= parse_hex(comma
, (unsigned char *)comma
, strlen(comma
), NULL
, NULL
);
2475 new->data
= opt_malloc(new->len
);
2476 memcpy(new->data
, comma
, new->len
);
2482 new->match_type
= MATCH_USER
;
2485 new->match_type
= MATCH_VENDOR
;
2488 new->match_type
= MATCH_CIRCUIT
;
2491 new->match_type
= MATCH_REMOTE
;
2494 new->match_type
= MATCH_SUBSCRIBER
;
2497 new->next
= daemon
->dhcp_vendors
;
2498 daemon
->dhcp_vendors
= new;
2503 case LOPT_ALTPORT
: /* --dhcp-alternate-port */
2506 daemon
->dhcp_server_port
= DHCP_SERVER_ALTPORT
;
2507 daemon
->dhcp_client_port
= DHCP_CLIENT_ALTPORT
;
2512 if (!atoi_check16(arg
, &daemon
->dhcp_server_port
) ||
2513 (comma
&& !atoi_check16(comma
, &daemon
->dhcp_client_port
)))
2514 problem
= _("invalid port number");
2516 daemon
->dhcp_client_port
= daemon
->dhcp_server_port
+1;
2520 case 'J': /* --dhcp-ignore */
2521 case LOPT_NO_NAMES
: /* --dhcp-ignore-names */
2522 case LOPT_BROADCAST
: /* --dhcp-broadcast */
2523 case '3': /* --bootp-dynamic */
2524 case LOPT_GEN_NAMES
: /* --dhcp-generate-names */
2526 struct dhcp_netid_list
*new = opt_malloc(sizeof(struct dhcp_netid_list
));
2527 struct dhcp_netid
*list
= NULL
;
2530 new->next
= daemon
->dhcp_ignore
;
2531 daemon
->dhcp_ignore
= new;
2533 else if (option
== LOPT_BROADCAST
)
2535 new->next
= daemon
->force_broadcast
;
2536 daemon
->force_broadcast
= new;
2538 else if (option
== '3')
2540 new->next
= daemon
->bootp_dynamic
;
2541 daemon
->bootp_dynamic
= new;
2543 else if (option
== LOPT_GEN_NAMES
)
2545 new->next
= daemon
->dhcp_gen_names
;
2546 daemon
->dhcp_gen_names
= new;
2550 new->next
= daemon
->dhcp_ignore_names
;
2551 daemon
->dhcp_ignore_names
= new;
2555 struct dhcp_netid
*member
= opt_malloc(sizeof(struct dhcp_netid
));
2557 member
->next
= list
;
2559 if (is_tag_prefix(arg
))
2560 member
->net
= opt_string_alloc(arg
+4);
2562 member
->net
= opt_string_alloc(arg
);
2570 case LOPT_PROXY
: /* --dhcp-proxy */
2571 daemon
->override
= 1;
2573 struct addr_list
*new = opt_malloc(sizeof(struct addr_list
));
2575 if ((new->addr
.s_addr
= inet_addr(arg
)) == (in_addr_t
)-1)
2576 problem
= _("bad dhcp-proxy address");
2577 new->next
= daemon
->override_relays
;
2578 daemon
->override_relays
= new;
2584 case 'V': /* --alias */
2586 char *dash
, *a
[3] = { NULL
, NULL
, NULL
};
2588 struct doctor
*new = opt_malloc(sizeof(struct doctor
));
2589 new->next
= daemon
->doctors
;
2590 daemon
->doctors
= new;
2591 new->mask
.s_addr
= 0xffffffff;
2592 new->end
.s_addr
= 0;
2595 for (k
= 1; k
< 3; k
++)
2597 if (!(a
[k
] = split(a
[k
-1])))
2602 dash
= split_chr(a
[0], '-');
2605 ((new->in
.s_addr
= inet_addr(a
[0])) == (in_addr_t
)-1) ||
2606 ((new->out
.s_addr
= inet_addr(a
[1])) == (in_addr_t
)-1))
2610 new->mask
.s_addr
= inet_addr(a
[2]);
2613 ((new->end
.s_addr
= inet_addr(dash
)) == (in_addr_t
)-1 ||
2614 !is_same_net(new->in
, new->end
, new->mask
) ||
2615 ntohl(new->in
.s_addr
) > ntohl(new->end
.s_addr
)))
2616 problem
= _("invalid alias range");
2621 case LOPT_INTNAME
: /* --interface-name */
2623 struct interface_name
*new, **up
;
2624 char *domain
= NULL
;
2628 if (!comma
|| !(domain
= canonicalise_opt(arg
)))
2629 problem
= _("bad interface name");
2631 new = opt_malloc(sizeof(struct interface_name
));
2633 /* Add to the end of the list, so that first name
2634 of an interface is used for PTR lookups. */
2635 for (up
= &daemon
->int_names
; *up
; up
= &((*up
)->next
));
2638 new->intr
= opt_string_alloc(comma
);
2642 case LOPT_CNAME
: /* --cname */
2646 if (!(comma
= split(arg
)))
2650 char *alias
= canonicalise_opt(arg
);
2651 char *target
= canonicalise_opt(comma
);
2653 if (!alias
|| !target
)
2654 problem
= _("bad CNAME");
2657 for (new = daemon
->cnames
; new; new = new->next
)
2658 if (hostname_isequal(new->alias
, arg
))
2659 problem
= _("duplicate CNAME");
2660 new = opt_malloc(sizeof(struct cname
));
2661 new->next
= daemon
->cnames
;
2662 daemon
->cnames
= new;
2664 new->target
= target
;
2670 case LOPT_PTR
: /* --ptr-record */
2672 struct ptr_record
*new;
2673 char *dom
, *target
= NULL
;
2677 if (!(dom
= canonicalise_opt(arg
)) ||
2678 (comma
&& !(target
= canonicalise_opt(comma
))))
2679 problem
= _("bad PTR record");
2682 new = opt_malloc(sizeof(struct ptr_record
));
2683 new->next
= daemon
->ptr
;
2691 case LOPT_NAPTR
: /* --naptr-record */
2693 char *a
[7] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
2697 char *name
, *replace
= NULL
;
2700 for (k
= 1; k
< 7; k
++)
2701 if (!(a
[k
] = split(a
[k
-1])))
2706 !(name
= canonicalise_opt(a
[0])) ||
2707 !atoi_check16(a
[1], &order
) ||
2708 !atoi_check16(a
[2], &pref
) ||
2709 (k
== 7 && !(replace
= canonicalise_opt(a
[6]))))
2710 problem
= _("bad NAPTR record");
2713 new = opt_malloc(sizeof(struct naptr
));
2714 new->next
= daemon
->naptr
;
2715 daemon
->naptr
= new;
2717 new->flags
= opt_string_alloc(a
[3]);
2718 new->services
= opt_string_alloc(a
[4]);
2719 new->regexp
= opt_string_alloc(a
[5]);
2720 new->replace
= replace
;
2727 case 'Y': /* --txt-record */
2729 struct txt_record
*new;
2730 unsigned char *p
, *cnt
;
2735 new = opt_malloc(sizeof(struct txt_record
));
2736 new->next
= daemon
->txt
;
2740 if (!(new->name
= canonicalise_opt(arg
)))
2742 problem
= _("bad TXT record");
2746 len
= comma
? strlen(comma
) : 0;
2747 len
+= (len
/255) + 1; /* room for extra counts */
2748 new->txt
= p
= opt_malloc(len
);
2753 while (comma
&& *comma
)
2755 unsigned char c
= (unsigned char)*comma
++;
2757 if (c
== ',' || *cnt
== 255)
2766 *p
++ = unhide_meta(c
);
2771 new->len
= p
- new->txt
;
2776 case 'W': /* --srv-host */
2778 int port
= 1, priority
= 0, weight
= 0;
2779 char *name
, *target
= NULL
;
2780 struct mx_srv_record
*new;
2784 if (!(name
= canonicalise_opt(arg
)))
2785 problem
= _("bad SRV record");
2791 if (!(target
= canonicalise_opt(arg
))
2792 ) problem
= _("bad SRV target");
2798 if (!atoi_check16(arg
, &port
))
2799 problem
= _("invalid port number");
2805 if (!atoi_check16(arg
, &priority
))
2806 problem
= _("invalid priority");
2812 if (!atoi_check16(arg
, &weight
))
2813 problem
= _("invalid weight");
2819 new = opt_malloc(sizeof(struct mx_srv_record
));
2820 new->next
= daemon
->mxnames
;
2821 daemon
->mxnames
= new;
2824 new->target
= target
;
2825 new->srvport
= port
;
2826 new->priority
= priority
;
2827 new->weight
= weight
;
2832 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2845 static void read_file(char *file
, FILE *f
, int hard_opt
)
2847 volatile int lineno
= 0;
2848 char *buff
= daemon
->namebuff
;
2850 while (fgets(buff
, MAXDNAME
, f
))
2852 int white
, i
, option
; ;
2853 char *errmess
, *p
, *arg
, *start
;
2856 /* Memory allocation failure longjmps here if mem_recover == 1 */
2859 if (setjmp(mem_jmp
))
2867 /* Implement quotes, inside quotes we allow \\ \" \n and \t
2868 metacharacters get hidden also strip comments */
2869 for (white
= 1, p
= buff
; *p
; p
++)
2873 memmove(p
, p
+1, strlen(p
+1)+1);
2875 for(; *p
&& *p
!= '"'; p
++)
2877 if (*p
== '\\' && strchr("\"tnebr\\", p
[1]))
2881 else if (p
[1] == 'n')
2883 else if (p
[1] == 'b')
2885 else if (p
[1] == 'r')
2887 else if (p
[1] == 'e') /* escape */
2889 memmove(p
, p
+1, strlen(p
+1)+1);
2896 errmess
= _("missing \"");
2900 memmove(p
, p
+1, strlen(p
+1)+1);
2910 if (white
&& *p
== '#')
2920 /* strip leading spaces */
2921 for (start
= buff
; *start
&& *start
== ' '; start
++);
2923 /* strip trailing spaces */
2924 for (len
= strlen(start
); (len
!= 0) && (start
[len
-1] == ' '); len
--);
2933 else if ((p
=strchr(start
, '=')))
2935 /* allow spaces around "=" */
2936 for (arg
= p
+1; *arg
== ' '; arg
++);
2937 for (; p
>= start
&& (*p
== ' ' || *p
== '='); p
--)
2947 for (option
= 0, i
= 0; opts
[i
].name
; i
++)
2948 if (strcmp(opts
[i
].name
, start
) == 0)
2950 option
= opts
[i
].val
;
2955 errmess
= _("bad option");
2956 else if (opts
[i
].has_arg
== 0 && arg
)
2957 errmess
= _("extraneous parameter");
2958 else if (opts
[i
].has_arg
== 1 && !arg
)
2959 errmess
= _("missing parameter");
2963 errmess
= one_opt(option
, arg
, _("error"), 0);
2968 sprintf(buff
, _("%s at line %d of %%s"), errmess
, lineno
);
2970 my_syslog(LOG_ERR
, buff
, file
);
2972 die(buff
, file
, EC_BADCONF
);
2980 static void one_file(char *file
, int hard_opt
)
2984 static int read_stdin
= 0;
2985 static struct fileread
{
2988 struct fileread
*next
;
2989 } *filesread
= NULL
;
2991 if (hard_opt
== '7')
2993 /* default conf-file reading */
2998 if (hard_opt
== 0 && strcmp(file
, "-") == 0)
3000 if (read_stdin
== 1)
3008 /* ignore repeated files. */
3009 struct stat statbuf
;
3011 if (hard_opt
== 0 && stat(file
, &statbuf
) == 0)
3015 for (r
= filesread
; r
; r
= r
->next
)
3016 if (r
->dev
== statbuf
.st_dev
&& r
->ino
== statbuf
.st_ino
)
3019 r
= safe_malloc(sizeof(struct fileread
));
3020 r
->next
= filesread
;
3022 r
->dev
= statbuf
.st_dev
;
3023 r
->ino
= statbuf
.st_ino
;
3026 if (!(f
= fopen(file
, "r")))
3028 if (errno
== ENOENT
&& nofile_ok
)
3029 return; /* No conffile, all done. */
3032 char *str
= _("cannot read %s: %s");
3035 my_syslog(LOG_ERR
, str
, file
, strerror(errno
));
3039 die(str
, file
, EC_FILE
);
3044 read_file(file
, f
, hard_opt
);
3047 /* expand any name which is a directory */
3048 struct hostsfile
*expand_filelist(struct hostsfile
*list
)
3051 struct hostsfile
*ah
;
3053 for (i
= 0, ah
= list
; ah
; ah
= ah
->next
)
3058 if (ah
->flags
& AH_DIR
)
3059 ah
->flags
|= AH_INACTIVE
;
3061 ah
->flags
&= ~AH_INACTIVE
;
3064 for (ah
= list
; ah
; ah
= ah
->next
)
3065 if (!(ah
->flags
& AH_INACTIVE
))
3068 if (stat(ah
->fname
, &buf
) != -1 && S_ISDIR(buf
.st_mode
))
3073 /* don't read this as a file */
3074 ah
->flags
|= AH_INACTIVE
;
3076 if (!(dir_stream
= opendir(ah
->fname
)))
3077 my_syslog(LOG_ERR
, _("cannot access directory %s: %s"),
3078 ah
->fname
, strerror(errno
));
3081 while ((ent
= readdir(dir_stream
)))
3083 size_t lendir
= strlen(ah
->fname
);
3084 size_t lenfile
= strlen(ent
->d_name
);
3085 struct hostsfile
*ah1
;
3088 /* ignore emacs backups and dotfiles */
3090 ent
->d_name
[lenfile
- 1] == '~' ||
3091 (ent
->d_name
[0] == '#' && ent
->d_name
[lenfile
- 1] == '#') ||
3092 ent
->d_name
[0] == '.')
3095 /* see if we have an existing record.
3098 path to match is ah1->fname */
3100 for (ah1
= list
; ah1
; ah1
= ah1
->next
)
3102 if (lendir
< strlen(ah1
->fname
) &&
3103 strstr(ah1
->fname
, ah
->fname
) == ah1
->fname
&&
3104 ah1
->fname
[lendir
] == '/' &&
3105 strcmp(ah1
->fname
+ lendir
+ 1, ent
->d_name
) == 0)
3107 ah1
->flags
&= ~AH_INACTIVE
;
3112 /* make new record */
3115 if (!(ah1
= whine_malloc(sizeof(struct hostsfile
))))
3118 if (!(path
= whine_malloc(lendir
+ lenfile
+ 2)))
3124 strcpy(path
, ah
->fname
);
3126 strcat(path
, ent
->d_name
);
3129 ah1
->flags
= AH_DIR
;
3134 /* inactivate record if not regular file */
3135 if ((ah1
->flags
& AH_DIR
) && stat(ah1
->fname
, &buf
) != -1 && !S_ISREG(buf
.st_mode
))
3136 ah1
->flags
|= AH_INACTIVE
;
3139 closedir(dir_stream
);
3149 void reread_dhcp(void)
3151 struct hostsfile
*hf
;
3153 if (daemon
->dhcp_hosts_file
)
3155 struct dhcp_config
*configs
, *cp
, **up
;
3157 /* remove existing... */
3158 for (up
= &daemon
->dhcp_conf
, configs
= daemon
->dhcp_conf
; configs
; configs
= cp
)
3162 if (configs
->flags
& CONFIG_BANK
)
3164 struct hwaddr_config
*mac
, *tmp
;
3165 struct dhcp_netid_list
*list
, *tmplist
;
3167 for (mac
= configs
->hwaddr
; mac
; mac
= tmp
)
3173 if (configs
->flags
& CONFIG_CLID
)
3174 free(configs
->clid
);
3176 for (list
= configs
->netid
; list
; list
= tmplist
)
3179 tmplist
= list
->next
;
3183 if (configs
->flags
& CONFIG_NAME
)
3184 free(configs
->hostname
);
3186 *up
= configs
->next
;
3190 up
= &configs
->next
;
3193 daemon
->dhcp_hosts_file
= expand_filelist(daemon
->dhcp_hosts_file
);
3194 for (hf
= daemon
->dhcp_hosts_file
; hf
; hf
= hf
->next
)
3195 if (!(hf
->flags
& AH_INACTIVE
))
3197 one_file(hf
->fname
, LOPT_BANK
);
3198 my_syslog(MS_DHCP
| LOG_INFO
, _("read %s"), hf
->fname
);
3202 if (daemon
->dhcp_opts_file
)
3204 struct dhcp_opt
*opts
, *cp
, **up
;
3205 struct dhcp_netid
*id
, *next
;
3207 for (up
= &daemon
->dhcp_opts
, opts
= daemon
->dhcp_opts
; opts
; opts
= cp
)
3211 if (opts
->flags
& DHOPT_BANK
)
3213 if ((opts
->flags
& DHOPT_VENDOR
))
3214 free(opts
->u
.vendor_class
);
3216 for (id
= opts
->netid
; id
; id
= next
)
3229 daemon
->dhcp_opts_file
= expand_filelist(daemon
->dhcp_opts_file
);
3230 for (hf
= daemon
->dhcp_opts_file
; hf
; hf
= hf
->next
)
3231 if (!(hf
->flags
& AH_INACTIVE
))
3233 one_file(hf
->fname
, LOPT_OPTS
);
3234 my_syslog(MS_DHCP
| LOG_INFO
, _("read %s"), hf
->fname
);
3240 void read_opts(int argc
, char **argv
, char *compile_opts
)
3242 char *buff
= opt_malloc(MAXDNAME
);
3243 int option
, conffile_opt
= '7', testmode
= 0;
3244 char *errmess
, *arg
, *conffile
= CONFFILE
;
3248 daemon
= opt_malloc(sizeof(struct daemon
));
3249 memset(daemon
, 0, sizeof(struct daemon
));
3250 daemon
->namebuff
= buff
;
3252 /* Set defaults - everything else is zero or NULL */
3253 daemon
->cachesize
= CACHESIZ
;
3254 daemon
->ftabsize
= FTABSIZ
;
3255 daemon
->port
= NAMESERVER_PORT
;
3256 daemon
->dhcp_client_port
= DHCP_CLIENT_PORT
;
3257 daemon
->dhcp_server_port
= DHCP_SERVER_PORT
;
3258 daemon
->default_resolv
.is_default
= 1;
3259 daemon
->default_resolv
.name
= RESOLVFILE
;
3260 daemon
->resolv_files
= &daemon
->default_resolv
;
3261 daemon
->username
= CHUSER
;
3262 daemon
->runfile
= RUNFILE
;
3263 daemon
->dhcp_max
= MAXLEASES
;
3264 daemon
->tftp_max
= TFTP_MAX_CONNECTIONS
;
3265 daemon
->edns_pktsz
= EDNS_PKTSZ
;
3266 daemon
->log_fac
= -1;
3267 add_txt("version.bind", "dnsmasq-" VERSION
);
3268 add_txt("authors.bind", "Simon Kelley");
3269 add_txt("copyright.bind", COPYRIGHT
);
3273 #ifdef HAVE_GETOPT_LONG
3274 option
= getopt_long(argc
, argv
, OPTSTRING
, opts
, NULL
);
3276 option
= getopt(argc
, argv
, OPTSTRING
);
3281 for (; optind
< argc
; optind
++)
3283 unsigned char *c
= (unsigned char *)argv
[optind
];
3284 for (; *c
!= 0; c
++)
3286 die(_("junk found in command line"), NULL
, EC_BADCONF
);
3291 /* Copy optarg so that argv doesn't get changed */
3294 strncpy(buff
, optarg
, MAXDNAME
);
3295 buff
[MAXDNAME
-1] = 0;
3301 /* command-line only stuff */
3302 if (option
== LOPT_TEST
)
3304 else if (option
== 'w')
3306 if (argc
!= 3 || strcmp(argv
[2], "dhcp") != 0)
3314 else if (option
== 'v')
3316 printf(_("Dnsmasq version %s %s\n"), VERSION
, COPYRIGHT
);
3317 printf(_("Compile time options: %s\n\n"), compile_opts
);
3318 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
3319 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
3320 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
3323 else if (option
== 'C')
3325 conffile_opt
= 0; /* file must exist */
3326 conffile
= opt_string_alloc(arg
);
3330 #ifdef HAVE_GETOPT_LONG
3331 errmess
= one_opt(option
, arg
, _("try --help"), 1);
3333 errmess
= one_opt(option
, arg
, _("try -w"), 1);
3336 die(_("bad command line options: %s"), errmess
, EC_BADCONF
);
3341 one_file(conffile
, conffile_opt
);
3343 /* port might not be known when the address is parsed - fill in here */
3344 if (daemon
->servers
)
3347 for (tmp
= daemon
->servers
; tmp
; tmp
= tmp
->next
)
3348 if (!(tmp
->flags
& SERV_HAS_SOURCE
))
3350 if (tmp
->source_addr
.sa
.sa_family
== AF_INET
)
3351 tmp
->source_addr
.in
.sin_port
= htons(daemon
->query_port
);
3353 else if (tmp
->source_addr
.sa
.sa_family
== AF_INET6
)
3354 tmp
->source_addr
.in6
.sin6_port
= htons(daemon
->query_port
);
3359 if (daemon
->if_addrs
)
3362 for(tmp
= daemon
->if_addrs
; tmp
; tmp
= tmp
->next
)
3363 if (tmp
->addr
.sa
.sa_family
== AF_INET
)
3364 tmp
->addr
.in
.sin_port
= htons(daemon
->port
);
3366 else if (tmp
->addr
.sa
.sa_family
== AF_INET6
)
3367 tmp
->addr
.in6
.sin6_port
= htons(daemon
->port
);
3371 /* only one of these need be specified: the other defaults to the host-name */
3372 if (option_bool(OPT_LOCALMX
) || daemon
->mxnames
|| daemon
->mxtarget
)
3374 struct mx_srv_record
*mx
;
3376 if (gethostname(buff
, MAXDNAME
) == -1)
3377 die(_("cannot get host-name: %s"), NULL
, EC_MISC
);
3379 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
3380 if (!mx
->issrv
&& hostname_isequal(mx
->name
, buff
))
3383 if ((daemon
->mxtarget
|| option_bool(OPT_LOCALMX
)) && !mx
)
3385 mx
= opt_malloc(sizeof(struct mx_srv_record
));
3386 mx
->next
= daemon
->mxnames
;
3389 mx
->name
= opt_string_alloc(buff
);
3390 daemon
->mxnames
= mx
;
3393 if (!daemon
->mxtarget
)
3394 daemon
->mxtarget
= opt_string_alloc(buff
);
3396 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
3397 if (!mx
->issrv
&& !mx
->target
)
3398 mx
->target
= daemon
->mxtarget
;
3401 if (!option_bool(OPT_NO_RESOLV
) &&
3402 daemon
->resolv_files
&&
3403 daemon
->resolv_files
->next
&&
3404 option_bool(OPT_NO_POLL
))
3405 die(_("only one resolv.conf file allowed in no-poll mode."), NULL
, EC_BADCONF
);
3407 if (option_bool(OPT_RESOLV_DOMAIN
))
3412 if (option_bool(OPT_NO_RESOLV
) ||
3413 !daemon
->resolv_files
||
3414 (daemon
->resolv_files
)->next
)
3415 die(_("must have exactly one resolv.conf to read domain from."), NULL
, EC_BADCONF
);
3417 if (!(f
= fopen((daemon
->resolv_files
)->name
, "r")))
3418 die(_("failed to read %s: %s"), (daemon
->resolv_files
)->name
, EC_FILE
);
3420 while ((line
= fgets(buff
, MAXDNAME
, f
)))
3422 char *token
= strtok(line
, " \t\n\r");
3424 if (!token
|| strcmp(token
, "search") != 0)
3427 if ((token
= strtok(NULL
, " \t\n\r")) &&
3428 (daemon
->domain_suffix
= canonicalise_opt(token
)))
3434 if (!daemon
->domain_suffix
)
3435 die(_("no search directive found in %s"), (daemon
->resolv_files
)->name
, EC_MISC
);
3438 if (daemon
->domain_suffix
)
3440 /* add domain for any srv record without one. */
3441 struct mx_srv_record
*srv
;
3443 for (srv
= daemon
->mxnames
; srv
; srv
= srv
->next
)
3445 strchr(srv
->name
, '.') &&
3446 strchr(srv
->name
, '.') == strrchr(srv
->name
, '.'))
3448 strcpy(buff
, srv
->name
);
3450 strcat(buff
, daemon
->domain_suffix
);
3452 srv
->name
= opt_string_alloc(buff
);
3455 else if (option_bool(OPT_DHCP_FQDN
))
3456 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL
, EC_BADCONF
);
3460 fprintf(stderr
, "dnsmasq: %s.\n", _("syntax check OK"));