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