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