1 /* dnsmasq is Copyright (c) 2000-2009 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 nest
, 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
106 #ifdef HAVE_GETOPT_LONG
107 static const struct option opts
[] =
109 static const struct myoption opts
[] =
112 { "version", 0, 0, 'v' },
113 { "no-hosts", 0, 0, 'h' },
114 { "no-poll", 0, 0, 'n' },
115 { "help", 0, 0, 'w' },
116 { "no-daemon", 0, 0, 'd' },
117 { "log-queries", 0, 0, 'q' },
118 { "user", 2, 0, 'u' },
119 { "group", 2, 0, 'g' },
120 { "resolv-file", 2, 0, 'r' },
121 { "mx-host", 1, 0, 'm' },
122 { "mx-target", 1, 0, 't' },
123 { "cache-size", 2, 0, 'c' },
124 { "port", 1, 0, 'p' },
125 { "dhcp-leasefile", 2, 0, 'l' },
126 { "dhcp-lease", 1, 0, 'l' },
127 { "dhcp-host", 1, 0, 'G' },
128 { "dhcp-range", 1, 0, 'F' },
129 { "dhcp-option", 1, 0, 'O' },
130 { "dhcp-boot", 1, 0, 'M' },
131 { "domain", 1, 0, 's' },
132 { "domain-suffix", 1, 0, 's' },
133 { "interface", 1, 0, 'i' },
134 { "listen-address", 1, 0, 'a' },
135 { "bogus-priv", 0, 0, 'b' },
136 { "bogus-nxdomain", 1, 0, 'B' },
137 { "selfmx", 0, 0, 'e' },
138 { "filterwin2k", 0, 0, 'f' },
139 { "pid-file", 2, 0, 'x' },
140 { "strict-order", 0, 0, 'o' },
141 { "server", 1, 0, 'S' },
142 { "local", 1, 0, LOPT_LOCAL
},
143 { "address", 1, 0, 'A' },
144 { "conf-file", 2, 0, 'C' },
145 { "no-resolv", 0, 0, 'R' },
146 { "expand-hosts", 0, 0, 'E' },
147 { "localmx", 0, 0, 'L' },
148 { "local-ttl", 1, 0, 'T' },
149 { "no-negcache", 0, 0, 'N' },
150 { "addn-hosts", 1, 0, 'H' },
151 { "query-port", 1, 0, 'Q' },
152 { "except-interface", 1, 0, 'I' },
153 { "no-dhcp-interface", 1, 0, '2' },
154 { "domain-needed", 0, 0, 'D' },
155 { "dhcp-lease-max", 1, 0, 'X' },
156 { "bind-interfaces", 0, 0, 'z' },
157 { "read-ethers", 0, 0, 'Z' },
158 { "alias", 1, 0, 'V' },
159 { "dhcp-vendorclass", 1, 0, 'U' },
160 { "dhcp-userclass", 1, 0, 'j' },
161 { "dhcp-ignore", 1, 0, 'J' },
162 { "edns-packet-max", 1, 0, 'P' },
163 { "keep-in-foreground", 0, 0, 'k' },
164 { "dhcp-authoritative", 0, 0, 'K' },
165 { "srv-host", 1, 0, 'W' },
166 { "localise-queries", 0, 0, 'y' },
167 { "txt-record", 1, 0, 'Y' },
168 { "enable-dbus", 0, 0, '1' },
169 { "bootp-dynamic", 2, 0, '3' },
170 { "dhcp-mac", 1, 0, '4' },
171 { "no-ping", 0, 0, '5' },
172 { "dhcp-script", 1, 0, '6' },
173 { "conf-dir", 1, 0, '7' },
174 { "log-facility", 1, 0 ,'8' },
175 { "leasefile-ro", 0, 0, '9' },
176 { "dns-forward-max", 1, 0, '0' },
177 { "clear-on-reload", 0, 0, LOPT_RELOAD
},
178 { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES
},
179 { "enable-tftp", 0, 0, LOPT_TFTP
},
180 { "tftp-secure", 0, 0, LOPT_SECURE
},
181 { "tftp-unique-root", 0, 0, LOPT_APREF
},
182 { "tftp-root", 1, 0, LOPT_PREFIX
},
183 { "tftp-max", 1, 0, LOPT_TFTP_MAX
},
184 { "ptr-record", 1, 0, LOPT_PTR
},
185 { "naptr-record", 1, 0, LOPT_NAPTR
},
186 { "bridge-interface", 1, 0 , LOPT_BRIDGE
},
187 { "dhcp-option-force", 1, 0, LOPT_FORCE
},
188 { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK
},
189 { "log-dhcp", 0, 0, LOPT_LOG_OPTS
},
190 { "log-async", 2, 0, LOPT_MAX_LOGS
},
191 { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT
},
192 { "dhcp-remoteid", 1, 0, LOPT_REMOTE
},
193 { "dhcp-subscrid", 1, 0, LOPT_SUBSCR
},
194 { "interface-name", 1, 0, LOPT_INTNAME
},
195 { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST
},
196 { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS
},
197 { "dhcp-no-override", 0, 0, LOPT_OVERRIDE
},
198 { "tftp-port-range", 1, 0, LOPT_TFTPPORTS
},
199 { "stop-dns-rebind", 0, 0, LOPT_REBIND
},
200 { "all-servers", 0, 0, LOPT_NOLAST
},
201 { "dhcp-match", 1, 0, LOPT_MATCH
},
202 { "dhcp-broadcast", 1, 0, LOPT_BROADCAST
},
203 { "neg-ttl", 1, 0, LOPT_NEGTTL
},
204 { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT
},
205 { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR
},
206 { "min-port", 1, 0, LOPT_MINPORT
},
207 { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN
},
208 { "cname", 1, 0, LOPT_CNAME
},
209 { "pxe-prompt", 1, 0, LOPT_PXE_PROMT
},
210 { "pxe-service", 1, 0, LOPT_PXE_SERV
},
211 { "test", 0, 0, LOPT_TEST
},
215 /* These must have more the one '1' bit */
218 #define ARG_USED_CL 7
219 #define ARG_USED_FILE 9
224 char * const flagdesc
;
228 { 'a', ARG_DUP
, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL
},
229 { 'A', ARG_DUP
, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL
},
230 { 'b', OPT_BOGUSPRIV
, NULL
, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL
},
231 { 'B', ARG_DUP
, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL
},
232 { 'c', ARG_ONE
, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
233 { 'C', ARG_DUP
, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE
},
234 { 'd', OPT_DEBUG
, NULL
, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL
},
235 { 'D', OPT_NODOTS_LOCAL
, NULL
, gettext_noop("Do NOT forward queries with no domain part."), NULL
},
236 { 'e', OPT_SELFMX
, NULL
, gettext_noop("Return self-pointing MX records for local hosts."), NULL
},
237 { 'E', OPT_EXPAND
, NULL
, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL
},
238 { 'f', OPT_FILTER
, NULL
, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL
},
239 { 'F', ARG_DUP
, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL
},
240 { 'g', ARG_ONE
, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP
},
241 { 'G', ARG_DUP
, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL
},
242 { LOPT_DHCP_HOST
, ARG_ONE
, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL
},
243 { LOPT_DHCP_OPTS
, ARG_ONE
, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL
},
244 { 'h', OPT_NO_HOSTS
, NULL
, gettext_noop("Do NOT load %s file."), HOSTSFILE
},
245 { 'H', ARG_DUP
, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE
},
246 { 'i', ARG_DUP
, "interface", gettext_noop("Specify interface(s) to listen on."), NULL
},
247 { 'I', ARG_DUP
, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL
},
248 { 'j', ARG_DUP
, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL
},
249 { LOPT_CIRCUIT
, ARG_DUP
, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL
},
250 { LOPT_REMOTE
, ARG_DUP
, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL
},
251 { LOPT_SUBSCR
, ARG_DUP
, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL
},
252 { 'J', ARG_DUP
, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL
},
253 { LOPT_BROADCAST
, ARG_DUP
, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL
},
254 { 'k', OPT_NO_FORK
, NULL
, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL
},
255 { 'K', OPT_AUTHORITATIVE
, NULL
, gettext_noop("Assume we are the only DHCP server on the local network."), NULL
},
256 { 'l', ARG_ONE
, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE
},
257 { 'L', OPT_LOCALMX
, NULL
, gettext_noop("Return MX records for local hosts."), NULL
},
258 { 'm', ARG_DUP
, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL
},
259 { 'M', ARG_DUP
, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL
},
260 { 'n', OPT_NO_POLL
, NULL
, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE
},
261 { 'N', OPT_NO_NEG
, NULL
, gettext_noop("Do NOT cache failed search results."), NULL
},
262 { 'o', OPT_ORDER
, NULL
, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE
},
263 { 'O', ARG_DUP
, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL
},
264 { LOPT_FORCE
, ARG_DUP
, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL
},
265 { 'p', ARG_ONE
, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL
},
266 { 'P', ARG_ONE
, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
267 { 'q', OPT_LOG
, NULL
, gettext_noop("Log DNS queries."), NULL
},
268 { 'Q', ARG_ONE
, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL
},
269 { 'R', OPT_NO_RESOLV
, NULL
, gettext_noop("Do NOT read resolv.conf."), NULL
},
270 { 'r', ARG_DUP
, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE
},
271 { 'S', ARG_DUP
, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL
},
272 { LOPT_LOCAL
, ARG_DUP
, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL
},
273 { 's', ARG_DUP
, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL
},
274 { 't', ARG_ONE
, "host_name", gettext_noop("Specify default target in an MX record."), NULL
},
275 { 'T', ARG_ONE
, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL
},
276 { LOPT_NEGTTL
, ARG_ONE
, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL
},
277 { 'u', ARG_ONE
, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER
},
278 { 'U', ARG_DUP
, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL
},
279 { 'v', 0, NULL
, gettext_noop("Display dnsmasq version and copyright information."), NULL
},
280 { 'V', ARG_DUP
, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL
},
281 { 'W', ARG_DUP
, "name,target,...", gettext_noop("Specify a SRV record."), NULL
},
282 { 'w', 0, NULL
, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL
},
283 { 'x', ARG_ONE
, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE
},
284 { 'X', ARG_ONE
, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
285 { 'y', OPT_LOCALISE
, NULL
, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL
},
286 { 'Y', ARG_DUP
, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL
},
287 { LOPT_PTR
, ARG_DUP
, "name,target", gettext_noop("Specify PTR DNS record."), NULL
},
288 { LOPT_INTNAME
, ARG_DUP
, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL
},
289 { 'z', OPT_NOWILD
, NULL
, gettext_noop("Bind only to interfaces in use."), NULL
},
290 { 'Z', OPT_ETHERS
, NULL
, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE
},
291 { '1', OPT_DBUS
, NULL
, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL
},
292 { '2', ARG_DUP
, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL
},
293 { '3', ARG_DUP
, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL
},
294 { '4', ARG_DUP
, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL
},
295 { LOPT_BRIDGE
, ARG_DUP
, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL
},
296 { '5', OPT_NO_PING
, NULL
, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL
},
297 { '6', ARG_ONE
, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL
},
298 { '7', ARG_DUP
, "path", gettext_noop("Read configuration from all the files in this directory."), NULL
},
299 { '8', ARG_ONE
, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL
},
300 { '9', OPT_LEASE_RO
, NULL
, gettext_noop("Do not use leasefile."), NULL
},
301 { '0', ARG_ONE
, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
302 { LOPT_RELOAD
, OPT_RELOAD
, NULL
, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE
},
303 { LOPT_NO_NAMES
, ARG_DUP
, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL
},
304 { LOPT_OVERRIDE
, OPT_NO_OVERRIDE
, NULL
, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL
},
305 { LOPT_TFTP
, OPT_TFTP
, NULL
, gettext_noop("Enable integrated read-only TFTP server."), NULL
},
306 { LOPT_PREFIX
, ARG_ONE
, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL
},
307 { LOPT_APREF
, OPT_TFTP_APREF
, NULL
, gettext_noop("Add client IP address to tftp-root."), NULL
},
308 { LOPT_SECURE
, OPT_TFTP_SECURE
, NULL
, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL
},
309 { LOPT_TFTP_MAX
, ARG_ONE
, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
310 { LOPT_NOBLOCK
, OPT_TFTP_NOBLOCK
, NULL
, gettext_noop("Disable the TFTP blocksize extension."), NULL
},
311 { LOPT_TFTPPORTS
, ARG_ONE
, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL
},
312 { LOPT_LOG_OPTS
, OPT_LOG_OPTS
, NULL
, gettext_noop("Extra logging for DHCP."), NULL
},
313 { LOPT_MAX_LOGS
, ARG_ONE
, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL
},
314 { LOPT_REBIND
, OPT_NO_REBIND
, NULL
, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL
},
315 { LOPT_NOLAST
, OPT_ALL_SERVERS
, NULL
, gettext_noop("Always perform DNS queries to all servers."), NULL
},
316 { LOPT_MATCH
, ARG_DUP
, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL
},
317 { LOPT_ALTPORT
, ARG_ONE
, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL
},
318 { LOPT_SCRIPTUSR
, ARG_ONE
, "<username>", gettext_noop("Run lease-change script as this user."), NULL
},
319 { LOPT_NAPTR
, ARG_DUP
, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL
},
320 { LOPT_MINPORT
, ARG_ONE
, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL
},
321 { LOPT_DHCP_FQDN
, OPT_DHCP_FQDN
, NULL
, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL
},
322 { LOPT_CNAME
, ARG_DUP
, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL
},
323 { LOPT_PXE_PROMT
, ARG_DUP
, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL
},
324 { LOPT_PXE_SERV
, ARG_DUP
, "<service>", gettext_noop("Boot service for PXE menu."), NULL
},
325 { LOPT_TEST
, 0, NULL
, gettext_noop("Check configuration syntax."), NULL
},
326 { 0, 0, NULL
, NULL
, NULL
}
330 /* makes options which take a list of addresses */
331 #define OT_ADDR_LIST 0x80
332 /* DHCP-internal options, for logging. not valid in config file */
333 #define OT_INTERNAL 0x40
336 static const struct {
338 unsigned char val
, size
;
340 { "netmask", 1, OT_ADDR_LIST
},
341 { "time-offset", 2, 4 },
342 { "router", 3, OT_ADDR_LIST
},
343 { "dns-server", 6, OT_ADDR_LIST
},
344 { "log-server", 7, OT_ADDR_LIST
},
345 { "lpr-server", 9, OT_ADDR_LIST
},
346 { "hostname", 12, OT_INTERNAL
| OT_NAME
},
347 { "boot-file-size", 13, 2 },
348 { "domain-name", 15, OT_NAME
},
349 { "swap-server", 16, OT_ADDR_LIST
},
350 { "root-path", 17, 0 },
351 { "extension-path", 18, 0 },
352 { "ip-forward-enable", 19, 1 },
353 { "non-local-source-routing", 20, 1 },
354 { "policy-filter", 21, OT_ADDR_LIST
},
355 { "max-datagram-reassembly", 22, 2 },
356 { "default-ttl", 23, 1 },
358 { "all-subnets-local", 27, 1 },
359 { "broadcast", 28, OT_INTERNAL
| OT_ADDR_LIST
},
360 { "router-discovery", 31, 1 },
361 { "router-solicitation", 32, OT_ADDR_LIST
},
362 { "static-route", 33, OT_ADDR_LIST
},
363 { "trailer-encapsulation", 34, 1 },
364 { "arp-timeout", 35, 4 },
365 { "ethernet-encap", 36, 1 },
366 { "tcp-ttl", 37, 1 },
367 { "tcp-keepalive", 38, 4 },
368 { "nis-domain", 40, 0 },
369 { "nis-server", 41, OT_ADDR_LIST
},
370 { "ntp-server", 42, OT_ADDR_LIST
},
371 { "vendor-encap", 43, OT_INTERNAL
},
372 { "netbios-ns", 44, OT_ADDR_LIST
},
373 { "netbios-dd", 45, OT_ADDR_LIST
},
374 { "netbios-nodetype", 46, 1 },
375 { "netbios-scope", 47, 0 },
376 { "x-windows-fs", 48, OT_ADDR_LIST
},
377 { "x-windows-dm", 49, OT_ADDR_LIST
},
378 { "requested-address", 50, OT_INTERNAL
| OT_ADDR_LIST
},
379 { "lease-time", 51, OT_INTERNAL
},
380 { "option-overload", 52, OT_INTERNAL
},
381 { "message-type", 53, OT_INTERNAL
, },
382 { "server-identifier", 54, OT_INTERNAL
| OT_ADDR_LIST
},
383 { "parameter-request", 55, OT_INTERNAL
},
384 { "message", 56, OT_INTERNAL
},
385 { "max-message-size", 57, OT_INTERNAL
},
386 { "T1", 58, OT_INTERNAL
},
387 { "T2", 59, OT_INTERNAL
},
388 { "vendor-class", 60, 0 },
389 { "client-id", 61,OT_INTERNAL
},
390 { "nis+-domain", 64, 0 },
391 { "nis+-server", 65, OT_ADDR_LIST
},
392 { "tftp-server", 66, 0 },
393 { "bootfile-name", 67, 0 },
394 { "mobile-ip-home", 68, OT_ADDR_LIST
},
395 { "smtp-server", 69, OT_ADDR_LIST
},
396 { "pop3-server", 70, OT_ADDR_LIST
},
397 { "nntp-server", 71, OT_ADDR_LIST
},
398 { "irc-server", 74, OT_ADDR_LIST
},
399 { "user-class", 77, 0 },
400 { "FQDN", 81, OT_INTERNAL
},
401 { "agent-id", 82, OT_INTERNAL
},
402 { "client-arch", 93, 2 },
403 { "client-interface-id", 94, 0 },
404 { "client-machine-id", 97, 0 },
405 { "subnet-select", 118, OT_INTERNAL
},
406 { "domain-search", 119, 0 },
407 { "sip-server", 120, 0 },
408 { "classless-static-route", 121, 0 },
409 { "server-ip-address", 255, OT_ADDR_LIST
}, /* special, internal only, sets siaddr */
413 char *option_string(unsigned char opt
, int *is_ip
, int *is_name
)
417 for (i
= 0; opttab
[i
].name
; i
++)
418 if (opttab
[i
].val
== opt
)
421 *is_ip
= !!(opttab
[i
].size
& OT_ADDR_LIST
);
423 *is_name
= !!(opttab
[i
].size
& OT_NAME
);
424 return opttab
[i
].name
;
432 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
433 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
434 following sequence so that they map to themselves: it is therefore possible to call
435 unhide_metas repeatedly on string without breaking things.
436 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
437 couple of other places.
438 Note that space is included here so that
439 --dhcp-option=3, string
440 has five characters, whilst
441 --dhcp-option=3," string"
445 static const char meta
[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
447 static char hide_meta(char c
)
451 for (i
= 0; i
< (sizeof(meta
) - 1); i
++)
458 static char unhide_meta(char cr
)
462 if (c
< (sizeof(meta
) - 1))
468 static void unhide_metas(char *cp
)
472 *cp
= unhide_meta(*cp
);
475 static void *opt_malloc(size_t size
)
481 ret
= whine_malloc(size
);
486 ret
= safe_malloc(size
);
491 static char *opt_string_alloc(char *cp
)
495 if (cp
&& strlen(cp
) != 0)
497 ret
= opt_malloc(strlen(cp
)+1);
500 /* restore hidden metachars */
508 /* find next comma, split string with zero and eliminate spaces.
509 return start of string following comma */
511 static char *split_chr(char *s
, char c
)
515 if (!s
|| !(comma
= strchr(s
, c
)))
521 for (; isspace((int)*comma
); comma
++);
523 for (; (p
>= s
) && isspace((int)*p
); p
--)
529 static char *split(char *s
)
531 return split_chr(s
, ',');
534 static char *canonicalise_opt(char *s
)
543 if (!(ret
= canonicalise(s
, &nomem
)) && nomem
)
548 die(_("could not get memory"), NULL
, EC_NOMEM
);
554 static int atoi_check(char *a
, int *res
)
564 if (*p
< '0' || *p
> '9')
571 static int atoi_check16(char *a
, int *res
)
573 if (!(atoi_check(a
, res
)) ||
581 static void add_txt(char *name
, char *txt
)
583 size_t len
= strlen(txt
);
584 struct txt_record
*r
= opt_malloc(sizeof(struct txt_record
));
586 r
->name
= opt_string_alloc(name
);
587 r
->next
= daemon
->txt
;
590 r
->txt
= opt_malloc(len
+1);
593 memcpy((r
->txt
)+1, txt
, len
);
596 static void do_usage(void)
609 { '#', TFTP_MAX_CONNECTIONS
},
613 printf(_("Usage: dnsmasq [options]\n\n"));
614 #ifndef HAVE_GETOPT_LONG
615 printf(_("Use short options only on the command line.\n"));
617 printf(_("Valid options are:\n"));
619 for (i
= 0; usage
[i
].opt
!= 0; i
++)
621 char *desc
= usage
[i
].flagdesc
;
624 if (!desc
|| *desc
== '[')
630 for ( j
= 0; opts
[j
].name
; j
++)
631 if (opts
[j
].val
== usage
[i
].opt
)
633 if (usage
[i
].opt
< 256)
634 sprintf(buff
, "-%c, ", usage
[i
].opt
);
638 sprintf(buff
+4, "--%s%s%s", opts
[j
].name
, eq
, desc
);
639 printf("%-36.36s", buff
);
643 strcpy(buff
, usage
[i
].arg
);
644 for (j
= 0; tab
[j
].handle
; j
++)
645 if (tab
[j
].handle
== *(usage
[i
].arg
))
646 sprintf(buff
, "%d", tab
[j
].val
);
648 printf(_(usage
[i
].desc
), buff
);
654 static void display_opts(void)
658 printf(_("Known DHCP options:\n"));
660 for (i
= 0; opttab
[i
].name
; i
++)
661 if (!(opttab
[i
].size
& OT_INTERNAL
))
662 printf("%3d %s\n", opttab
[i
].val
, opttab
[i
].name
);
665 /* This is too insanely large to keep in-line in the switch */
666 static char *parse_dhcp_opt(char *arg
, int flags
)
668 struct dhcp_opt
*new = opt_malloc(sizeof(struct dhcp_opt
));
669 char lenchar
= 0, *cp
;
670 int i
, addrs
, digs
, is_addr
, is_hex
, is_dec
, is_string
, dots
;
671 char *comma
= NULL
, *problem
= NULL
;
672 struct dhcp_netid
*np
= NULL
;
673 unsigned char opt_len
= 0;
685 for (cp
= arg
; *cp
; cp
++)
686 if (*cp
< '0' || *cp
> '9')
691 new->opt
= atoi(arg
);
696 if (strstr(arg
, "option:") == arg
)
698 for (i
= 0; opttab
[i
].name
; i
++)
699 if (!(opttab
[i
].size
& OT_INTERNAL
) &&
700 strcasecmp(opttab
[i
].name
, arg
+7) == 0)
702 new->opt
= opttab
[i
].val
;
703 opt_len
= opttab
[i
].size
;
706 /* option:<optname> must follow tag and vendor string. */
709 else if (strstr(arg
, "vendor:") == arg
)
711 new->u
.vendor_class
= (unsigned char *)opt_string_alloc(arg
+7);
712 new->flags
|= DHOPT_VENDOR
;
714 else if (strstr(arg
, "encap:") == arg
)
716 new->u
.encap
= atoi(arg
+6);
717 new->flags
|= DHOPT_ENCAPSULATE
;
721 new->netid
= opt_malloc(sizeof (struct dhcp_netid
));
722 /* allow optional "net:" for consistency */
723 if (strstr(arg
, "net:") == arg
)
724 new->netid
->net
= opt_string_alloc(arg
+4);
726 new->netid
->net
= opt_string_alloc(arg
);
727 new->netid
->next
= np
;
735 problem
= _("bad dhcp-option");
738 /* characterise the value */
740 is_addr
= is_hex
= is_dec
= is_string
= 1;
743 for (cp
= comma
; (c
= *cp
); cp
++)
752 is_dec
= is_addr
= 0;
757 if (cp
== comma
) /* leading / means a pathname */
766 is_hex
= is_addr
= 0;
769 else if (!(c
>='0' && c
<= '9'))
772 if (cp
[1] == 0 && is_dec
&&
773 (c
== 'b' || c
== 's' || c
== 'i'))
780 if (!((c
>='A' && c
<= 'F') ||
781 (c
>='a' && c
<= 'f') ||
782 (c
== '*' && (flags
& DHOPT_MATCH
))))
786 /* We know that some options take addresses */
788 if (opt_len
& OT_ADDR_LIST
)
790 is_string
= is_dec
= is_hex
= 0;
791 if (!is_addr
|| dots
== 0)
792 problem
= _("bad IP address");
795 if (is_hex
&& digs
> 1)
798 new->val
= opt_malloc(new->len
);
799 parse_hex(comma
, new->val
, digs
, (flags
& DHOPT_MATCH
) ? &new->u
.wildcard_mask
: NULL
, NULL
);
800 new->flags
|= DHOPT_HEX
;
804 int i
, val
= atoi(comma
);
805 /* assume numeric arg is 1 byte except for
806 options where it is known otherwise.
807 For vendor class option, we have to hack. */
810 else if (val
& 0xffff0000)
812 else if (val
& 0xff00)
819 else if (lenchar
== 's')
821 else if (lenchar
== 'i')
824 new->val
= opt_malloc(new->len
);
825 for (i
=0; i
<new->len
; i
++)
826 new->val
[i
] = val
>>((new->len
- i
- 1)*8);
833 /* max length of address/subnet descriptor is five bytes,
834 add one for the option 120 enc byte too */
835 new->val
= op
= opt_malloc((5 * addrs
) + 1);
836 new->flags
|= DHOPT_ADDR
;
838 if (!(new->flags
& DHOPT_ENCAPSULATE
) && new->opt
== 120)
840 *(op
++) = 1; /* RFC 3361 "enc byte" */
841 new->flags
&= ~DHOPT_ADDR
;
847 slash
= split_chr(cp
, '/');
848 in
.s_addr
= inet_addr(cp
);
851 memcpy(op
, &in
, INADDRSZ
);
856 unsigned char *p
= (unsigned char *)&in
;
857 int netsize
= atoi(slash
);
867 new->flags
&= ~DHOPT_ADDR
; /* cannot re-write descriptor format */
870 new->len
= op
- new->val
;
875 if ((new->opt
== 119 || new->opt
== 120) && !(new->flags
& DHOPT_ENCAPSULATE
))
877 /* dns search, RFC 3397, or SIP, RFC 3361 */
878 unsigned char *q
, *r
, *tail
;
879 unsigned char *p
, *m
= NULL
, *newp
;
880 size_t newlen
, len
= 0;
881 int header_size
= (new->opt
== 119) ? 0 : 1;
889 if (!(dom
= arg
= canonicalise_opt(arg
)))
891 problem
= _("bad domain in dhcp-option");
895 newp
= opt_malloc(len
+ strlen(arg
) + 2 + header_size
);
897 memcpy(newp
, m
, header_size
+ len
);
902 /* add string on the end in RFC1035 format */
905 unsigned char *cp
= q
++;
907 for (j
= 0; *arg
&& (*arg
!= '.'); arg
++, j
++)
916 /* Now tail-compress using earlier names. */
918 for (tail
= p
+ len
; *tail
; tail
+= (*tail
) + 1)
919 for (r
= p
; r
- p
< (int)len
; r
+= (*r
) + 1)
920 if (strcmp((char *)r
, (char *)tail
) == 0)
922 PUTSHORT((r
- p
) | 0xc000, tail
);
933 /* RFC 3361, enc byte is zero for names */
936 new->len
= (int) len
+ header_size
;
941 new->len
= strlen(comma
);
942 /* keep terminating zero on string */
943 new->val
= (unsigned char *)opt_string_alloc(comma
);
944 new->flags
|= DHOPT_STRING
;
949 if ((new->len
> 255) || (new->len
> 253 && (new->flags
& (DHOPT_VENDOR
| DHOPT_ENCAPSULATE
))))
950 problem
= _("dhcp-option too long");
954 if (flags
== DHOPT_MATCH
)
956 if ((new->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
)) ||
959 problem
= _("illegal dhcp-match");
962 new->next
= daemon
->dhcp_match
;
963 daemon
->dhcp_match
= new;
968 new->next
= daemon
->dhcp_opts
;
969 daemon
->dhcp_opts
= new;
978 static char *one_opt(int option
, char *arg
, char *gen_prob
, int nest
)
981 char *comma
, *problem
= NULL
;;
986 for (i
=0; usage
[i
].opt
!= 0; i
++)
987 if (usage
[i
].opt
== option
)
989 int rept
= usage
[i
].rept
;
994 if (rept
== ARG_USED_CL
)
995 return _("illegal repeated flag");
997 usage
[i
].rept
= ARG_USED_CL
;
1001 /* allow file to override command line */
1002 if (rept
== ARG_USED_FILE
)
1003 return _("illegal repeated keyword");
1004 if (rept
== ARG_USED_CL
|| rept
== ARG_ONE
)
1005 usage
[i
].rept
= ARG_USED_FILE
;
1008 if (rept
!= ARG_DUP
&& rept
!= ARG_ONE
&& rept
!= ARG_USED_CL
)
1010 daemon
->options
|= rept
;
1019 case 'C': /* --conf-file */
1021 char *file
= opt_string_alloc(arg
);
1024 one_file(file
, nest
, 0);
1030 case '7': /* --conf-dir */
1034 char *directory
, *path
;
1038 } *ignore_suffix
= NULL
, *li
;
1041 if (!(directory
= opt_string_alloc(arg
)))
1044 for (arg
= comma
; arg
; arg
= comma
)
1047 li
= opt_malloc(sizeof(struct list
));
1048 li
->next
= ignore_suffix
;
1050 /* Have to copy: buffer is overwritten */
1051 li
->suffix
= opt_string_alloc(arg
);
1054 if (!(dir_stream
= opendir(directory
)))
1055 die(_("cannot access directory %s: %s"), directory
, EC_FILE
);
1057 while ((ent
= readdir(dir_stream
)))
1059 size_t len
= strlen(ent
->d_name
);
1062 /* ignore emacs backups and dotfiles */
1064 ent
->d_name
[len
- 1] == '~' ||
1065 (ent
->d_name
[0] == '#' && ent
->d_name
[len
- 1] == '#') ||
1066 ent
->d_name
[0] == '.')
1069 for (li
= ignore_suffix
; li
; li
= li
->next
)
1071 /* check for proscribed suffices */
1072 size_t ls
= strlen(li
->suffix
);
1074 strcmp(li
->suffix
, &ent
->d_name
[len
- ls
]) == 0)
1080 path
= opt_malloc(strlen(directory
) + len
+ 2);
1081 strcpy(path
, directory
);
1083 strcat(path
, ent
->d_name
);
1085 if (stat(path
, &buf
) == -1)
1086 die(_("cannot access %s: %s"), path
, EC_FILE
);
1087 /* only reg files allowed. */
1088 if (!S_ISREG(buf
.st_mode
))
1091 /* dir is one level, so files must be readable */
1092 one_file(path
, nest
+ 1, 0);
1096 closedir(dir_stream
);
1098 for(; ignore_suffix
; ignore_suffix
= li
)
1100 li
= ignore_suffix
->next
;
1101 free(ignore_suffix
->suffix
);
1102 free(ignore_suffix
);
1108 case '8': /* --log-facility */
1109 /* may be a filename */
1110 if (strchr(arg
, '/'))
1111 daemon
->log_file
= opt_string_alloc(arg
);
1114 for (i
= 0; facilitynames
[i
].c_name
; i
++)
1115 if (hostname_isequal((char *)facilitynames
[i
].c_name
, arg
))
1118 if (facilitynames
[i
].c_name
)
1119 daemon
->log_fac
= facilitynames
[i
].c_val
;
1121 problem
= "bad log facility";
1125 case 'x': /* --pid-file */
1126 daemon
->runfile
= opt_string_alloc(arg
);
1129 case LOPT_DHCP_HOST
: /* --dhcp-hostfile */
1130 if (daemon
->dhcp_hosts_file
)
1131 problem
= _("only one dhcp-hostsfile allowed");
1133 daemon
->dhcp_hosts_file
= opt_string_alloc(arg
);
1136 case LOPT_DHCP_OPTS
: /* --dhcp-optsfile */
1137 if (daemon
->dhcp_opts_file
)
1138 problem
= _("only one dhcp-optsfile allowed");
1140 daemon
->dhcp_opts_file
= opt_string_alloc(arg
);
1143 case 'r': /* --resolv-file */
1145 char *name
= opt_string_alloc(arg
);
1146 struct resolvc
*new, *list
= daemon
->resolv_files
;
1148 if (list
&& list
->is_default
)
1150 /* replace default resolv file - possibly with nothing */
1153 list
->is_default
= 0;
1161 new = opt_malloc(sizeof(struct resolvc
));
1164 new->is_default
= 0;
1169 daemon
->resolv_files
= list
;
1173 case 'm': /* --mx-host */
1176 struct mx_srv_record
*new;
1177 char *name
, *target
= NULL
;
1179 if ((comma
= split(arg
)))
1182 if ((prefstr
= split(comma
)) && !atoi_check16(prefstr
, &pref
))
1183 problem
= _("bad MX preference");
1186 if (!(name
= canonicalise_opt(arg
)) ||
1187 (comma
&& !(target
= canonicalise_opt(comma
))))
1188 problem
= _("bad MX name");
1190 new = opt_malloc(sizeof(struct mx_srv_record
));
1191 new->next
= daemon
->mxnames
;
1192 daemon
->mxnames
= new;
1195 new->target
= target
; /* may be NULL */
1200 case 't': /* --mx-target */
1201 if (!(daemon
->mxtarget
= canonicalise_opt(arg
)))
1202 problem
= _("bad MX target");
1206 case 'l': /* --dhcp-leasefile */
1207 daemon
->lease_file
= opt_string_alloc(arg
);
1210 case '6': /* --dhcp-script */
1211 # if defined(NO_FORK)
1212 problem
= _("cannot run scripts under uClinux");
1213 # elif !defined(HAVE_SCRIPT)
1214 problem
= _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
1216 daemon
->lease_change_command
= opt_string_alloc(arg
);
1221 case 'H': /* --addn-hosts */
1223 struct hostsfile
*new = opt_malloc(sizeof(struct hostsfile
));
1224 static int hosts_index
= 1;
1225 new->fname
= opt_string_alloc(arg
);
1226 new->index
= hosts_index
++;
1228 new->next
= daemon
->addn_hosts
;
1229 daemon
->addn_hosts
= new;
1233 case 's': /* --domain */
1234 if (strcmp (arg
, "#") == 0)
1235 daemon
->options
|= OPT_RESOLV_DOMAIN
;
1240 if (!(d
= canonicalise_opt(arg
)))
1246 struct cond_domain
*new = safe_malloc(sizeof(struct cond_domain
));
1247 unhide_metas(comma
);
1248 if ((arg
= split_chr(comma
, '/')))
1251 if ((new->start
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1 ||
1252 !atoi_check(arg
, &mask
))
1256 mask
= (1 << (32 - mask
)) - 1;
1257 new->start
.s_addr
= ntohl(htonl(new->start
.s_addr
) & ~mask
);
1258 new->end
.s_addr
= new->start
.s_addr
| htonl(mask
);
1261 else if ((arg
= split(comma
)))
1263 if ((new->start
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1 ||
1264 (new->end
.s_addr
= inet_addr(arg
)) == (in_addr_t
)-1)
1267 else if ((new->start
.s_addr
= new->end
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
1271 new->next
= daemon
->cond_domain
;
1272 daemon
->cond_domain
= new;
1275 daemon
->domain_suffix
= d
;
1280 case 'u': /* --user */
1281 daemon
->username
= opt_string_alloc(arg
);
1284 case 'g': /* --group */
1285 daemon
->groupname
= opt_string_alloc(arg
);
1286 daemon
->group_set
= 1;
1290 case LOPT_SCRIPTUSR
: /* --scriptuser */
1291 daemon
->scriptuser
= opt_string_alloc(arg
);
1295 case 'i': /* --interface */
1297 struct iname
*new = opt_malloc(sizeof(struct iname
));
1299 new->next
= daemon
->if_names
;
1300 daemon
->if_names
= new;
1301 /* new->name may be NULL if someone does
1302 "interface=" to disable all interfaces except loop. */
1303 new->name
= opt_string_alloc(arg
);
1304 new->isloop
= new->used
= 0;
1309 case 'I': /* --except-interface */
1310 case '2': /* --no-dhcp-interface */
1312 struct iname
*new = opt_malloc(sizeof(struct iname
));
1314 new->name
= opt_string_alloc(arg
);
1317 new->next
= daemon
->if_except
;
1318 daemon
->if_except
= new;
1322 new->next
= daemon
->dhcp_except
;
1323 daemon
->dhcp_except
= new;
1329 case 'B': /* --bogus-nxdomain */
1331 struct in_addr addr
;
1333 if (arg
&& (addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
)-1)
1335 struct bogus_addr
*baddr
= opt_malloc(sizeof(struct bogus_addr
));
1336 baddr
->next
= daemon
->bogus_addr
;
1337 daemon
->bogus_addr
= baddr
;
1341 option
= '?'; /* error */
1345 case 'a': /* --listen-address */
1347 struct iname
*new = opt_malloc(sizeof(struct iname
));
1350 new->next
= daemon
->if_addrs
;
1351 if (arg
&& (new->addr
.in
.sin_addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
)-1)
1353 new->addr
.sa
.sa_family
= AF_INET
;
1354 #ifdef HAVE_SOCKADDR_SA_LEN
1355 new->addr
.in
.sin_len
= sizeof(new->addr
.in
);
1359 else if (arg
&& inet_pton(AF_INET6
, arg
, &new->addr
.in6
.sin6_addr
) > 0)
1361 new->addr
.sa
.sa_family
= AF_INET6
;
1362 new->addr
.in6
.sin6_flowinfo
= 0;
1363 new->addr
.in6
.sin6_scope_id
= 0;
1364 #ifdef HAVE_SOCKADDR_SA_LEN
1365 new->addr
.in6
.sin6_len
= sizeof(new->addr
.in6
);
1371 option
= '?'; /* error */
1375 daemon
->if_addrs
= new;
1380 case 'S': /* --server */
1381 case LOPT_LOCAL
: /* --local */
1382 case 'A': /* --address */
1384 struct server
*serv
, *newlist
= NULL
;
1388 if (arg
&& *arg
== '/')
1392 while ((end
= split_chr(arg
, '/')))
1394 char *domain
= NULL
;
1395 /* # matches everything and becomes a zero length domain string */
1396 if (strcmp(arg
, "#") == 0)
1398 else if (strlen (arg
) != 0 && !(domain
= canonicalise_opt(arg
)))
1400 serv
= opt_malloc(sizeof(struct server
));
1401 memset(serv
, 0, sizeof(struct server
));
1402 serv
->next
= newlist
;
1404 serv
->domain
= domain
;
1405 serv
->flags
= domain
? SERV_HAS_DOMAIN
: SERV_FOR_NODOTS
;
1417 newlist
= opt_malloc(sizeof(struct server
));
1418 memset(newlist
, 0, sizeof(struct server
));
1423 newlist
->flags
|= SERV_LITERAL_ADDRESS
;
1424 if (!(newlist
->flags
& SERV_TYPE
))
1430 newlist
->flags
|= SERV_NO_ADDR
; /* no server */
1431 if (newlist
->flags
& SERV_LITERAL_ADDRESS
)
1436 int source_port
= 0, serv_port
= NAMESERVER_PORT
;
1437 char *portno
, *source
;
1439 if ((source
= split_chr(arg
, '@')) && /* is there a source. */
1440 (portno
= split_chr(source
, '#')) &&
1441 !atoi_check16(portno
, &source_port
))
1442 problem
= _("bad port");
1444 if ((portno
= split_chr(arg
, '#')) && /* is there a port no. */
1445 !atoi_check16(portno
, &serv_port
))
1446 problem
= _("bad port");
1448 if ((newlist
->addr
.in
.sin_addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
) -1)
1450 newlist
->addr
.in
.sin_port
= htons(serv_port
);
1451 newlist
->source_addr
.in
.sin_port
= htons(source_port
);
1452 newlist
->addr
.sa
.sa_family
= newlist
->source_addr
.sa
.sa_family
= AF_INET
;
1453 #ifdef HAVE_SOCKADDR_SA_LEN
1454 newlist
->source_addr
.in
.sin_len
= newlist
->addr
.in
.sin_len
= sizeof(struct sockaddr_in
);
1458 newlist
->flags
|= SERV_HAS_SOURCE
;
1459 if ((newlist
->source_addr
.in
.sin_addr
.s_addr
= inet_addr(source
)) == (in_addr_t
) -1)
1461 #if defined(SO_BINDTODEVICE)
1462 newlist
->source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
1463 strncpy(newlist
->interface
, source
, IF_NAMESIZE
);
1465 problem
= _("interface binding not supported");
1470 newlist
->source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
1473 else if (inet_pton(AF_INET6
, arg
, &newlist
->addr
.in6
.sin6_addr
) > 0)
1475 newlist
->addr
.in6
.sin6_port
= htons(serv_port
);
1476 newlist
->source_addr
.in6
.sin6_port
= htons(source_port
);
1477 newlist
->addr
.sa
.sa_family
= newlist
->source_addr
.sa
.sa_family
= AF_INET6
;
1478 #ifdef HAVE_SOCKADDR_SA_LEN
1479 newlist
->addr
.in6
.sin6_len
= newlist
->source_addr
.in6
.sin6_len
= sizeof(newlist
->addr
.in6
);
1483 newlist
->flags
|= SERV_HAS_SOURCE
;
1484 if (inet_pton(AF_INET6
, source
, &newlist
->source_addr
.in6
.sin6_addr
) == 0)
1486 #if defined(SO_BINDTODEVICE)
1487 newlist
->source_addr
.in6
.sin6_addr
= in6addr_any
;
1488 strncpy(newlist
->interface
, source
, IF_NAMESIZE
);
1490 problem
= _("interface binding not supported");
1495 newlist
->source_addr
.in6
.sin6_addr
= in6addr_any
;
1499 option
= '?'; /* error */
1506 serv
->next
->flags
= serv
->flags
;
1507 serv
->next
->addr
= serv
->addr
;
1508 serv
->next
->source_addr
= serv
->source_addr
;
1511 serv
->next
= daemon
->servers
;
1512 daemon
->servers
= newlist
;
1516 case 'c': /* --cache-size */
1520 if (!atoi_check(arg
, &size
))
1524 /* zero is OK, and means no caching. */
1528 else if (size
> 10000)
1531 daemon
->cachesize
= size
;
1536 case 'p': /* --port */
1537 if (!atoi_check16(arg
, &daemon
->port
))
1541 case LOPT_MINPORT
: /* --min-port */
1542 if (!atoi_check16(arg
, &daemon
->min_port
))
1546 case '0': /* --dns-forward-max */
1547 if (!atoi_check(arg
, &daemon
->ftabsize
))
1551 case LOPT_MAX_LOGS
: /* --log-async */
1552 daemon
->max_logs
= LOG_MAX
; /* default */
1553 if (arg
&& !atoi_check(arg
, &daemon
->max_logs
))
1555 else if (daemon
->max_logs
> 100)
1556 daemon
->max_logs
= 100;
1559 case 'P': /* --edns-packet-max */
1562 if (!atoi_check(arg
, &i
))
1564 daemon
->edns_pktsz
= (unsigned short)i
;
1568 case 'Q': /* --query-port */
1569 if (!atoi_check16(arg
, &daemon
->query_port
))
1571 /* if explicitly set to zero, use single OS ephemeral port
1572 and disable random ports */
1573 if (daemon
->query_port
== 0)
1577 case 'T': /* --local-ttl */
1578 case LOPT_NEGTTL
: /* --neg-ttl */
1581 if (!atoi_check(arg
, &ttl
))
1583 else if (option
== LOPT_NEGTTL
)
1584 daemon
->neg_ttl
= (unsigned long)ttl
;
1586 daemon
->local_ttl
= (unsigned long)ttl
;
1591 case 'X': /* --dhcp-lease-max */
1592 if (!atoi_check(arg
, &daemon
->dhcp_max
))
1598 case LOPT_TFTP_MAX
: /* --tftp-max */
1599 if (!atoi_check(arg
, &daemon
->tftp_max
))
1603 case LOPT_PREFIX
: /* --tftp-prefix */
1604 daemon
->tftp_prefix
= opt_string_alloc(arg
);
1607 case LOPT_TFTPPORTS
: /* --tftp-port-range */
1608 if (!(comma
= split(arg
)) ||
1609 !atoi_check16(arg
, &daemon
->start_tftp_port
) ||
1610 !atoi_check16(comma
, &daemon
->end_tftp_port
))
1611 problem
= _("bad port range");
1613 if (daemon
->start_tftp_port
> daemon
->end_tftp_port
)
1615 int tmp
= daemon
->start_tftp_port
;
1616 daemon
->start_tftp_port
= daemon
->end_tftp_port
;
1617 daemon
->end_tftp_port
= tmp
;
1623 case LOPT_BRIDGE
: /* --bridge-interface */
1625 struct dhcp_bridge
*new = opt_malloc(sizeof(struct dhcp_bridge
));
1626 if (!(comma
= split(arg
)))
1628 problem
= _("bad bridge-interface");
1632 strncpy(new->iface
, arg
, IF_NAMESIZE
);
1634 new->next
= daemon
->bridges
;
1635 daemon
->bridges
= new;
1640 if (strlen(arg
) != 0)
1642 struct dhcp_bridge
*b
= opt_malloc(sizeof(struct dhcp_bridge
));
1643 b
->next
= new->alias
;
1645 strncpy(b
->iface
, arg
, IF_NAMESIZE
);
1653 case 'F': /* --dhcp-range */
1655 int k
, leasepos
= 2;
1656 char *cp
, *a
[5] = { NULL
, NULL
, NULL
, NULL
, NULL
};
1657 struct dhcp_context
*new = opt_malloc(sizeof(struct dhcp_context
));
1659 new->next
= daemon
->dhcp
;
1660 new->lease_time
= DEFLEASE
;
1661 new->addr_epoch
= 0;
1662 new->netmask
.s_addr
= 0;
1663 new->broadcast
.s_addr
= 0;
1664 new->router
.s_addr
= 0;
1665 new->netid
.net
= NULL
;
1669 gen_prob
= _("bad dhcp-range");
1679 for (cp
= arg
; *cp
; cp
++)
1680 if (!(*cp
== ' ' || *cp
== '.' || (*cp
>='0' && *cp
<= '9')))
1683 if (*cp
!= ',' && (comma
= split(arg
)))
1685 if (strstr(arg
, "net:") == arg
)
1687 struct dhcp_netid
*tt
= opt_malloc(sizeof (struct dhcp_netid
));
1688 tt
->net
= opt_string_alloc(arg
+4);
1689 tt
->next
= new->filter
;
1695 problem
= _("only one netid tag allowed");
1697 new->netid
.net
= opt_string_alloc(arg
);
1708 for (k
= 1; k
< 5; k
++)
1709 if (!(a
[k
] = split(a
[k
-1])))
1712 if ((k
< 2) || ((new->start
.s_addr
= inet_addr(a
[0])) == (in_addr_t
)-1))
1714 else if (strcmp(a
[1], "static") == 0)
1716 new->end
= new->start
;
1717 new->flags
|= CONTEXT_STATIC
;
1719 else if (strcmp(a
[1], "proxy") == 0)
1721 new->end
= new->start
;
1722 new->flags
|= CONTEXT_PROXY
;
1724 else if ((new->end
.s_addr
= inet_addr(a
[1])) == (in_addr_t
)-1)
1727 if (ntohl(new->start
.s_addr
) > ntohl(new->end
.s_addr
))
1729 struct in_addr tmp
= new->start
;
1730 new->start
= new->end
;
1734 if (option
!= '?' && k
>= 3 && strchr(a
[2], '.') &&
1735 ((new->netmask
.s_addr
= inet_addr(a
[2])) != (in_addr_t
)-1))
1737 new->flags
|= CONTEXT_NETMASK
;
1739 if (!is_same_net(new->start
, new->end
, new->netmask
))
1740 problem
= _("inconsistent DHCP range");
1744 if (k
>= 4 && strchr(a
[3], '.') &&
1745 ((new->broadcast
.s_addr
= inet_addr(a
[3])) != (in_addr_t
)-1))
1747 new->flags
|= CONTEXT_BRDCAST
;
1751 if (k
>= leasepos
+1)
1753 if (strcmp(a
[leasepos
], "infinite") == 0)
1754 new->lease_time
= 0xffffffff;
1758 if (strlen(a
[leasepos
]) > 0)
1760 switch (a
[leasepos
][strlen(a
[leasepos
]) - 1])
1776 a
[leasepos
][strlen(a
[leasepos
]) - 1] = 0;
1779 new->lease_time
= atoi(a
[leasepos
]) * fac
;
1780 /* Leases of a minute or less confuse
1781 some clients, notably Apple's */
1782 if (new->lease_time
< 120)
1783 new->lease_time
= 120;
1791 case 'G': /* --dhcp-host */
1794 char *a
[6] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
1795 struct dhcp_config
*new;
1798 new = opt_malloc(sizeof(struct dhcp_config
));
1800 new->next
= daemon
->dhcp_conf
;
1801 new->flags
= (option
== LOPT_BANK
) ? CONFIG_BANK
: 0;
1805 for (k
= 1; k
< 6; k
++)
1806 if (!(a
[k
] = split(a
[k
-1])))
1809 for (j
= 0; j
< k
; j
++)
1810 if (strchr(a
[j
], ':')) /* ethernet address, netid or binary CLID */
1814 if ((arg
[0] == 'i' || arg
[0] == 'I') &&
1815 (arg
[1] == 'd' || arg
[1] == 'D') &&
1819 new->flags
|= CONFIG_NOCLID
;
1823 arg
+= 3; /* dump id: */
1824 if (strchr(arg
, ':'))
1825 len
= parse_hex(arg
, (unsigned char *)arg
, -1, NULL
, NULL
);
1829 len
= (int) strlen(arg
);
1832 if ((new->clid
= opt_malloc(len
)))
1834 new->flags
|= CONFIG_CLID
;
1835 new->clid_len
= len
;
1836 memcpy(new->clid
, arg
, len
);
1840 else if (strstr(arg
, "net:") == arg
)
1842 int len
= strlen(arg
+ 4) + 1;
1843 if ((new->netid
.net
= opt_malloc(len
)))
1845 new->flags
|= CONFIG_NETID
;
1846 strcpy(new->netid
.net
, arg
+4);
1847 unhide_metas(new->netid
.net
);
1852 struct hwaddr_config
*newhw
= opt_malloc(sizeof(struct hwaddr_config
));
1853 newhw
->next
= new->hwaddr
;
1854 new->hwaddr
= newhw
;
1855 newhw
->hwaddr_len
= parse_hex(a
[j
], newhw
->hwaddr
, DHCP_CHADDR_MAX
,
1856 &newhw
->wildcard_mask
, &newhw
->hwaddr_type
);
1859 else if (strchr(a
[j
], '.') && (in
.s_addr
= inet_addr(a
[j
])) != (in_addr_t
)-1)
1862 new->flags
|= CONFIG_ADDR
;
1866 char *cp
, *lastp
= NULL
, last
= 0;
1869 if (strlen(a
[j
]) > 1)
1871 lastp
= a
[j
] + strlen(a
[j
]) - 1;
1893 for (cp
= a
[j
]; *cp
; cp
++)
1894 if (!isdigit((int)*cp
) && *cp
!= ' ')
1901 if (strcmp(a
[j
], "infinite") == 0)
1903 new->lease_time
= 0xffffffff;
1904 new->flags
|= CONFIG_TIME
;
1906 else if (strcmp(a
[j
], "ignore") == 0)
1907 new->flags
|= CONFIG_DISABLE
;
1910 if (!(new->hostname
= canonicalise_opt(a
[j
])) ||
1911 !legal_hostname(new->hostname
))
1912 problem
= _("bad DHCP host name");
1914 new->flags
|= CONFIG_NAME
;
1920 new->lease_time
= atoi(a
[j
]) * fac
;
1921 /* Leases of a minute or less confuse
1922 some clients, notably Apple's */
1923 if (new->lease_time
< 120)
1924 new->lease_time
= 120;
1925 new->flags
|= CONFIG_TIME
;
1929 daemon
->dhcp_conf
= new;
1933 case 'O': /* --dhcp-option */
1934 case LOPT_FORCE
: /* --dhcp-option-force */
1936 case LOPT_MATCH
: /* --dhcp-match */
1937 problem
= parse_dhcp_opt(arg
,
1938 option
== LOPT_FORCE
? DHOPT_FORCE
:
1939 (option
== LOPT_MATCH
? DHOPT_MATCH
:
1940 (option
== LOPT_OPTS
? DHOPT_BANK
: 0)));
1943 case 'M': /* --dhcp-boot */
1945 struct dhcp_netid
*id
= NULL
;
1946 while (arg
&& strstr(arg
, "net:") == arg
)
1948 struct dhcp_netid
*newid
= opt_malloc(sizeof(struct dhcp_netid
));
1952 newid
->net
= opt_string_alloc(arg
+4);
1960 char *dhcp_file
, *dhcp_sname
= NULL
;
1961 struct in_addr dhcp_next_server
;
1963 dhcp_file
= opt_string_alloc(arg
);
1964 dhcp_next_server
.s_addr
= 0;
1969 dhcp_sname
= opt_string_alloc(arg
);
1972 unhide_metas(comma
);
1973 if ((dhcp_next_server
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
1979 struct dhcp_boot
*new = opt_malloc(sizeof(struct dhcp_boot
));
1980 new->file
= dhcp_file
;
1981 new->sname
= dhcp_sname
;
1982 new->next_server
= dhcp_next_server
;
1984 new->next
= daemon
->boot_config
;
1985 daemon
->boot_config
= new;
1992 case LOPT_PXE_PROMT
: /* --pxe-prompt */
1994 struct dhcp_opt
*new = opt_malloc(sizeof(struct dhcp_opt
));
1998 new->opt
= 10; /* PXE_MENU_PROMPT */
2000 while (arg
&& strstr(arg
, "net:") == arg
)
2002 struct dhcp_netid
*nn
= opt_malloc(sizeof (struct dhcp_netid
));
2004 nn
->next
= new->netid
;
2006 nn
->net
= opt_string_alloc(arg
+4);
2016 new->len
= strlen(arg
) + 1;
2017 new->val
= opt_malloc(new->len
);
2018 memcpy(new->val
+ 1, arg
, new->len
- 1);
2020 new->u
.vendor_class
= (unsigned char *)"PXEClient";
2021 new->flags
= DHOPT_VENDOR
;
2023 if (comma
&& atoi_check(comma
, &timeout
))
2024 *(new->val
) = timeout
;
2028 new->next
= daemon
->dhcp_opts
;
2029 daemon
->dhcp_opts
= new;
2030 daemon
->enable_pxe
= 1;
2036 case LOPT_PXE_SERV
: /* --pxe-service */
2038 struct pxe_service
*new = opt_malloc(sizeof(struct pxe_service
));
2039 char *CSA
[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
2040 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL
};
2041 static int boottype
= 32768;
2044 new->server
.s_addr
= 0;
2046 while (arg
&& strstr(arg
, "net:") == arg
)
2048 struct dhcp_netid
*nn
= opt_malloc(sizeof (struct dhcp_netid
));
2050 nn
->next
= new->netid
;
2052 nn
->net
= opt_string_alloc(arg
+4);
2056 if (arg
&& (comma
= split(arg
)))
2058 for (i
= 0; CSA
[i
]; i
++)
2059 if (strcasecmp(CSA
[i
], arg
) == 0)
2062 if (CSA
[i
] || atoi_check(arg
, &i
))
2068 new->menu
= opt_string_alloc(arg
);
2074 if (atoi_check(arg
, &i
))
2077 new->basename
= NULL
;
2081 new->type
= boottype
++;
2082 new->basename
= opt_string_alloc(arg
);
2085 if (comma
&& (new->server
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
2090 if (!daemon
->pxe_services
)
2091 daemon
->pxe_services
= new;
2094 struct pxe_service
*s
;
2095 for (s
= daemon
->pxe_services
; s
->next
; s
= s
->next
);
2099 daemon
->enable_pxe
= 1;
2109 case '4': /* --dhcp-mac */
2111 if (!(comma
= split(arg
)))
2115 struct dhcp_mac
*new = opt_malloc(sizeof(struct dhcp_mac
));
2116 if (strstr(arg
, "net:") == arg
)
2117 new->netid
.net
= opt_string_alloc(arg
+4);
2119 new->netid
.net
= opt_string_alloc(arg
);
2120 unhide_metas(comma
);
2121 new->hwaddr_len
= parse_hex(comma
, new->hwaddr
, DHCP_CHADDR_MAX
, &new->mask
, &new->hwaddr_type
);
2122 new->next
= daemon
->dhcp_macs
;
2123 daemon
->dhcp_macs
= new;
2128 case 'U': /* --dhcp-vendorclass */
2129 case 'j': /* --dhcp-userclass */
2130 case LOPT_CIRCUIT
: /* --dhcp-circuitid */
2131 case LOPT_REMOTE
: /* --dhcp-remoteid */
2132 case LOPT_SUBSCR
: /* --dhcp-subscrid */
2134 if (!(comma
= split(arg
)))
2140 struct dhcp_vendor
*new = opt_malloc(sizeof(struct dhcp_vendor
));
2141 if (strstr(arg
, "net:") == arg
)
2142 new->netid
.net
= opt_string_alloc(arg
+4);
2144 new->netid
.net
= opt_string_alloc(arg
);
2145 /* check for hex string - must digits may include : must not have nothing else,
2146 only allowed for agent-options. */
2147 for (p
= comma
; *p
; p
++)
2148 if (isxdigit((int)*p
))
2152 unhide_metas(comma
);
2153 if (option
== 'U' || option
== 'j' || *p
|| !dig
)
2155 new->len
= strlen(comma
);
2156 new->data
= opt_malloc(new->len
);
2157 memcpy(new->data
, comma
, new->len
);
2161 new->len
= parse_hex(comma
, (unsigned char *)comma
, strlen(comma
), NULL
, NULL
);
2162 new->data
= opt_malloc(new->len
);
2163 memcpy(new->data
, comma
, new->len
);
2169 new->match_type
= MATCH_USER
;
2172 new->match_type
= MATCH_VENDOR
;
2175 new->match_type
= MATCH_CIRCUIT
;
2178 new->match_type
= MATCH_REMOTE
;
2181 new->match_type
= MATCH_SUBSCRIBER
;
2184 new->next
= daemon
->dhcp_vendors
;
2185 daemon
->dhcp_vendors
= new;
2190 case LOPT_ALTPORT
: /* --dhcp-alternate-port */
2193 daemon
->dhcp_server_port
= DHCP_SERVER_ALTPORT
;
2194 daemon
->dhcp_client_port
= DHCP_CLIENT_ALTPORT
;
2199 if (!atoi_check16(arg
, &daemon
->dhcp_server_port
) ||
2200 (comma
&& !atoi_check16(comma
, &daemon
->dhcp_client_port
)))
2201 problem
= _("invalid port number");
2203 daemon
->dhcp_client_port
= daemon
->dhcp_server_port
+1;
2207 case 'J': /* --dhcp-ignore */
2208 case LOPT_NO_NAMES
: /* --dhcp-ignore-names */
2209 case LOPT_BROADCAST
: /* --dhcp-broadcast */
2210 case '3': /* --bootp-dynamic */
2212 struct dhcp_netid_list
*new = opt_malloc(sizeof(struct dhcp_netid_list
));
2213 struct dhcp_netid
*list
= NULL
;
2216 new->next
= daemon
->dhcp_ignore
;
2217 daemon
->dhcp_ignore
= new;
2219 else if (option
== LOPT_BROADCAST
)
2221 new->next
= daemon
->force_broadcast
;
2222 daemon
->force_broadcast
= new;
2224 else if (option
== '3')
2226 new->next
= daemon
->bootp_dynamic
;
2227 daemon
->bootp_dynamic
= new;
2231 new->next
= daemon
->dhcp_ignore_names
;
2232 daemon
->dhcp_ignore_names
= new;
2236 struct dhcp_netid
*member
= opt_malloc(sizeof(struct dhcp_netid
));
2238 member
->next
= list
;
2240 if (strstr(arg
, "net:") == arg
)
2241 member
->net
= opt_string_alloc(arg
+4);
2243 member
->net
= opt_string_alloc(arg
);
2252 case 'V': /* --alias */
2254 char *dash
, *a
[3] = { NULL
, NULL
, NULL
};
2256 struct doctor
*new = opt_malloc(sizeof(struct doctor
));
2257 new->next
= daemon
->doctors
;
2258 daemon
->doctors
= new;
2259 new->mask
.s_addr
= 0xffffffff;
2260 new->end
.s_addr
= 0;
2263 for (k
= 1; k
< 3; k
++)
2265 if (!(a
[k
] = split(a
[k
-1])))
2270 dash
= split_chr(a
[0], '-');
2273 ((new->in
.s_addr
= inet_addr(a
[0])) == (in_addr_t
)-1) ||
2274 ((new->out
.s_addr
= inet_addr(a
[1])) == (in_addr_t
)-1))
2278 new->mask
.s_addr
= inet_addr(a
[2]);
2281 ((new->end
.s_addr
= inet_addr(dash
)) == (in_addr_t
)-1 ||
2282 !is_same_net(new->in
, new->end
, new->mask
) ||
2283 ntohl(new->in
.s_addr
) > ntohl(new->end
.s_addr
)))
2284 problem
= _("invalid alias range");
2289 case LOPT_INTNAME
: /* --interface-name */
2291 struct interface_name
*new, **up
;
2292 char *domain
= NULL
;
2296 if (!comma
|| !(domain
= canonicalise_opt(arg
)))
2297 problem
= _("bad interface name");
2299 new = opt_malloc(sizeof(struct interface_name
));
2301 /* Add to the end of the list, so that first name
2302 of an interface is used for PTR lookups. */
2303 for (up
= &daemon
->int_names
; *up
; up
= &((*up
)->next
));
2306 new->intr
= opt_string_alloc(comma
);
2310 case LOPT_CNAME
: /* --cname */
2314 if (!(comma
= split(arg
)))
2318 char *alias
= canonicalise_opt(arg
);
2319 char *target
= canonicalise_opt(comma
);
2321 if (!alias
|| !target
)
2322 problem
= _("bad CNAME");
2325 for (new = daemon
->cnames
; new; new = new->next
)
2326 if (hostname_isequal(new->alias
, arg
))
2327 problem
= _("duplicate CNAME");
2328 new = opt_malloc(sizeof(struct cname
));
2329 new->next
= daemon
->cnames
;
2330 daemon
->cnames
= new;
2332 new->target
= target
;
2338 case LOPT_PTR
: /* --ptr-record */
2340 struct ptr_record
*new;
2341 char *dom
, *target
= NULL
;
2345 if (!(dom
= canonicalise_opt(arg
)) ||
2346 (comma
&& !(target
= canonicalise_opt(comma
))))
2347 problem
= _("bad PTR record");
2350 new = opt_malloc(sizeof(struct ptr_record
));
2351 new->next
= daemon
->ptr
;
2359 case LOPT_NAPTR
: /* --naptr-record */
2361 char *a
[7] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
2365 char *name
, *replace
= NULL
;
2368 for (k
= 1; k
< 7; k
++)
2369 if (!(a
[k
] = split(a
[k
-1])))
2374 !(name
= canonicalise_opt(a
[0])) ||
2375 !atoi_check16(a
[1], &order
) ||
2376 !atoi_check16(a
[2], &pref
) ||
2377 (k
== 7 && !(replace
= canonicalise_opt(a
[6]))))
2378 problem
= _("bad NAPTR record");
2381 new = opt_malloc(sizeof(struct naptr
));
2382 new->next
= daemon
->naptr
;
2383 daemon
->naptr
= new;
2385 new->flags
= opt_string_alloc(a
[3]);
2386 new->services
= opt_string_alloc(a
[4]);
2387 new->regexp
= opt_string_alloc(a
[5]);
2388 new->replace
= replace
;
2395 case 'Y': /* --txt-record */
2397 struct txt_record
*new;
2398 unsigned char *p
, *q
;
2400 if ((comma
= split(arg
)))
2403 gen_prob
= _("TXT record string too long");
2405 if ((q
= (unsigned char *)comma
))
2409 if ((p
= (unsigned char *)strchr((char*)q
+1, ',')))
2411 if ((len
= p
- q
- 1) > 255)
2414 for (q
= q
+1; q
< p
; q
++)
2415 *q
= unhide_meta(*q
);
2419 if ((len
= strlen((char *)q
+1)) > 255)
2422 for (q
= q
+1; *q
; q
++)
2423 *q
= unhide_meta(*q
);
2428 new = opt_malloc(sizeof(struct txt_record
));
2429 new->next
= daemon
->txt
;
2434 new->len
= q
- ((unsigned char *)comma
);
2435 new->txt
= opt_malloc(new->len
);
2436 memcpy(new->txt
, comma
, new->len
);
2440 static char empty
[] = "";
2445 /* ensure arg is terminated */
2449 if (!(new->name
= canonicalise_opt(arg
)))
2451 problem
= _("bad TXT record");
2458 case 'W': /* --srv-host */
2460 int port
= 1, priority
= 0, weight
= 0;
2461 char *name
, *target
= NULL
;
2462 struct mx_srv_record
*new;
2466 if (!(name
= canonicalise_opt(arg
)))
2467 problem
= _("bad SRV record");
2473 if (!(target
= canonicalise_opt(arg
))
2474 ) problem
= _("bad SRV target");
2480 if (!atoi_check16(arg
, &port
))
2481 problem
= _("invalid port number");
2487 if (!atoi_check16(arg
, &priority
))
2488 problem
= _("invalid priority");
2494 if (!atoi_check16(arg
, &weight
))
2495 problem
= _("invalid weight");
2501 new = opt_malloc(sizeof(struct mx_srv_record
));
2502 new->next
= daemon
->mxnames
;
2503 daemon
->mxnames
= new;
2506 new->target
= target
;
2507 new->srvport
= port
;
2508 new->priority
= priority
;
2509 new->weight
= weight
;
2514 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2527 static void one_file(char *file
, int nest
, int hard_opt
)
2529 volatile int lineno
= 0;
2532 char *p
, *arg
, *start
, *buff
= daemon
->namebuff
;
2533 static struct fileread
{
2536 struct fileread
*next
;
2537 } *filesread
= NULL
;
2538 struct stat statbuf
;
2540 /* ignore repeated files. */
2541 if (hard_opt
== 0 && stat(file
, &statbuf
) == 0)
2545 for (r
= filesread
; r
; r
= r
->next
)
2546 if (r
->dev
== statbuf
.st_dev
&& r
->ino
== statbuf
.st_ino
)
2549 r
= safe_malloc(sizeof(struct fileread
));
2550 r
->next
= filesread
;
2552 r
->dev
= statbuf
.st_dev
;
2553 r
->ino
= statbuf
.st_ino
;
2557 die(_("files nested too deep in %s"), file
, EC_BADCONF
);
2559 if (!(f
= fopen(file
, "r")))
2561 if (errno
== ENOENT
&& nest
== 0)
2562 return; /* No conffile, all done. */
2565 char *str
= _("cannot read %s: %s");
2568 my_syslog(LOG_ERR
, str
, file
, strerror(errno
));
2572 die(str
, file
, EC_FILE
);
2576 while (fgets(buff
, MAXDNAME
, f
))
2579 unsigned int lastquote
;
2582 /* Memory allocation failure longjmps here if mem_recover == 1 */
2585 if (setjmp(mem_jmp
))
2593 /* Implement quotes, inside quotes we allow \\ \" \n and \t
2594 metacharacters get hidden also strip comments */
2596 for (white
= 1, lastquote
= 0, p
= buff
; *p
; p
++)
2600 memmove(p
, p
+1, strlen(p
+1)+1);
2601 for(; *p
&& *p
!= '"'; p
++)
2603 if (*p
== '\\' && strchr("\"tnebr\\", p
[1]))
2607 else if (p
[1] == 'n')
2609 else if (p
[1] == 'b')
2611 else if (p
[1] == 'r')
2613 else if (p
[1] == 'e') /* escape */
2615 memmove(p
, p
+1, strlen(p
+1)+1);
2621 memmove(p
, p
+1, strlen(p
+1)+1);
2622 lastquote
= p
- buff
;
2626 errmess
= _("missing \"");
2631 if (white
&& *p
== '#')
2636 white
= isspace((int)unhide_meta(*p
));
2639 /* fgets gets end of line char too. */
2640 while (strlen(buff
) > lastquote
&& isspace((int)unhide_meta(buff
[strlen(buff
)-1])))
2641 buff
[strlen(buff
)-1] = 0;
2648 else if ((p
=strchr(buff
, '=')))
2650 /* allow spaces around "=" */
2652 for (; p
>= buff
&& (isspace((int)*p
) || *p
== '='); p
--)
2662 /* skip leading space */
2663 for (start
= buff
; *start
&& isspace((int)*start
); start
++);
2665 for (option
= 0, i
= 0; opts
[i
].name
; i
++)
2666 if (strcmp(opts
[i
].name
, start
) == 0)
2668 option
= opts
[i
].val
;
2673 errmess
= _("bad option");
2674 else if (opts
[i
].has_arg
== 0 && arg
)
2675 errmess
= _("extraneous parameter");
2676 else if (opts
[i
].has_arg
== 1 && !arg
)
2677 errmess
= _("missing parameter");
2683 for (; isspace((int)*arg
); arg
++);
2685 errmess
= one_opt(option
, arg
, _("error"), nest
+ 1);
2691 sprintf(buff
, _("%s at line %d of %%s"), errmess
, lineno
);
2693 my_syslog(LOG_ERR
, buff
, file
);
2695 die(buff
, file
, EC_BADCONF
);
2704 void reread_dhcp(void)
2706 if (daemon
->dhcp_hosts_file
)
2708 struct dhcp_config
*configs
, *cp
, **up
;
2710 /* remove existing... */
2711 for (up
= &daemon
->dhcp_conf
, configs
= daemon
->dhcp_conf
; configs
; configs
= cp
)
2715 if (configs
->flags
& CONFIG_BANK
)
2717 struct hwaddr_config
*mac
, *tmp
;
2719 for (mac
= configs
->hwaddr
; mac
; mac
= tmp
)
2724 if (configs
->flags
& CONFIG_CLID
)
2725 free(configs
->clid
);
2726 if (configs
->flags
& CONFIG_NETID
)
2727 free(configs
->netid
.net
);
2728 if (configs
->flags
& CONFIG_NAME
)
2729 free(configs
->hostname
);
2732 *up
= configs
->next
;
2736 up
= &configs
->next
;
2739 one_file(daemon
->dhcp_hosts_file
, 1, LOPT_BANK
);
2740 my_syslog(MS_DHCP
| LOG_INFO
, _("read %s"), daemon
->dhcp_hosts_file
);
2743 if (daemon
->dhcp_opts_file
)
2745 struct dhcp_opt
*opts
, *cp
, **up
;
2746 struct dhcp_netid
*id
, *next
;
2748 for (up
= &daemon
->dhcp_opts
, opts
= daemon
->dhcp_opts
; opts
; opts
= cp
)
2752 if (opts
->flags
& DHOPT_BANK
)
2754 if ((opts
->flags
& DHOPT_VENDOR
))
2755 free(opts
->u
.vendor_class
);
2757 for (id
= opts
->netid
; id
; id
= next
)
2770 one_file(daemon
->dhcp_opts_file
, 1, LOPT_OPTS
);
2771 my_syslog(MS_DHCP
| LOG_INFO
, _("read %s"), daemon
->dhcp_opts_file
);
2776 void read_opts(int argc
, char **argv
, char *compile_opts
)
2778 char *buff
= opt_malloc(MAXDNAME
);
2779 int option
, nest
= 0, testmode
= 0;
2780 char *errmess
, *arg
, *conffile
= CONFFILE
;
2784 daemon
= opt_malloc(sizeof(struct daemon
));
2785 memset(daemon
, 0, sizeof(struct daemon
));
2786 daemon
->namebuff
= buff
;
2788 /* Set defaults - everything else is zero or NULL */
2789 daemon
->cachesize
= CACHESIZ
;
2790 daemon
->ftabsize
= FTABSIZ
;
2791 daemon
->port
= NAMESERVER_PORT
;
2792 daemon
->dhcp_client_port
= DHCP_CLIENT_PORT
;
2793 daemon
->dhcp_server_port
= DHCP_SERVER_PORT
;
2794 daemon
->default_resolv
.is_default
= 1;
2795 daemon
->default_resolv
.name
= RESOLVFILE
;
2796 daemon
->resolv_files
= &daemon
->default_resolv
;
2797 daemon
->username
= CHUSER
;
2798 daemon
->runfile
= RUNFILE
;
2799 daemon
->dhcp_max
= MAXLEASES
;
2800 daemon
->tftp_max
= TFTP_MAX_CONNECTIONS
;
2801 daemon
->edns_pktsz
= EDNS_PKTSZ
;
2802 daemon
->log_fac
= -1;
2803 add_txt("version.bind", "dnsmasq-" VERSION
);
2804 add_txt("authors.bind", "Simon Kelley");
2805 add_txt("copyright.bind", COPYRIGHT
);
2809 #ifdef HAVE_GETOPT_LONG
2810 option
= getopt_long(argc
, argv
, OPTSTRING
, opts
, NULL
);
2812 option
= getopt(argc
, argv
, OPTSTRING
);
2818 /* Copy optarg so that argv doesn't get changed */
2821 strncpy(buff
, optarg
, MAXDNAME
);
2822 buff
[MAXDNAME
-1] = 0;
2828 /* command-line only stuff */
2829 if (option
== LOPT_TEST
)
2831 else if (option
== 'w')
2833 if (argc
!= 3 || strcmp(argv
[2], "dhcp") != 0)
2841 else if (option
== 'v')
2843 printf(_("Dnsmasq version %s %s\n"), VERSION
, COPYRIGHT
);
2844 printf(_("Compile time options %s\n\n"), compile_opts
);
2845 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
2846 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
2847 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
2850 else if (option
== 'C')
2852 conffile
= opt_string_alloc(arg
);
2857 #ifdef HAVE_GETOPT_LONG
2858 errmess
= one_opt(option
, arg
, _("try --help"), 0);
2860 errmess
= one_opt(option
, arg
, _("try -w"), 0);
2863 die(_("bad command line options: %s"), errmess
, EC_BADCONF
);
2868 one_file(conffile
, nest
, 0);
2870 /* port might not be known when the address is parsed - fill in here */
2871 if (daemon
->servers
)
2874 for (tmp
= daemon
->servers
; tmp
; tmp
= tmp
->next
)
2875 if (!(tmp
->flags
& SERV_HAS_SOURCE
))
2877 if (tmp
->source_addr
.sa
.sa_family
== AF_INET
)
2878 tmp
->source_addr
.in
.sin_port
= htons(daemon
->query_port
);
2880 else if (tmp
->source_addr
.sa
.sa_family
== AF_INET6
)
2881 tmp
->source_addr
.in6
.sin6_port
= htons(daemon
->query_port
);
2886 if (daemon
->if_addrs
)
2889 for(tmp
= daemon
->if_addrs
; tmp
; tmp
= tmp
->next
)
2890 if (tmp
->addr
.sa
.sa_family
== AF_INET
)
2891 tmp
->addr
.in
.sin_port
= htons(daemon
->port
);
2893 else if (tmp
->addr
.sa
.sa_family
== AF_INET6
)
2894 tmp
->addr
.in6
.sin6_port
= htons(daemon
->port
);
2898 /* only one of these need be specified: the other defaults to the host-name */
2899 if ((daemon
->options
& OPT_LOCALMX
) || daemon
->mxnames
|| daemon
->mxtarget
)
2901 struct mx_srv_record
*mx
;
2903 if (gethostname(buff
, MAXDNAME
) == -1)
2904 die(_("cannot get host-name: %s"), NULL
, EC_MISC
);
2906 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
2907 if (!mx
->issrv
&& hostname_isequal(mx
->name
, buff
))
2910 if ((daemon
->mxtarget
|| (daemon
->options
& OPT_LOCALMX
)) && !mx
)
2912 mx
= opt_malloc(sizeof(struct mx_srv_record
));
2913 mx
->next
= daemon
->mxnames
;
2916 mx
->name
= opt_string_alloc(buff
);
2917 daemon
->mxnames
= mx
;
2920 if (!daemon
->mxtarget
)
2921 daemon
->mxtarget
= opt_string_alloc(buff
);
2923 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
2924 if (!mx
->issrv
&& !mx
->target
)
2925 mx
->target
= daemon
->mxtarget
;
2928 if (!(daemon
->options
& OPT_NO_RESOLV
) &&
2929 daemon
->resolv_files
&&
2930 daemon
->resolv_files
->next
&&
2931 (daemon
->options
& OPT_NO_POLL
))
2932 die(_("only one resolv.conf file allowed in no-poll mode."), NULL
, EC_BADCONF
);
2934 if (daemon
->options
& OPT_RESOLV_DOMAIN
)
2939 if ((daemon
->options
& OPT_NO_RESOLV
) ||
2940 !daemon
->resolv_files
||
2941 (daemon
->resolv_files
)->next
)
2942 die(_("must have exactly one resolv.conf to read domain from."), NULL
, EC_BADCONF
);
2944 if (!(f
= fopen((daemon
->resolv_files
)->name
, "r")))
2945 die(_("failed to read %s: %s"), (daemon
->resolv_files
)->name
, EC_FILE
);
2947 while ((line
= fgets(buff
, MAXDNAME
, f
)))
2949 char *token
= strtok(line
, " \t\n\r");
2951 if (!token
|| strcmp(token
, "search") != 0)
2954 if ((token
= strtok(NULL
, " \t\n\r")) &&
2955 (daemon
->domain_suffix
= canonicalise_opt(token
)))
2961 if (!daemon
->domain_suffix
)
2962 die(_("no search directive found in %s"), (daemon
->resolv_files
)->name
, EC_MISC
);
2965 if (daemon
->domain_suffix
)
2967 /* add domain for any srv record without one. */
2968 struct mx_srv_record
*srv
;
2970 for (srv
= daemon
->mxnames
; srv
; srv
= srv
->next
)
2972 strchr(srv
->name
, '.') &&
2973 strchr(srv
->name
, '.') == strrchr(srv
->name
, '.'))
2975 strcpy(buff
, srv
->name
);
2977 strcat(buff
, daemon
->domain_suffix
);
2979 srv
->name
= opt_string_alloc(buff
);
2982 else if (daemon
->options
& OPT_DHCP_FQDN
)
2983 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL
, EC_BADCONF
);
2987 fprintf(stderr
, "dnsmasq: %s.\n", _("syntax check OK"));