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 },
412 char *option_string(unsigned char opt
, int *is_ip
, int *is_name
)
416 for (i
= 0; opttab
[i
].name
; i
++)
417 if (opttab
[i
].val
== opt
)
420 *is_ip
= !!(opttab
[i
].size
& OT_ADDR_LIST
);
422 *is_name
= !!(opttab
[i
].size
& OT_NAME
);
423 return opttab
[i
].name
;
431 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
432 character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
433 following sequence so that they map to themselves: it is therefore possible to call
434 unhide_metas repeatedly on string without breaking things.
435 The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
436 couple of other places.
437 Note that space is included here so that
438 --dhcp-option=3, string
439 has five characters, whilst
440 --dhcp-option=3," string"
444 static const char meta
[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
446 static char hide_meta(char c
)
450 for (i
= 0; i
< (sizeof(meta
) - 1); i
++)
457 static char unhide_meta(char cr
)
461 if (c
< (sizeof(meta
) - 1))
467 static void unhide_metas(char *cp
)
471 *cp
= unhide_meta(*cp
);
474 static void *opt_malloc(size_t size
)
480 ret
= whine_malloc(size
);
485 ret
= safe_malloc(size
);
490 static char *opt_string_alloc(char *cp
)
494 if (cp
&& strlen(cp
) != 0)
496 ret
= opt_malloc(strlen(cp
)+1);
499 /* restore hidden metachars */
507 /* find next comma, split string with zero and eliminate spaces.
508 return start of string following comma */
510 static char *split_chr(char *s
, char c
)
514 if (!s
|| !(comma
= strchr(s
, c
)))
520 for (; isspace((int)*comma
); comma
++);
522 for (; (p
>= s
) && isspace((int)*p
); p
--)
528 static char *split(char *s
)
530 return split_chr(s
, ',');
533 static int canonicalise_opt(char *s
)
539 return canonicalise(s
);
542 static int atoi_check(char *a
, int *res
)
552 if (*p
< '0' || *p
> '9')
559 static int atoi_check16(char *a
, int *res
)
561 if (!(atoi_check(a
, res
)) ||
569 static void add_txt(char *name
, char *txt
)
571 size_t len
= strlen(txt
);
572 struct txt_record
*r
= opt_malloc(sizeof(struct txt_record
));
574 r
->name
= opt_string_alloc(name
);
575 r
->next
= daemon
->txt
;
578 r
->txt
= opt_malloc(len
+1);
581 memcpy((r
->txt
)+1, txt
, len
);
584 static void do_usage(void)
597 { '#', TFTP_MAX_CONNECTIONS
},
601 printf(_("Usage: dnsmasq [options]\n\n"));
602 #ifndef HAVE_GETOPT_LONG
603 printf(_("Use short options only on the command line.\n"));
605 printf(_("Valid options are:\n"));
607 for (i
= 0; usage
[i
].opt
!= 0; i
++)
609 char *desc
= usage
[i
].flagdesc
;
612 if (!desc
|| *desc
== '[')
618 for ( j
= 0; opts
[j
].name
; j
++)
619 if (opts
[j
].val
== usage
[i
].opt
)
621 if (usage
[i
].opt
< 256)
622 sprintf(buff
, "-%c, ", usage
[i
].opt
);
626 sprintf(buff
+4, "--%s%s%s", opts
[j
].name
, eq
, desc
);
627 printf("%-36.36s", buff
);
631 strcpy(buff
, usage
[i
].arg
);
632 for (j
= 0; tab
[j
].handle
; j
++)
633 if (tab
[j
].handle
== *(usage
[i
].arg
))
634 sprintf(buff
, "%d", tab
[j
].val
);
636 printf(_(usage
[i
].desc
), buff
);
642 static void display_opts(void)
646 printf(_("Known DHCP options:\n"));
648 for (i
= 0; opttab
[i
].name
; i
++)
649 if (opttab
[i
].size
!= OT_INTERNAL
)
650 printf("%3d %s\n", opttab
[i
].val
, opttab
[i
].name
);
653 /* This is too insanely large to keep in-line in the switch */
654 static char *parse_dhcp_opt(char *arg
, int flags
)
656 struct dhcp_opt
*new = opt_malloc(sizeof(struct dhcp_opt
));
657 char lenchar
= 0, *cp
;
658 int i
, addrs
, digs
, is_addr
, is_hex
, is_dec
, is_string
, dots
;
659 char *comma
= NULL
, *problem
= NULL
;
660 struct dhcp_netid
*np
= NULL
;
661 unsigned char opt_len
= 0;
673 for (cp
= arg
; *cp
; cp
++)
674 if (*cp
< '0' || *cp
> '9')
679 new->opt
= atoi(arg
);
684 if (strstr(arg
, "option:") == arg
)
686 for (i
= 0; opttab
[i
].name
; i
++)
687 if (opttab
[i
].size
!= OT_INTERNAL
&&
688 strcasecmp(opttab
[i
].name
, arg
+7) == 0)
690 new->opt
= opttab
[i
].val
;
691 opt_len
= opttab
[i
].size
;
694 /* option:<optname> must follow tag and vendor string. */
697 else if (strstr(arg
, "vendor:") == arg
)
699 new->u
.vendor_class
= (unsigned char *)opt_string_alloc(arg
+7);
700 new->flags
|= DHOPT_VENDOR
;
702 else if (strstr(arg
, "encap:") == arg
)
704 new->u
.encap
= atoi(arg
+6);
705 new->flags
|= DHOPT_ENCAPSULATE
;
709 new->netid
= opt_malloc(sizeof (struct dhcp_netid
));
710 /* allow optional "net:" for consistency */
711 if (strstr(arg
, "net:") == arg
)
712 new->netid
->net
= opt_string_alloc(arg
+4);
714 new->netid
->net
= opt_string_alloc(arg
);
715 new->netid
->next
= np
;
723 problem
= _("bad dhcp-option");
726 /* characterise the value */
728 is_addr
= is_hex
= is_dec
= is_string
= 1;
731 for (cp
= comma
; (c
= *cp
); cp
++)
740 is_dec
= is_addr
= 0;
745 if (cp
== comma
) /* leading / means a pathname */
754 is_hex
= is_addr
= 0;
757 else if (!(c
>='0' && c
<= '9'))
760 if (cp
[1] == 0 && is_dec
&&
761 (c
== 'b' || c
== 's' || c
== 'i'))
768 if (!((c
>='A' && c
<= 'F') ||
769 (c
>='a' && c
<= 'f') ||
770 (c
== '*' && (flags
& DHOPT_MATCH
))))
774 /* We know that some options take addresses */
776 if (opt_len
& OT_ADDR_LIST
)
778 is_string
= is_dec
= is_hex
= 0;
779 if (!is_addr
|| dots
== 0)
780 problem
= _("bad IP address");
783 if (is_hex
&& digs
> 1)
786 new->val
= opt_malloc(new->len
);
787 parse_hex(comma
, new->val
, digs
, (flags
& DHOPT_MATCH
) ? &new->u
.wildcard_mask
: NULL
, NULL
);
788 new->flags
|= DHOPT_HEX
;
792 int i
, val
= atoi(comma
);
793 /* assume numeric arg is 1 byte except for
794 options where it is known otherwise.
795 For vendor class option, we have to hack. */
798 else if (val
& 0xffff0000)
800 else if (val
& 0xff00)
807 else if (lenchar
== 's')
809 else if (lenchar
== 'i')
812 new->val
= opt_malloc(new->len
);
813 for (i
=0; i
<new->len
; i
++)
814 new->val
[i
] = val
>>((new->len
- i
- 1)*8);
821 /* max length of address/subnet descriptor is five bytes,
822 add one for the option 120 enc byte too */
823 new->val
= op
= opt_malloc((5 * addrs
) + 1);
824 new->flags
|= DHOPT_ADDR
;
826 if (!(new->flags
& DHOPT_ENCAPSULATE
) && new->opt
== 120)
828 *(op
++) = 1; /* RFC 3361 "enc byte" */
829 new->flags
&= ~DHOPT_ADDR
;
835 slash
= split_chr(cp
, '/');
836 in
.s_addr
= inet_addr(cp
);
839 memcpy(op
, &in
, INADDRSZ
);
844 unsigned char *p
= (unsigned char *)&in
;
845 int netsize
= atoi(slash
);
855 new->flags
&= ~DHOPT_ADDR
; /* cannot re-write descriptor format */
858 new->len
= op
- new->val
;
863 if ((new->opt
== 119 || new->opt
== 120) && !(new->flags
& DHOPT_ENCAPSULATE
))
865 /* dns search, RFC 3397, or SIP, RFC 3361 */
866 unsigned char *q
, *r
, *tail
;
867 unsigned char *p
, *m
= NULL
, *newp
;
868 size_t newlen
, len
= 0;
869 int header_size
= (new->opt
== 119) ? 0 : 1;
876 if (!canonicalise_opt(arg
))
878 problem
= _("bad domain in dhcp-option");
882 newp
= opt_malloc(len
+ strlen(arg
) + 2 + header_size
);
884 memcpy(newp
, m
, header_size
+ len
);
889 /* add string on the end in RFC1035 format */
892 unsigned char *cp
= q
++;
894 for (j
= 0; *arg
&& (*arg
!= '.'); arg
++, j
++)
902 /* Now tail-compress using earlier names. */
904 for (tail
= p
+ len
; *tail
; tail
+= (*tail
) + 1)
905 for (r
= p
; r
- p
< (int)len
; r
+= (*r
) + 1)
906 if (strcmp((char *)r
, (char *)tail
) == 0)
908 PUTSHORT((r
- p
) | 0xc000, tail
);
919 /* RFC 3361, enc byte is zero for names */
922 new->len
= (int) len
+ header_size
;
927 new->len
= strlen(comma
);
928 /* keep terminating zero on string */
929 new->val
= (unsigned char *)opt_string_alloc(comma
);
930 new->flags
|= DHOPT_STRING
;
935 if ((new->len
> 255) || (new->len
> 253 && (new->flags
& (DHOPT_VENDOR
| DHOPT_ENCAPSULATE
))))
936 problem
= _("dhcp-option too long");
940 if (flags
== DHOPT_MATCH
)
942 if ((new->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
)) ||
945 problem
= _("illegal dhcp-match");
948 new->next
= daemon
->dhcp_match
;
949 daemon
->dhcp_match
= new;
954 new->next
= daemon
->dhcp_opts
;
955 daemon
->dhcp_opts
= new;
964 static char *one_opt(int option
, char *arg
, char *gen_prob
, int nest
)
967 char *comma
, *problem
= NULL
;;
972 for (i
=0; usage
[i
].opt
!= 0; i
++)
973 if (usage
[i
].opt
== option
)
975 int rept
= usage
[i
].rept
;
980 if (rept
== ARG_USED_CL
)
981 return _("illegal repeated flag");
983 usage
[i
].rept
= ARG_USED_CL
;
987 /* allow file to override command line */
988 if (rept
== ARG_USED_FILE
)
989 return _("illegal repeated keyword");
990 if (rept
== ARG_USED_CL
|| rept
== ARG_ONE
)
991 usage
[i
].rept
= ARG_USED_FILE
;
994 if (rept
!= ARG_DUP
&& rept
!= ARG_ONE
&& rept
!= ARG_USED_CL
)
996 daemon
->options
|= rept
;
1005 case 'C': /* --conf-file */
1007 char *file
= opt_string_alloc(arg
);
1010 one_file(file
, nest
, 0);
1016 case '7': /* --conf-dir */
1020 char *directory
, *path
;
1022 if (!(directory
= opt_string_alloc(arg
)))
1025 if (!(dir_stream
= opendir(directory
)))
1026 die(_("cannot access directory %s: %s"), directory
, EC_FILE
);
1028 while ((ent
= readdir(dir_stream
)))
1030 size_t len
= strlen(ent
->d_name
);
1033 /* ignore emacs backups and dotfiles */
1035 ent
->d_name
[len
- 1] == '~' ||
1036 (ent
->d_name
[0] == '#' && ent
->d_name
[len
- 1] == '#') ||
1037 ent
->d_name
[0] == '.')
1040 path
= opt_malloc(strlen(directory
) + len
+ 2);
1041 strcpy(path
, directory
);
1043 strcat(path
, ent
->d_name
);
1045 if (stat(path
, &buf
) == -1)
1046 die(_("cannot access %s: %s"), path
, EC_FILE
);
1047 /* only reg files allowed. */
1048 if (!S_ISREG(buf
.st_mode
))
1051 /* dir is one level, so files must be readable */
1052 one_file(path
, nest
+ 1, 0);
1056 closedir(dir_stream
);
1061 case '8': /* --log-facility */
1062 /* may be a filename */
1063 if (strchr(arg
, '/'))
1064 daemon
->log_file
= opt_string_alloc(arg
);
1067 for (i
= 0; facilitynames
[i
].c_name
; i
++)
1068 if (hostname_isequal((char *)facilitynames
[i
].c_name
, arg
))
1071 if (facilitynames
[i
].c_name
)
1072 daemon
->log_fac
= facilitynames
[i
].c_val
;
1074 problem
= "bad log facility";
1078 case 'x': /* --pid-file */
1079 daemon
->runfile
= opt_string_alloc(arg
);
1082 case LOPT_DHCP_HOST
: /* --dhcp-hostfile */
1083 if (daemon
->dhcp_hosts_file
)
1084 problem
= _("only one dhcp-hostsfile allowed");
1086 daemon
->dhcp_hosts_file
= opt_string_alloc(arg
);
1089 case LOPT_DHCP_OPTS
: /* --dhcp-optsfile */
1090 if (daemon
->dhcp_opts_file
)
1091 problem
= _("only one dhcp-optsfile allowed");
1093 daemon
->dhcp_opts_file
= opt_string_alloc(arg
);
1096 case 'r': /* --resolv-file */
1098 char *name
= opt_string_alloc(arg
);
1099 struct resolvc
*new, *list
= daemon
->resolv_files
;
1101 if (list
&& list
->is_default
)
1103 /* replace default resolv file - possibly with nothing */
1106 list
->is_default
= 0;
1114 new = opt_malloc(sizeof(struct resolvc
));
1117 new->is_default
= 0;
1122 daemon
->resolv_files
= list
;
1126 case 'm': /* --mx-host */
1129 struct mx_srv_record
*new;
1131 if ((comma
= split(arg
)))
1134 if ((prefstr
=split(comma
)) && !atoi_check16(prefstr
, &pref
))
1135 problem
= _("bad MX preference");
1138 if (!canonicalise_opt(arg
) || (comma
&& !canonicalise_opt(comma
)))
1139 problem
= _("bad MX name");
1141 new = opt_malloc(sizeof(struct mx_srv_record
));
1142 new->next
= daemon
->mxnames
;
1143 daemon
->mxnames
= new;
1145 new->name
= opt_string_alloc(arg
);
1146 new->target
= opt_string_alloc(comma
); /* may be NULL */
1151 case 't': /* --mx-target */
1152 if (!canonicalise_opt(arg
))
1153 problem
= _("bad MX target");
1155 daemon
->mxtarget
= opt_string_alloc(arg
);
1159 case 'l': /* --dhcp-leasefile */
1160 daemon
->lease_file
= opt_string_alloc(arg
);
1163 case '6': /* --dhcp-script */
1165 problem
= _("cannot run scripts under uClinux");
1167 daemon
->lease_change_command
= opt_string_alloc(arg
);
1172 case 'H': /* --addn-hosts */
1174 struct hostsfile
*new = opt_malloc(sizeof(struct hostsfile
));
1175 static int hosts_index
= 1;
1176 new->fname
= opt_string_alloc(arg
);
1177 new->index
= hosts_index
++;
1179 new->next
= daemon
->addn_hosts
;
1180 daemon
->addn_hosts
= new;
1184 case 's': /* --domain */
1185 if (strcmp (arg
, "#") == 0)
1186 daemon
->options
|= OPT_RESOLV_DOMAIN
;
1190 if (!canonicalise_opt(arg
))
1194 char *d
= opt_string_alloc(arg
);
1197 struct cond_domain
*new = safe_malloc(sizeof(struct cond_domain
));
1198 unhide_metas(comma
);
1199 if ((arg
= split_chr(comma
, '/')))
1202 if ((new->start
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1 ||
1203 !atoi_check(arg
, &mask
))
1207 mask
= (1 << (32 - mask
)) - 1;
1208 new->start
.s_addr
= ntohl(htonl(new->start
.s_addr
) & ~mask
);
1209 new->end
.s_addr
= new->start
.s_addr
| htonl(mask
);
1212 else if ((arg
= split(comma
)))
1214 if ((new->start
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1 ||
1215 (new->end
.s_addr
= inet_addr(arg
)) == (in_addr_t
)-1)
1218 else if ((new->start
.s_addr
= new->end
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
1222 new->next
= daemon
->cond_domain
;
1223 daemon
->cond_domain
= new;
1226 daemon
->domain_suffix
= d
;
1231 case 'u': /* --user */
1232 daemon
->username
= opt_string_alloc(arg
);
1235 case 'g': /* --group */
1236 daemon
->groupname
= opt_string_alloc(arg
);
1237 daemon
->group_set
= 1;
1241 case LOPT_SCRIPTUSR
: /* --scriptuser */
1242 daemon
->scriptuser
= opt_string_alloc(arg
);
1246 case 'i': /* --interface */
1248 struct iname
*new = opt_malloc(sizeof(struct iname
));
1250 new->next
= daemon
->if_names
;
1251 daemon
->if_names
= new;
1252 /* new->name may be NULL if someone does
1253 "interface=" to disable all interfaces except loop. */
1254 new->name
= opt_string_alloc(arg
);
1255 new->isloop
= new->used
= 0;
1260 case 'I': /* --except-interface */
1261 case '2': /* --no-dhcp-interface */
1263 struct iname
*new = opt_malloc(sizeof(struct iname
));
1265 new->name
= opt_string_alloc(arg
);
1268 new->next
= daemon
->if_except
;
1269 daemon
->if_except
= new;
1273 new->next
= daemon
->dhcp_except
;
1274 daemon
->dhcp_except
= new;
1280 case 'B': /* --bogus-nxdomain */
1282 struct in_addr addr
;
1284 if (arg
&& (addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
)-1)
1286 struct bogus_addr
*baddr
= opt_malloc(sizeof(struct bogus_addr
));
1287 baddr
->next
= daemon
->bogus_addr
;
1288 daemon
->bogus_addr
= baddr
;
1292 option
= '?'; /* error */
1296 case 'a': /* --listen-address */
1298 struct iname
*new = opt_malloc(sizeof(struct iname
));
1301 new->next
= daemon
->if_addrs
;
1302 if (arg
&& (new->addr
.in
.sin_addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
)-1)
1304 new->addr
.sa
.sa_family
= AF_INET
;
1305 #ifdef HAVE_SOCKADDR_SA_LEN
1306 new->addr
.in
.sin_len
= sizeof(new->addr
.in
);
1310 else if (arg
&& inet_pton(AF_INET6
, arg
, &new->addr
.in6
.sin6_addr
) > 0)
1312 new->addr
.sa
.sa_family
= AF_INET6
;
1313 new->addr
.in6
.sin6_flowinfo
= 0;
1314 new->addr
.in6
.sin6_scope_id
= 0;
1315 #ifdef HAVE_SOCKADDR_SA_LEN
1316 new->addr
.in6
.sin6_len
= sizeof(new->addr
.in6
);
1322 option
= '?'; /* error */
1326 daemon
->if_addrs
= new;
1331 case 'S': /* --server */
1332 case LOPT_LOCAL
: /* --local */
1333 case 'A': /* --address */
1335 struct server
*serv
, *newlist
= NULL
;
1339 if (arg
&& *arg
== '/')
1343 while ((end
= split_chr(arg
, '/')))
1345 char *domain
= NULL
;
1346 /* # matches everything and becomes a zero length domain string */
1347 if (strcmp(arg
, "#") == 0)
1349 else if (!canonicalise_opt(arg
) && strlen(arg
) != 0)
1352 domain
= opt_string_alloc(arg
); /* NULL if strlen is zero */
1353 serv
= opt_malloc(sizeof(struct server
));
1354 memset(serv
, 0, sizeof(struct server
));
1355 serv
->next
= newlist
;
1357 serv
->domain
= domain
;
1358 serv
->flags
= domain
? SERV_HAS_DOMAIN
: SERV_FOR_NODOTS
;
1370 newlist
= opt_malloc(sizeof(struct server
));
1371 memset(newlist
, 0, sizeof(struct server
));
1376 newlist
->flags
|= SERV_LITERAL_ADDRESS
;
1377 if (!(newlist
->flags
& SERV_TYPE
))
1383 newlist
->flags
|= SERV_NO_ADDR
; /* no server */
1384 if (newlist
->flags
& SERV_LITERAL_ADDRESS
)
1389 int source_port
= 0, serv_port
= NAMESERVER_PORT
;
1390 char *portno
, *source
;
1392 if ((source
= split_chr(arg
, '@')) && /* is there a source. */
1393 (portno
= split_chr(source
, '#')) &&
1394 !atoi_check16(portno
, &source_port
))
1395 problem
= _("bad port");
1397 if ((portno
= split_chr(arg
, '#')) && /* is there a port no. */
1398 !atoi_check16(portno
, &serv_port
))
1399 problem
= _("bad port");
1401 if ((newlist
->addr
.in
.sin_addr
.s_addr
= inet_addr(arg
)) != (in_addr_t
) -1)
1403 newlist
->addr
.in
.sin_port
= htons(serv_port
);
1404 newlist
->source_addr
.in
.sin_port
= htons(source_port
);
1405 newlist
->addr
.sa
.sa_family
= newlist
->source_addr
.sa
.sa_family
= AF_INET
;
1406 #ifdef HAVE_SOCKADDR_SA_LEN
1407 newlist
->source_addr
.in
.sin_len
= newlist
->addr
.in
.sin_len
= sizeof(struct sockaddr_in
);
1411 newlist
->flags
|= SERV_HAS_SOURCE
;
1412 if ((newlist
->source_addr
.in
.sin_addr
.s_addr
= inet_addr(source
)) == (in_addr_t
) -1)
1414 #if defined(SO_BINDTODEVICE)
1415 newlist
->source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
1416 strncpy(newlist
->interface
, source
, IF_NAMESIZE
);
1418 problem
= _("interface binding not supported");
1423 newlist
->source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
1426 else if (inet_pton(AF_INET6
, arg
, &newlist
->addr
.in6
.sin6_addr
) > 0)
1428 newlist
->addr
.in6
.sin6_port
= htons(serv_port
);
1429 newlist
->source_addr
.in6
.sin6_port
= htons(source_port
);
1430 newlist
->addr
.sa
.sa_family
= newlist
->source_addr
.sa
.sa_family
= AF_INET6
;
1431 #ifdef HAVE_SOCKADDR_SA_LEN
1432 newlist
->addr
.in6
.sin6_len
= newlist
->source_addr
.in6
.sin6_len
= sizeof(newlist
->addr
.in6
);
1436 newlist
->flags
|= SERV_HAS_SOURCE
;
1437 if (inet_pton(AF_INET6
, source
, &newlist
->source_addr
.in6
.sin6_addr
) == 0)
1439 #if defined(SO_BINDTODEVICE)
1440 newlist
->source_addr
.in6
.sin6_addr
= in6addr_any
;
1441 strncpy(newlist
->interface
, source
, IF_NAMESIZE
);
1443 problem
= _("interface binding not supported");
1448 newlist
->source_addr
.in6
.sin6_addr
= in6addr_any
;
1452 option
= '?'; /* error */
1459 serv
->next
->flags
= serv
->flags
;
1460 serv
->next
->addr
= serv
->addr
;
1461 serv
->next
->source_addr
= serv
->source_addr
;
1464 serv
->next
= daemon
->servers
;
1465 daemon
->servers
= newlist
;
1469 case 'c': /* --cache-size */
1473 if (!atoi_check(arg
, &size
))
1477 /* zero is OK, and means no caching. */
1481 else if (size
> 10000)
1484 daemon
->cachesize
= size
;
1489 case 'p': /* --port */
1490 if (!atoi_check16(arg
, &daemon
->port
))
1494 case LOPT_MINPORT
: /* --min-port */
1495 if (!atoi_check16(arg
, &daemon
->min_port
))
1499 case '0': /* --dns-forward-max */
1500 if (!atoi_check(arg
, &daemon
->ftabsize
))
1504 case LOPT_MAX_LOGS
: /* --log-async */
1505 daemon
->max_logs
= LOG_MAX
; /* default */
1506 if (arg
&& !atoi_check(arg
, &daemon
->max_logs
))
1508 else if (daemon
->max_logs
> 100)
1509 daemon
->max_logs
= 100;
1512 case 'P': /* --edns-packet-max */
1515 if (!atoi_check(arg
, &i
))
1517 daemon
->edns_pktsz
= (unsigned short)i
;
1521 case 'Q': /* --query-port */
1522 if (!atoi_check16(arg
, &daemon
->query_port
))
1524 /* if explicitly set to zero, use single OS ephemeral port
1525 and disable random ports */
1526 if (daemon
->query_port
== 0)
1530 case 'T': /* --local-ttl */
1531 case LOPT_NEGTTL
: /* --neg-ttl */
1534 if (!atoi_check(arg
, &ttl
))
1536 else if (option
== LOPT_NEGTTL
)
1537 daemon
->neg_ttl
= (unsigned long)ttl
;
1539 daemon
->local_ttl
= (unsigned long)ttl
;
1544 case 'X': /* --dhcp-lease-max */
1545 if (!atoi_check(arg
, &daemon
->dhcp_max
))
1551 case LOPT_TFTP_MAX
: /* --tftp-max */
1552 if (!atoi_check(arg
, &daemon
->tftp_max
))
1556 case LOPT_PREFIX
: /* --tftp-prefix */
1557 daemon
->tftp_prefix
= opt_string_alloc(arg
);
1560 case LOPT_TFTPPORTS
: /* --tftp-port-range */
1561 if (!(comma
= split(arg
)) ||
1562 !atoi_check16(arg
, &daemon
->start_tftp_port
) ||
1563 !atoi_check16(comma
, &daemon
->end_tftp_port
))
1564 problem
= _("bad port range");
1566 if (daemon
->start_tftp_port
> daemon
->end_tftp_port
)
1568 int tmp
= daemon
->start_tftp_port
;
1569 daemon
->start_tftp_port
= daemon
->end_tftp_port
;
1570 daemon
->end_tftp_port
= tmp
;
1576 case LOPT_BRIDGE
: /* --bridge-interface */
1578 struct dhcp_bridge
*new = opt_malloc(sizeof(struct dhcp_bridge
));
1579 if (!(comma
= split(arg
)))
1581 problem
= _("bad bridge-interface");
1585 strncpy(new->iface
, arg
, IF_NAMESIZE
);
1587 new->next
= daemon
->bridges
;
1588 daemon
->bridges
= new;
1593 if (strlen(arg
) != 0)
1595 struct dhcp_bridge
*b
= opt_malloc(sizeof(struct dhcp_bridge
));
1596 b
->next
= new->alias
;
1598 strncpy(b
->iface
, arg
, IF_NAMESIZE
);
1606 case 'F': /* --dhcp-range */
1608 int k
, leasepos
= 2;
1609 char *cp
, *a
[5] = { NULL
, NULL
, NULL
, NULL
, NULL
};
1610 struct dhcp_context
*new = opt_malloc(sizeof(struct dhcp_context
));
1612 new->next
= daemon
->dhcp
;
1613 new->lease_time
= DEFLEASE
;
1614 new->addr_epoch
= 0;
1615 new->netmask
.s_addr
= 0;
1616 new->broadcast
.s_addr
= 0;
1617 new->router
.s_addr
= 0;
1618 new->netid
.net
= NULL
;
1622 gen_prob
= _("bad dhcp-range");
1632 for (cp
= arg
; *cp
; cp
++)
1633 if (!(*cp
== ' ' || *cp
== '.' || (*cp
>='0' && *cp
<= '9')))
1636 if (*cp
!= ',' && (comma
= split(arg
)))
1638 if (strstr(arg
, "net:") == arg
)
1640 struct dhcp_netid
*tt
= opt_malloc(sizeof (struct dhcp_netid
));
1641 tt
->net
= opt_string_alloc(arg
+4);
1642 tt
->next
= new->filter
;
1648 problem
= _("only one netid tag allowed");
1650 new->netid
.net
= opt_string_alloc(arg
);
1661 for (k
= 1; k
< 5; k
++)
1662 if (!(a
[k
] = split(a
[k
-1])))
1665 if (option
== '?' || (k
< 2) || ((new->start
.s_addr
= inet_addr(a
[0])) == (in_addr_t
)-1))
1667 else if (strcmp(a
[1], "static") == 0)
1669 new->end
= new->start
;
1670 new->flags
|= CONTEXT_STATIC
;
1672 else if (strcmp(a
[1], "proxy") == 0)
1674 new->end
= new->start
;
1675 new->flags
|= CONTEXT_PROXY
;
1677 else if ((new->end
.s_addr
= inet_addr(a
[1])) == (in_addr_t
)-1)
1680 if (ntohl(new->start
.s_addr
) > ntohl(new->end
.s_addr
))
1682 struct in_addr tmp
= new->start
;
1683 new->start
= new->end
;
1687 if (option
!= '?' && k
>= 3 && strchr(a
[2], '.') &&
1688 ((new->netmask
.s_addr
= inet_addr(a
[2])) != (in_addr_t
)-1))
1690 new->flags
|= CONTEXT_NETMASK
;
1692 if (!is_same_net(new->start
, new->end
, new->netmask
))
1693 problem
= _("inconsistent DHCP range");
1697 if (k
>= 4 && strchr(a
[3], '.') &&
1698 ((new->broadcast
.s_addr
= inet_addr(a
[3])) != (in_addr_t
)-1))
1700 new->flags
|= CONTEXT_BRDCAST
;
1704 if (k
>= leasepos
+1)
1706 if (strcmp(a
[leasepos
], "infinite") == 0)
1707 new->lease_time
= 0xffffffff;
1711 if (strlen(a
[leasepos
]) > 0)
1713 switch (a
[leasepos
][strlen(a
[leasepos
]) - 1])
1729 a
[leasepos
][strlen(a
[leasepos
]) - 1] = 0;
1732 new->lease_time
= atoi(a
[leasepos
]) * fac
;
1733 /* Leases of a minute or less confuse
1734 some clients, notably Apple's */
1735 if (new->lease_time
< 120)
1736 new->lease_time
= 120;
1744 case 'G': /* --dhcp-host */
1747 char *a
[6] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
1748 struct dhcp_config
*new;
1751 new = opt_malloc(sizeof(struct dhcp_config
));
1753 new->next
= daemon
->dhcp_conf
;
1754 new->flags
= (option
== LOPT_BANK
) ? CONFIG_BANK
: 0;
1758 for (k
= 1; k
< 6; k
++)
1759 if (!(a
[k
] = split(a
[k
-1])))
1762 for (j
= 0; j
< k
; j
++)
1763 if (strchr(a
[j
], ':')) /* ethernet address, netid or binary CLID */
1767 if ((arg
[0] == 'i' || arg
[0] == 'I') &&
1768 (arg
[1] == 'd' || arg
[1] == 'D') &&
1772 new->flags
|= CONFIG_NOCLID
;
1776 arg
+= 3; /* dump id: */
1777 if (strchr(arg
, ':'))
1778 len
= parse_hex(arg
, (unsigned char *)arg
, -1, NULL
, NULL
);
1782 len
= (int) strlen(arg
);
1785 if ((new->clid
= opt_malloc(len
)))
1787 new->flags
|= CONFIG_CLID
;
1788 new->clid_len
= len
;
1789 memcpy(new->clid
, arg
, len
);
1793 else if (strstr(arg
, "net:") == arg
)
1795 int len
= strlen(arg
+ 4) + 1;
1796 if ((new->netid
.net
= opt_malloc(len
)))
1798 new->flags
|= CONFIG_NETID
;
1799 strcpy(new->netid
.net
, arg
+4);
1800 unhide_metas(new->netid
.net
);
1805 struct hwaddr_config
*newhw
= opt_malloc(sizeof(struct hwaddr_config
));
1806 newhw
->next
= new->hwaddr
;
1807 new->hwaddr
= newhw
;
1808 newhw
->hwaddr_len
= parse_hex(a
[j
], newhw
->hwaddr
, DHCP_CHADDR_MAX
,
1809 &newhw
->wildcard_mask
, &newhw
->hwaddr_type
);
1812 else if (strchr(a
[j
], '.') && (in
.s_addr
= inet_addr(a
[j
])) != (in_addr_t
)-1)
1815 new->flags
|= CONFIG_ADDR
;
1819 char *cp
, *lastp
= NULL
, last
= 0;
1822 if (strlen(a
[j
]) > 1)
1824 lastp
= a
[j
] + strlen(a
[j
]) - 1;
1846 for (cp
= a
[j
]; *cp
; cp
++)
1847 if (!isdigit((int)*cp
) && *cp
!= ' ')
1854 if (strcmp(a
[j
], "infinite") == 0)
1856 new->lease_time
= 0xffffffff;
1857 new->flags
|= CONFIG_TIME
;
1859 else if (strcmp(a
[j
], "ignore") == 0)
1860 new->flags
|= CONFIG_DISABLE
;
1863 int len
= strlen(a
[j
]) + 1;
1864 if (!canonicalise_opt(a
[j
]))
1865 problem
= _("bad DHCP host name");
1866 else if ((new->hostname
= opt_malloc(len
)))
1868 new->flags
|= CONFIG_NAME
;
1869 strcpy(new->hostname
, a
[j
]);
1876 new->lease_time
= atoi(a
[j
]) * fac
;
1877 /* Leases of a minute or less confuse
1878 some clients, notably Apple's */
1879 if (new->lease_time
< 120)
1880 new->lease_time
= 120;
1881 new->flags
|= CONFIG_TIME
;
1885 daemon
->dhcp_conf
= new;
1889 case 'O': /* --dhcp-option */
1890 case LOPT_FORCE
: /* --dhcp-option-force */
1892 case LOPT_MATCH
: /* --dhcp-match */
1893 problem
= parse_dhcp_opt(arg
,
1894 option
== LOPT_FORCE
? DHOPT_FORCE
:
1895 (option
== LOPT_MATCH
? DHOPT_MATCH
:
1896 (option
== LOPT_OPTS
? DHOPT_BANK
: 0)));
1899 case 'M': /* --dhcp-boot */
1901 struct dhcp_netid
*id
= NULL
;
1902 while (arg
&& strstr(arg
, "net:") == arg
)
1904 struct dhcp_netid
*newid
= opt_malloc(sizeof(struct dhcp_netid
));
1908 newid
->net
= opt_string_alloc(arg
+4);
1916 char *dhcp_file
, *dhcp_sname
= NULL
;
1917 struct in_addr dhcp_next_server
;
1919 dhcp_file
= opt_string_alloc(arg
);
1920 dhcp_next_server
.s_addr
= 0;
1925 dhcp_sname
= opt_string_alloc(arg
);
1928 unhide_metas(comma
);
1929 if ((dhcp_next_server
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
1935 struct dhcp_boot
*new = opt_malloc(sizeof(struct dhcp_boot
));
1936 new->file
= dhcp_file
;
1937 new->sname
= dhcp_sname
;
1938 new->next_server
= dhcp_next_server
;
1940 new->next
= daemon
->boot_config
;
1941 daemon
->boot_config
= new;
1948 case LOPT_PXE_PROMT
: /* --pxe-prompt */
1950 struct dhcp_opt
*new = opt_malloc(sizeof(struct dhcp_opt
));
1954 new->opt
= 10; /* PXE_MENU_PROMPT */
1956 while (arg
&& strstr(arg
, "net:") == arg
)
1958 struct dhcp_netid
*nn
= opt_malloc(sizeof (struct dhcp_netid
));
1960 nn
->next
= new->netid
;
1962 nn
->net
= opt_string_alloc(arg
+4);
1972 new->len
= strlen(arg
) + 1;
1973 new->val
= opt_malloc(new->len
);
1974 memcpy(new->val
+ 1, arg
, new->len
- 1);
1976 new->u
.vendor_class
= (unsigned char *)"PXEClient";
1977 new->flags
= DHOPT_VENDOR
;
1979 if (comma
&& atoi_check(comma
, &timeout
))
1980 *(new->val
) = timeout
;
1984 new->next
= daemon
->dhcp_opts
;
1985 daemon
->dhcp_opts
= new;
1991 case LOPT_PXE_SERV
: /* --pxe-service */
1993 struct pxe_service
*new = opt_malloc(sizeof(struct pxe_service
));
1994 char *CSA
[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
1995 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL
};
1996 static int boottype
= 32768;
1999 new->server
.s_addr
= 0;
2001 while (arg
&& strstr(arg
, "net:") == arg
)
2003 struct dhcp_netid
*nn
= opt_malloc(sizeof (struct dhcp_netid
));
2005 nn
->next
= new->netid
;
2007 nn
->net
= opt_string_alloc(arg
+4);
2011 if (arg
&& (comma
= split(arg
)))
2013 for (i
= 0; CSA
[i
]; i
++)
2014 if (strcasecmp(CSA
[i
], arg
) == 0)
2017 if (CSA
[i
] || atoi_check(arg
, &i
))
2023 new->menu
= opt_string_alloc(arg
);
2029 if (atoi_check(arg
, &i
))
2032 new->basename
= NULL
;
2036 new->type
= boottype
++;
2037 new->basename
= opt_string_alloc(arg
);
2040 if (comma
&& (new->server
.s_addr
= inet_addr(comma
)) == (in_addr_t
)-1)
2045 if (!daemon
->pxe_services
)
2046 daemon
->pxe_services
= new;
2049 struct pxe_service
*s
;
2050 for (s
= daemon
->pxe_services
; s
->next
; s
= s
->next
);
2063 case '4': /* --dhcp-mac */
2065 if (!(comma
= split(arg
)))
2069 struct dhcp_mac
*new = opt_malloc(sizeof(struct dhcp_mac
));
2070 if (strstr(arg
, "net:") == arg
)
2071 new->netid
.net
= opt_string_alloc(arg
+4);
2073 new->netid
.net
= opt_string_alloc(arg
);
2074 unhide_metas(comma
);
2075 new->hwaddr_len
= parse_hex(comma
, new->hwaddr
, DHCP_CHADDR_MAX
, &new->mask
, &new->hwaddr_type
);
2076 new->next
= daemon
->dhcp_macs
;
2077 daemon
->dhcp_macs
= new;
2082 case 'U': /* --dhcp-vendorclass */
2083 case 'j': /* --dhcp-userclass */
2084 case LOPT_CIRCUIT
: /* --dhcp-circuitid */
2085 case LOPT_REMOTE
: /* --dhcp-remoteid */
2086 case LOPT_SUBSCR
: /* --dhcp-subscrid */
2088 if (!(comma
= split(arg
)))
2094 struct dhcp_vendor
*new = opt_malloc(sizeof(struct dhcp_vendor
));
2095 if (strstr(arg
, "net:") == arg
)
2096 new->netid
.net
= opt_string_alloc(arg
+4);
2098 new->netid
.net
= opt_string_alloc(arg
);
2099 /* check for hex string - must digits may include : must not have nothing else,
2100 only allowed for agent-options. */
2101 for (p
= comma
; *p
; p
++)
2102 if (isxdigit((int)*p
))
2106 unhide_metas(comma
);
2107 if (option
== 'U' || option
== 'j' || *p
|| !dig
)
2109 new->len
= strlen(comma
);
2110 new->data
= opt_malloc(new->len
);
2111 memcpy(new->data
, comma
, new->len
);
2115 new->len
= parse_hex(comma
, (unsigned char *)comma
, strlen(comma
), NULL
, NULL
);
2116 new->data
= opt_malloc(new->len
);
2117 memcpy(new->data
, comma
, new->len
);
2123 new->match_type
= MATCH_USER
;
2126 new->match_type
= MATCH_VENDOR
;
2129 new->match_type
= MATCH_CIRCUIT
;
2132 new->match_type
= MATCH_REMOTE
;
2135 new->match_type
= MATCH_SUBSCRIBER
;
2138 new->next
= daemon
->dhcp_vendors
;
2139 daemon
->dhcp_vendors
= new;
2144 case LOPT_ALTPORT
: /* --dhcp-alternate-port */
2147 daemon
->dhcp_server_port
= DHCP_SERVER_ALTPORT
;
2148 daemon
->dhcp_client_port
= DHCP_CLIENT_ALTPORT
;
2153 if (!atoi_check16(arg
, &daemon
->dhcp_server_port
) ||
2154 (comma
&& !atoi_check16(comma
, &daemon
->dhcp_client_port
)))
2155 problem
= _("invalid port number");
2157 daemon
->dhcp_client_port
= daemon
->dhcp_server_port
+1;
2161 case 'J': /* --dhcp-ignore */
2162 case LOPT_NO_NAMES
: /* --dhcp-ignore-names */
2163 case LOPT_BROADCAST
: /* --dhcp-broadcast */
2164 case '3': /* --bootp-dynamic */
2166 struct dhcp_netid_list
*new = opt_malloc(sizeof(struct dhcp_netid_list
));
2167 struct dhcp_netid
*list
= NULL
;
2170 new->next
= daemon
->dhcp_ignore
;
2171 daemon
->dhcp_ignore
= new;
2173 else if (option
== LOPT_BROADCAST
)
2175 new->next
= daemon
->force_broadcast
;
2176 daemon
->force_broadcast
= new;
2178 else if (option
== '3')
2180 new->next
= daemon
->bootp_dynamic
;
2181 daemon
->bootp_dynamic
= new;
2185 new->next
= daemon
->dhcp_ignore_names
;
2186 daemon
->dhcp_ignore_names
= new;
2190 struct dhcp_netid
*member
= opt_malloc(sizeof(struct dhcp_netid
));
2192 member
->next
= list
;
2194 if (strstr(arg
, "net:") == arg
)
2195 member
->net
= opt_string_alloc(arg
+4);
2197 member
->net
= opt_string_alloc(arg
);
2206 case 'V': /* --alias */
2208 char *dash
, *a
[3] = { NULL
, NULL
, NULL
};
2210 struct doctor
*new = opt_malloc(sizeof(struct doctor
));
2211 new->next
= daemon
->doctors
;
2212 daemon
->doctors
= new;
2213 new->mask
.s_addr
= 0xffffffff;
2214 new->end
.s_addr
= 0;
2217 for (k
= 1; k
< 3; k
++)
2219 if (!(a
[k
] = split(a
[k
-1])))
2224 dash
= split_chr(a
[0], '-');
2227 ((new->in
.s_addr
= inet_addr(a
[0])) == (in_addr_t
)-1) ||
2228 ((new->out
.s_addr
= inet_addr(a
[1])) == (in_addr_t
)-1))
2232 new->mask
.s_addr
= inet_addr(a
[2]);
2235 ((new->end
.s_addr
= inet_addr(dash
)) == (in_addr_t
)-1 ||
2236 !is_same_net(new->in
, new->end
, new->mask
) ||
2237 ntohl(new->in
.s_addr
) > ntohl(new->end
.s_addr
)))
2238 problem
= _("invalid alias range");
2243 case LOPT_INTNAME
: /* --interface-name */
2245 struct interface_name
*new, **up
;
2249 if (!comma
|| !canonicalise_opt(arg
))
2250 problem
= _("bad interface name");
2252 new = opt_malloc(sizeof(struct interface_name
));
2254 /* Add to the end of the list, so that first name
2255 of an interface is used for PTR lookups. */
2256 for (up
= &daemon
->int_names
; *up
; up
= &((*up
)->next
));
2258 new->name
= opt_string_alloc(arg
);
2259 new->intr
= opt_string_alloc(comma
);
2263 case LOPT_CNAME
: /* --cname */
2267 if (!(comma
= split(arg
)))
2271 for (new = daemon
->cnames
; new; new = new->next
)
2272 if (hostname_isequal(new->alias
, arg
))
2273 problem
= _("duplicate CNAME");
2274 new = opt_malloc(sizeof(struct cname
));
2275 new->next
= daemon
->cnames
;
2276 daemon
->cnames
= new;
2277 new->alias
= opt_string_alloc(arg
);
2278 new->target
= opt_string_alloc(comma
);
2283 case LOPT_PTR
: /* --ptr-record */
2285 struct ptr_record
*new;
2289 if (!canonicalise_opt(arg
))
2290 problem
= _("bad PTR record");
2292 new = opt_malloc(sizeof(struct ptr_record
));
2293 new->next
= daemon
->ptr
;
2295 new->name
= opt_string_alloc(arg
);
2298 new->ptr
= opt_string_alloc(comma
);
2302 case LOPT_NAPTR
: /* --naptr-record */
2304 char *a
[7] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
2310 for (k
= 1; k
< 7; k
++)
2311 if (!(a
[k
] = split(a
[k
-1])))
2316 !canonicalise_opt(a
[0]) ||
2317 !atoi_check16(a
[1], &order
) ||
2318 !atoi_check16(a
[2], &pref
) ||
2319 (k
== 7 && !canonicalise_opt(a
[6])))
2320 problem
= _("bad NAPTR record");
2323 new = opt_malloc(sizeof(struct naptr
));
2324 new->next
= daemon
->naptr
;
2325 daemon
->naptr
= new;
2326 new->name
= opt_string_alloc(a
[0]);
2327 new->flags
= opt_string_alloc(a
[3]);
2328 new->services
= opt_string_alloc(a
[4]);
2329 new->regexp
= opt_string_alloc(a
[5]);
2331 new->replace
= opt_string_alloc(a
[6]);
2338 case 'Y': /* --txt-record */
2340 struct txt_record
*new;
2341 unsigned char *p
, *q
;
2343 if ((comma
= split(arg
)))
2346 gen_prob
= _("TXT record string too long");
2348 if (!canonicalise_opt(arg
))
2350 problem
= _("bad TXT record");
2354 if ((q
= (unsigned char *)comma
))
2358 if ((p
= (unsigned char *)strchr((char*)q
+1, ',')))
2360 if ((len
= p
- q
- 1) > 255)
2363 for (q
= q
+1; q
< p
; q
++)
2364 *q
= unhide_meta(*q
);
2368 if ((len
= strlen((char *)q
+1)) > 255)
2371 for (q
= q
+1; *q
; q
++)
2372 *q
= unhide_meta(*q
);
2377 new = opt_malloc(sizeof(struct txt_record
));
2378 new->next
= daemon
->txt
;
2383 new->len
= q
- ((unsigned char *)comma
);
2384 new->txt
= opt_malloc(new->len
);
2385 memcpy(new->txt
, comma
, new->len
);
2389 static char empty
[] = "";
2394 /* ensure arg is terminated */
2397 new->name
= opt_string_alloc(arg
);
2401 case 'W': /* --srv-host */
2403 int port
= 1, priority
= 0, weight
= 0;
2404 char *name
, *target
= NULL
;
2405 struct mx_srv_record
*new;
2409 if (!canonicalise_opt(arg
))
2410 problem
= _("bad SRV record");
2412 name
= opt_string_alloc(arg
);
2418 if (!canonicalise_opt(arg
))
2419 problem
= _("bad SRV target");
2421 target
= opt_string_alloc(arg
);
2426 if (!atoi_check16(arg
, &port
))
2427 problem
= _("invalid port number");
2433 if (!atoi_check16(arg
, &priority
))
2434 problem
= _("invalid priority");
2440 if (!atoi_check16(arg
, &weight
))
2441 problem
= _("invalid weight");
2447 new = opt_malloc(sizeof(struct mx_srv_record
));
2448 new->next
= daemon
->mxnames
;
2449 daemon
->mxnames
= new;
2452 new->target
= target
;
2453 new->srvport
= port
;
2454 new->priority
= priority
;
2455 new->weight
= weight
;
2460 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
2473 static void one_file(char *file
, int nest
, int hard_opt
)
2475 volatile int lineno
= 0;
2478 char *p
, *arg
, *start
, *buff
= daemon
->namebuff
;
2479 static struct fileread
{
2482 struct fileread
*next
;
2483 } *filesread
= NULL
;
2484 struct stat statbuf
;
2486 /* ignore repeated files. */
2487 if (hard_opt
== 0 && stat(file
, &statbuf
) == 0)
2491 for (r
= filesread
; r
; r
= r
->next
)
2492 if (r
->dev
== statbuf
.st_dev
&& r
->ino
== statbuf
.st_ino
)
2495 r
= safe_malloc(sizeof(struct fileread
));
2496 r
->next
= filesread
;
2498 r
->dev
= statbuf
.st_dev
;
2499 r
->ino
= statbuf
.st_ino
;
2503 die(_("files nested too deep in %s"), file
, EC_BADCONF
);
2505 if (!(f
= fopen(file
, "r")))
2507 if (errno
== ENOENT
&& nest
== 0)
2508 return; /* No conffile, all done. */
2511 char *str
= _("cannot read %s: %s");
2514 my_syslog(LOG_ERR
, str
, file
, strerror(errno
));
2518 die(str
, file
, EC_FILE
);
2522 while (fgets(buff
, MAXDNAME
, f
))
2525 unsigned int lastquote
;
2528 /* Memory allocation failure longjmps here if mem_recover == 1 */
2531 if (setjmp(mem_jmp
))
2539 /* Implement quotes, inside quotes we allow \\ \" \n and \t
2540 metacharacters get hidden also strip comments */
2542 for (white
= 1, lastquote
= 0, p
= buff
; *p
; p
++)
2546 memmove(p
, p
+1, strlen(p
+1)+1);
2547 for(; *p
&& *p
!= '"'; p
++)
2549 if (*p
== '\\' && strchr("\"tnebr\\", p
[1]))
2553 else if (p
[1] == 'n')
2555 else if (p
[1] == 'b')
2557 else if (p
[1] == 'r')
2559 else if (p
[1] == 'e') /* escape */
2561 memmove(p
, p
+1, strlen(p
+1)+1);
2567 memmove(p
, p
+1, strlen(p
+1)+1);
2568 lastquote
= p
- buff
;
2572 errmess
= _("missing \"");
2577 if (white
&& *p
== '#')
2582 white
= isspace((int)unhide_meta(*p
));
2585 /* fgets gets end of line char too. */
2586 while (strlen(buff
) > lastquote
&& isspace((int)unhide_meta(buff
[strlen(buff
)-1])))
2587 buff
[strlen(buff
)-1] = 0;
2594 else if ((p
=strchr(buff
, '=')))
2596 /* allow spaces around "=" */
2598 for (; p
>= buff
&& (isspace((int)*p
) || *p
== '='); p
--)
2608 /* skip leading space */
2609 for (start
= buff
; *start
&& isspace((int)*start
); start
++);
2611 for (option
= 0, i
= 0; opts
[i
].name
; i
++)
2612 if (strcmp(opts
[i
].name
, start
) == 0)
2614 option
= opts
[i
].val
;
2619 errmess
= _("bad option");
2620 else if (opts
[i
].has_arg
== 0 && arg
)
2621 errmess
= _("extraneous parameter");
2622 else if (opts
[i
].has_arg
== 1 && !arg
)
2623 errmess
= _("missing parameter");
2629 for (; isspace((int)*arg
); arg
++);
2631 errmess
= one_opt(option
, arg
, _("error"), nest
+ 1);
2637 sprintf(buff
, _("%s at line %d of %%s"), errmess
, lineno
);
2639 my_syslog(LOG_ERR
, buff
, file
);
2641 die(buff
, file
, EC_BADCONF
);
2650 void reread_dhcp(void)
2652 if (daemon
->dhcp_hosts_file
)
2654 struct dhcp_config
*configs
, *cp
, **up
;
2656 /* remove existing... */
2657 for (up
= &daemon
->dhcp_conf
, configs
= daemon
->dhcp_conf
; configs
; configs
= cp
)
2661 if (configs
->flags
& CONFIG_BANK
)
2663 struct hwaddr_config
*mac
, *tmp
;
2665 for (mac
= configs
->hwaddr
; mac
; mac
= tmp
)
2670 if (configs
->flags
& CONFIG_CLID
)
2671 free(configs
->clid
);
2672 if (configs
->flags
& CONFIG_NETID
)
2673 free(configs
->netid
.net
);
2674 if (configs
->flags
& CONFIG_NAME
)
2675 free(configs
->hostname
);
2678 *up
= configs
->next
;
2682 up
= &configs
->next
;
2685 one_file(daemon
->dhcp_hosts_file
, 1, LOPT_BANK
);
2686 my_syslog(LOG_INFO
, _("read %s"), daemon
->dhcp_hosts_file
);
2689 if (daemon
->dhcp_opts_file
)
2691 struct dhcp_opt
*opts
, *cp
, **up
;
2692 struct dhcp_netid
*id
, *next
;
2694 for (up
= &daemon
->dhcp_opts
, opts
= daemon
->dhcp_opts
; opts
; opts
= cp
)
2698 if (opts
->flags
& DHOPT_BANK
)
2700 if ((opts
->flags
& DHOPT_VENDOR
))
2701 free(opts
->u
.vendor_class
);
2703 for (id
= opts
->netid
; id
; id
= next
)
2716 one_file(daemon
->dhcp_opts_file
, 1, LOPT_OPTS
);
2717 my_syslog(LOG_INFO
, _("read %s"), daemon
->dhcp_opts_file
);
2722 void read_opts(int argc
, char **argv
, char *compile_opts
)
2724 char *buff
= opt_malloc(MAXDNAME
);
2725 int option
, nest
= 0, testmode
= 0;
2726 char *errmess
, *arg
, *conffile
= CONFFILE
;
2730 daemon
= opt_malloc(sizeof(struct daemon
));
2731 memset(daemon
, 0, sizeof(struct daemon
));
2732 daemon
->namebuff
= buff
;
2734 /* Set defaults - everything else is zero or NULL */
2735 daemon
->cachesize
= CACHESIZ
;
2736 daemon
->ftabsize
= FTABSIZ
;
2737 daemon
->port
= NAMESERVER_PORT
;
2738 daemon
->dhcp_client_port
= DHCP_CLIENT_PORT
;
2739 daemon
->dhcp_server_port
= DHCP_SERVER_PORT
;
2740 daemon
->default_resolv
.is_default
= 1;
2741 daemon
->default_resolv
.name
= RESOLVFILE
;
2742 daemon
->resolv_files
= &daemon
->default_resolv
;
2743 daemon
->username
= CHUSER
;
2744 daemon
->runfile
= RUNFILE
;
2745 daemon
->dhcp_max
= MAXLEASES
;
2746 daemon
->tftp_max
= TFTP_MAX_CONNECTIONS
;
2747 daemon
->edns_pktsz
= EDNS_PKTSZ
;
2748 daemon
->log_fac
= -1;
2749 add_txt("version.bind", "dnsmasq-" VERSION
);
2750 add_txt("authors.bind", "Simon Kelley");
2751 add_txt("copyright.bind", COPYRIGHT
);
2755 #ifdef HAVE_GETOPT_LONG
2756 option
= getopt_long(argc
, argv
, OPTSTRING
, opts
, NULL
);
2758 option
= getopt(argc
, argv
, OPTSTRING
);
2764 /* Copy optarg so that argv doesn't get changed */
2767 strncpy(buff
, optarg
, MAXDNAME
);
2768 buff
[MAXDNAME
-1] = 0;
2774 /* command-line only stuff */
2775 if (option
== LOPT_TEST
)
2777 else if (option
== 'w')
2779 if (argc
!= 3 || strcmp(argv
[2], "dhcp") != 0)
2787 else if (option
== 'v')
2789 printf(_("Dnsmasq version %s %s\n"), VERSION
, COPYRIGHT
);
2790 printf(_("Compile time options %s\n\n"), compile_opts
);
2791 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
2792 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
2793 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
2796 else if (option
== 'C')
2798 conffile
= opt_string_alloc(arg
);
2803 #ifdef HAVE_GETOPT_LONG
2804 errmess
= one_opt(option
, arg
, _("try --help"), 0);
2806 errmess
= one_opt(option
, arg
, _("try -w"), 0);
2809 die(_("bad command line options: %s"), errmess
, EC_BADCONF
);
2814 one_file(conffile
, nest
, 0);
2816 /* port might not be known when the address is parsed - fill in here */
2817 if (daemon
->servers
)
2820 for (tmp
= daemon
->servers
; tmp
; tmp
= tmp
->next
)
2821 if (!(tmp
->flags
& SERV_HAS_SOURCE
))
2823 if (tmp
->source_addr
.sa
.sa_family
== AF_INET
)
2824 tmp
->source_addr
.in
.sin_port
= htons(daemon
->query_port
);
2826 else if (tmp
->source_addr
.sa
.sa_family
== AF_INET6
)
2827 tmp
->source_addr
.in6
.sin6_port
= htons(daemon
->query_port
);
2832 if (daemon
->if_addrs
)
2835 for(tmp
= daemon
->if_addrs
; tmp
; tmp
= tmp
->next
)
2836 if (tmp
->addr
.sa
.sa_family
== AF_INET
)
2837 tmp
->addr
.in
.sin_port
= htons(daemon
->port
);
2839 else if (tmp
->addr
.sa
.sa_family
== AF_INET6
)
2840 tmp
->addr
.in6
.sin6_port
= htons(daemon
->port
);
2844 /* only one of these need be specified: the other defaults to the host-name */
2845 if ((daemon
->options
& OPT_LOCALMX
) || daemon
->mxnames
|| daemon
->mxtarget
)
2847 struct mx_srv_record
*mx
;
2849 if (gethostname(buff
, MAXDNAME
) == -1)
2850 die(_("cannot get host-name: %s"), NULL
, EC_MISC
);
2852 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
2853 if (!mx
->issrv
&& hostname_isequal(mx
->name
, buff
))
2856 if ((daemon
->mxtarget
|| (daemon
->options
& OPT_LOCALMX
)) && !mx
)
2858 mx
= opt_malloc(sizeof(struct mx_srv_record
));
2859 mx
->next
= daemon
->mxnames
;
2862 mx
->name
= opt_string_alloc(buff
);
2863 daemon
->mxnames
= mx
;
2866 if (!daemon
->mxtarget
)
2867 daemon
->mxtarget
= opt_string_alloc(buff
);
2869 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
2870 if (!mx
->issrv
&& !mx
->target
)
2871 mx
->target
= daemon
->mxtarget
;
2874 if (!(daemon
->options
& OPT_NO_RESOLV
) &&
2875 daemon
->resolv_files
&&
2876 daemon
->resolv_files
->next
&&
2877 (daemon
->options
& OPT_NO_POLL
))
2878 die(_("only one resolv.conf file allowed in no-poll mode."), NULL
, EC_BADCONF
);
2880 if (daemon
->options
& OPT_RESOLV_DOMAIN
)
2885 if ((daemon
->options
& OPT_NO_RESOLV
) ||
2886 !daemon
->resolv_files
||
2887 (daemon
->resolv_files
)->next
)
2888 die(_("must have exactly one resolv.conf to read domain from."), NULL
, EC_BADCONF
);
2890 if (!(f
= fopen((daemon
->resolv_files
)->name
, "r")))
2891 die(_("failed to read %s: %s"), (daemon
->resolv_files
)->name
, EC_FILE
);
2893 while ((line
= fgets(buff
, MAXDNAME
, f
)))
2895 char *token
= strtok(line
, " \t\n\r");
2897 if (!token
|| strcmp(token
, "search") != 0)
2900 if ((token
= strtok(NULL
, " \t\n\r")) &&
2901 canonicalise_opt(token
) &&
2902 (daemon
->domain_suffix
= opt_string_alloc(token
)))
2908 if (!daemon
->domain_suffix
)
2909 die(_("no search directive found in %s"), (daemon
->resolv_files
)->name
, EC_MISC
);
2912 if (daemon
->domain_suffix
)
2914 /* add domain for any srv record without one. */
2915 struct mx_srv_record
*srv
;
2917 for (srv
= daemon
->mxnames
; srv
; srv
= srv
->next
)
2919 strchr(srv
->name
, '.') &&
2920 strchr(srv
->name
, '.') == strrchr(srv
->name
, '.'))
2922 strcpy(buff
, srv
->name
);
2924 strcat(buff
, daemon
->domain_suffix
);
2926 srv
->name
= opt_string_alloc(buff
);
2929 else if (daemon
->options
& OPT_DHCP_FQDN
)
2930 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL
, EC_BADCONF
);
2934 fprintf(stderr
, "dnsmasq: %s.\n", _("syntax check OK"));