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 106 #ifdef HAVE_GETOPT_LONG 107 static const struct option opts[] = 108 #else 109 static 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 221 static 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 336 static 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 413 char *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 445 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,."; 446 447 static 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 458 static 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 468 static void unhide_metas(char *cp) 469 { 470 if (cp) 471 for(; *cp; cp++) 472 *cp = unhide_meta(*cp); 473 } 474 475 static 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 491 static 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 511 static 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 529 static char *split(char *s) 530 { 531 return split_chr(s, ','); 532 } 533 534 static 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 554 static 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 571 static 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 581 static 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 596 static 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 654 static 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 */ 666 static 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 978 static 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 && 1356 parse_addr(AF_INET, arg, &new->addr) != 0 && 1357 parse_addr(AF_INET6, arg, &new->addr) != 0) 1358 { 1359 option = '?'; /* error */ 1360 break; 1361 } 1362 1363 daemon->if_addrs = new; 1364 arg = comma; 1365 } while (arg); 1366 break; 1367 1368 case 'S': /* --server */ 1369 case LOPT_LOCAL: /* --local */ 1370 case 'A': /* --address */ 1371 { 1372 struct server *serv, *newlist = NULL; 1373 1374 unhide_metas(arg); 1375 1376 if (arg && *arg == '/') 1377 { 1378 char *end; 1379 arg++; 1380 while ((end = split_chr(arg, '/'))) 1381 { 1382 char *domain = NULL; 1383 /* # matches everything and becomes a zero length domain string */ 1384 if (strcmp(arg, "#") == 0) 1385 domain = ""; 1386 else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg))) 1387 option = '?'; 1388 serv = opt_malloc(sizeof(struct server)); 1389 memset(serv, 0, sizeof(struct server)); 1390 serv->next = newlist; 1391 newlist = serv; 1392 serv->domain = domain; 1393 serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS; 1394 arg = end; 1395 } 1396 if (!newlist) 1397 { 1398 option = '?'; 1399 break; 1400 } 1401 1402 } 1403 else 1404 { 1405 newlist = opt_malloc(sizeof(struct server)); 1406 memset(newlist, 0, sizeof(struct server)); 1407 } 1408 1409 if (option == 'A') 1410 { 1411 newlist->flags |= SERV_LITERAL_ADDRESS; 1412 if (!(newlist->flags & SERV_TYPE)) 1413 option = '?'; 1414 } 1415 1416 if (!arg || !*arg) 1417 { 1418 newlist->flags |= SERV_NO_ADDR; /* no server */ 1419 if (newlist->flags & SERV_LITERAL_ADDRESS) 1420 option = '?'; 1421 } 1422 else 1423 { 1424 int source_port = 0, serv_port = NAMESERVER_PORT; 1425 char *portno, *source; 1426 1427 if ((source = split_chr(arg, '@')) && /* is there a source. */ 1428 (portno = split_chr(source, '#')) && 1429 !atoi_check16(portno, &source_port)) 1430 problem = _("bad port"); 1431 1432 if ((portno = split_chr(arg, '#')) && /* is there a port no. */ 1433 !atoi_check16(portno, &serv_port)) 1434 problem = _("bad port"); 1435 1436 if (parse_addr(AF_INET, arg, &newlist->addr) == 0) 1437 { 1438 newlist->addr.in.sin_port = htons(serv_port); 1439 #ifdef HAVE_SOCKADDR_SA_LEN 1440 newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in); 1441 #endif 1442 if (source) 1443 { 1444 newlist->flags |= SERV_HAS_SOURCE; 1445 if (parse_addr(AF_INET, source, &newlist->addr) != 0) 1446 { 1447 #if defined(SO_BINDTODEVICE) 1448 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY; 1449 strncpy(newlist->interface, source, IF_NAMESIZE); 1450 #else 1451 problem = _("interface binding not supported"); 1452 #endif 1453 } 1454 } 1455 else 1456 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY; 1457 1458 newlist->source_addr.in.sin_port = htons(source_port); 1459 newlist->source_addr.sa.sa_family = AF_INET; 1460 } 1461 #ifdef HAVE_IPV6 1462 else if (parse_addr(AF_INET6, arg, &newlist->addr) == 0) 1463 { 1464 newlist->addr.in6.sin6_port = htons(serv_port); 1465 if (source) 1466 { 1467 newlist->flags |= SERV_HAS_SOURCE; 1468 if (parse_addr(AF_INET6, source, &newlist->source_addr) != 0) 1469 { 1470 #if defined(SO_BINDTODEVICE) 1471 newlist->source_addr.in6.sin6_addr = in6addr_any; 1472 strncpy(newlist->interface, source, IF_NAMESIZE); 1473 #else 1474 problem = _("interface binding not supported"); 1475 #endif 1476 } 1477 } 1478 else 1479 newlist->source_addr.in6.sin6_addr = in6addr_any; 1480 1481 newlist->source_addr.in6.sin6_port = htons(source_port); 1482 newlist->source_addr.sa.sa_family = AF_INET6; 1483 } 1484 #endif 1485 else 1486 option = '?'; /* error */ 1487 1488 } 1489 1490 serv = newlist; 1491 while (serv->next) 1492 { 1493 serv->next->flags = serv->flags; 1494 serv->next->addr = serv->addr; 1495 serv->next->source_addr = serv->source_addr; 1496 serv = serv->next; 1497 } 1498 serv->next = daemon->servers; 1499 daemon->servers = newlist; 1500 break; 1501 } 1502 1503 case 'c': /* --cache-size */ 1504 { 1505 int size; 1506 1507 if (!atoi_check(arg, &size)) 1508 option = '?'; 1509 else 1510 { 1511 /* zero is OK, and means no caching. */ 1512 1513 if (size < 0) 1514 size = 0; 1515 else if (size > 10000) 1516 size = 10000; 1517 1518 daemon->cachesize = size; 1519 } 1520 break; 1521 } 1522 1523 case 'p': /* --port */ 1524 if (!atoi_check16(arg, &daemon->port)) 1525 option = '?'; 1526 break; 1527 1528 case LOPT_MINPORT: /* --min-port */ 1529 if (!atoi_check16(arg, &daemon->min_port)) 1530 option = '?'; 1531 break; 1532 1533 case '0': /* --dns-forward-max */ 1534 if (!atoi_check(arg, &daemon->ftabsize)) 1535 option = '?'; 1536 break; 1537 1538 case LOPT_MAX_LOGS: /* --log-async */ 1539 daemon->max_logs = LOG_MAX; /* default */ 1540 if (arg && !atoi_check(arg, &daemon->max_logs)) 1541 option = '?'; 1542 else if (daemon->max_logs > 100) 1543 daemon->max_logs = 100; 1544 break; 1545 1546 case 'P': /* --edns-packet-max */ 1547 { 1548 int i; 1549 if (!atoi_check(arg, &i)) 1550 option = '?'; 1551 daemon->edns_pktsz = (unsigned short)i; 1552 break; 1553 } 1554 1555 case 'Q': /* --query-port */ 1556 if (!atoi_check16(arg, &daemon->query_port)) 1557 option = '?'; 1558 /* if explicitly set to zero, use single OS ephemeral port 1559 and disable random ports */ 1560 if (daemon->query_port == 0) 1561 daemon->osport = 1; 1562 break; 1563 1564 case 'T': /* --local-ttl */ 1565 case LOPT_NEGTTL: /* --neg-ttl */ 1566 { 1567 int ttl; 1568 if (!atoi_check(arg, &ttl)) 1569 option = '?'; 1570 else if (option == LOPT_NEGTTL) 1571 daemon->neg_ttl = (unsigned long)ttl; 1572 else 1573 daemon->local_ttl = (unsigned long)ttl; 1574 break; 1575 } 1576 1577 #ifdef HAVE_DHCP 1578 case 'X': /* --dhcp-lease-max */ 1579 if (!atoi_check(arg, &daemon->dhcp_max)) 1580 option = '?'; 1581 break; 1582 #endif 1583 1584 #ifdef HAVE_TFTP 1585 case LOPT_TFTP_MAX: /* --tftp-max */ 1586 if (!atoi_check(arg, &daemon->tftp_max)) 1587 option = '?'; 1588 break; 1589 1590 case LOPT_PREFIX: /* --tftp-prefix */ 1591 daemon->tftp_prefix = opt_string_alloc(arg); 1592 break; 1593 1594 case LOPT_TFTPPORTS: /* --tftp-port-range */ 1595 if (!(comma = split(arg)) || 1596 !atoi_check16(arg, &daemon->start_tftp_port) || 1597 !atoi_check16(comma, &daemon->end_tftp_port)) 1598 problem = _("bad port range"); 1599 1600 if (daemon->start_tftp_port > daemon->end_tftp_port) 1601 { 1602 int tmp = daemon->start_tftp_port; 1603 daemon->start_tftp_port = daemon->end_tftp_port; 1604 daemon->end_tftp_port = tmp; 1605 } 1606 1607 break; 1608 #endif 1609 1610 case LOPT_BRIDGE: /* --bridge-interface */ 1611 { 1612 struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge)); 1613 if (!(comma = split(arg))) 1614 { 1615 problem = _("bad bridge-interface"); 1616 break; 1617 } 1618 1619 strncpy(new->iface, arg, IF_NAMESIZE); 1620 new->alias = NULL; 1621 new->next = daemon->bridges; 1622 daemon->bridges = new; 1623 1624 do { 1625 arg = comma; 1626 comma = split(arg); 1627 if (strlen(arg) != 0) 1628 { 1629 struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge)); 1630 b->next = new->alias; 1631 new->alias = b; 1632 strncpy(b->iface, arg, IF_NAMESIZE); 1633 } 1634 } while (comma); 1635 1636 break; 1637 } 1638 1639 #ifdef HAVE_DHCP 1640 case 'F': /* --dhcp-range */ 1641 { 1642 int k, leasepos = 2; 1643 char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL }; 1644 struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context)); 1645 1646 new->next = daemon->dhcp; 1647 new->lease_time = DEFLEASE; 1648 new->addr_epoch = 0; 1649 new->netmask.s_addr = 0; 1650 new->broadcast.s_addr = 0; 1651 new->router.s_addr = 0; 1652 new->netid.net = NULL; 1653 new->filter = NULL; 1654 new->flags = 0; 1655 1656 gen_prob = _("bad dhcp-range"); 1657 1658 if (!arg) 1659 { 1660 option = '?'; 1661 break; 1662 } 1663 1664 while(1) 1665 { 1666 for (cp = arg; *cp; cp++) 1667 if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9'))) 1668 break; 1669 1670 if (*cp != ',' && (comma = split(arg))) 1671 { 1672 if (strstr(arg, "net:") == arg) 1673 { 1674 struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid)); 1675 tt->net = opt_string_alloc(arg+4); 1676 tt->next = new->filter; 1677 new->filter = tt; 1678 } 1679 else 1680 { 1681 if (new->netid.net) 1682 problem = _("only one netid tag allowed"); 1683 else 1684 new->netid.net = opt_string_alloc(arg); 1685 } 1686 arg = comma; 1687 } 1688 else 1689 { 1690 a[0] = arg; 1691 break; 1692 } 1693 } 1694 1695 for (k = 1; k < 5; k++) 1696 if (!(a[k] = split(a[k-1]))) 1697 break; 1698 1699 if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1)) 1700 option = '?'; 1701 else if (strcmp(a[1], "static") == 0) 1702 { 1703 new->end = new->start; 1704 new->flags |= CONTEXT_STATIC; 1705 } 1706 else if (strcmp(a[1], "proxy") == 0) 1707 { 1708 new->end = new->start; 1709 new->flags |= CONTEXT_PROXY; 1710 } 1711 else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1) 1712 option = '?'; 1713 1714 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) 1715 { 1716 struct in_addr tmp = new->start; 1717 new->start = new->end; 1718 new->end = tmp; 1719 } 1720 1721 if (option != '?' && k >= 3 && strchr(a[2], '.') && 1722 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1)) 1723 { 1724 new->flags |= CONTEXT_NETMASK; 1725 leasepos = 3; 1726 if (!is_same_net(new->start, new->end, new->netmask)) 1727 problem = _("inconsistent DHCP range"); 1728 } 1729 daemon->dhcp = new; 1730 1731 if (k >= 4 && strchr(a[3], '.') && 1732 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1)) 1733 { 1734 new->flags |= CONTEXT_BRDCAST; 1735 leasepos = 4; 1736 } 1737 1738 if (k >= leasepos+1) 1739 { 1740 if (strcmp(a[leasepos], "infinite") == 0) 1741 new->lease_time = 0xffffffff; 1742 else 1743 { 1744 int fac = 1; 1745 if (strlen(a[leasepos]) > 0) 1746 { 1747 switch (a[leasepos][strlen(a[leasepos]) - 1]) 1748 { 1749 case 'd': 1750 case 'D': 1751 fac *= 24; 1752 /* fall though */ 1753 case 'h': 1754 case 'H': 1755 fac *= 60; 1756 /* fall through */ 1757 case 'm': 1758 case 'M': 1759 fac *= 60; 1760 /* fall through */ 1761 case 's': 1762 case 'S': 1763 a[leasepos][strlen(a[leasepos]) - 1] = 0; 1764 } 1765 1766 new->lease_time = atoi(a[leasepos]) * fac; 1767 /* Leases of a minute or less confuse 1768 some clients, notably Apple's */ 1769 if (new->lease_time < 120) 1770 new->lease_time = 120; 1771 } 1772 } 1773 } 1774 break; 1775 } 1776 1777 case LOPT_BANK: 1778 case 'G': /* --dhcp-host */ 1779 { 1780 int j, k = 0; 1781 char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; 1782 struct dhcp_config *new; 1783 struct in_addr in; 1784 1785 new = opt_malloc(sizeof(struct dhcp_config)); 1786 1787 new->next = daemon->dhcp_conf; 1788 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0; 1789 new->hwaddr = NULL; 1790 1791 if ((a[0] = arg)) 1792 for (k = 1; k < 6; k++) 1793 if (!(a[k] = split(a[k-1]))) 1794 break; 1795 1796 for (j = 0; j < k; j++) 1797 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */ 1798 { 1799 char *arg = a[j]; 1800 1801 if ((arg[0] == 'i' || arg[0] == 'I') && 1802 (arg[1] == 'd' || arg[1] == 'D') && 1803 arg[2] == ':') 1804 { 1805 if (arg[3] == '*') 1806 new->flags |= CONFIG_NOCLID; 1807 else 1808 { 1809 int len; 1810 arg += 3; /* dump id: */ 1811 if (strchr(arg, ':')) 1812 len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL); 1813 else 1814 { 1815 unhide_metas(arg); 1816 len = (int) strlen(arg); 1817 } 1818 1819 if ((new->clid = opt_malloc(len))) 1820 { 1821 new->flags |= CONFIG_CLID; 1822 new->clid_len = len; 1823 memcpy(new->clid, arg, len); 1824 } 1825 } 1826 } 1827 else if (strstr(arg, "net:") == arg) 1828 { 1829 int len = strlen(arg + 4) + 1; 1830 if ((new->netid.net = opt_malloc(len))) 1831 { 1832 new->flags |= CONFIG_NETID; 1833 strcpy(new->netid.net, arg+4); 1834 unhide_metas(new->netid.net); 1835 } 1836 } 1837 else 1838 { 1839 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config)); 1840 newhw->next = new->hwaddr; 1841 new->hwaddr = newhw; 1842 newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX, 1843 &newhw->wildcard_mask, &newhw->hwaddr_type); 1844 } 1845 } 1846 else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1) 1847 { 1848 new->addr = in; 1849 new->flags |= CONFIG_ADDR; 1850 } 1851 else 1852 { 1853 char *cp, *lastp = NULL, last = 0; 1854 int fac = 1; 1855 1856 if (strlen(a[j]) > 1) 1857 { 1858 lastp = a[j] + strlen(a[j]) - 1; 1859 last = *lastp; 1860 switch (last) 1861 { 1862 case 'd': 1863 case 'D': 1864 fac *= 24; 1865 /* fall through */ 1866 case 'h': 1867 case 'H': 1868 fac *= 60; 1869 /* fall through */ 1870 case 'm': 1871 case 'M': 1872 fac *= 60; 1873 /* fall through */ 1874 case 's': 1875 case 'S': 1876 *lastp = 0; 1877 } 1878 } 1879 1880 for (cp = a[j]; *cp; cp++) 1881 if (!isdigit((int)*cp) && *cp != ' ') 1882 break; 1883 1884 if (*cp) 1885 { 1886 if (lastp) 1887 *lastp = last; 1888 if (strcmp(a[j], "infinite") == 0) 1889 { 1890 new->lease_time = 0xffffffff; 1891 new->flags |= CONFIG_TIME; 1892 } 1893 else if (strcmp(a[j], "ignore") == 0) 1894 new->flags |= CONFIG_DISABLE; 1895 else 1896 { 1897 if (!(new->hostname = canonicalise_opt(a[j])) || 1898 !legal_hostname(new->hostname)) 1899 problem = _("bad DHCP host name"); 1900 else 1901 new->flags |= CONFIG_NAME; 1902 new->domain = NULL; 1903 } 1904 } 1905 else 1906 { 1907 new->lease_time = atoi(a[j]) * fac; 1908 /* Leases of a minute or less confuse 1909 some clients, notably Apple's */ 1910 if (new->lease_time < 120) 1911 new->lease_time = 120; 1912 new->flags |= CONFIG_TIME; 1913 } 1914 } 1915 1916 daemon->dhcp_conf = new; 1917 break; 1918 } 1919 1920 case 'O': /* --dhcp-option */ 1921 case LOPT_FORCE: /* --dhcp-option-force */ 1922 case LOPT_OPTS: 1923 case LOPT_MATCH: /* --dhcp-match */ 1924 problem = parse_dhcp_opt(arg, 1925 option == LOPT_FORCE ? DHOPT_FORCE : 1926 (option == LOPT_MATCH ? DHOPT_MATCH : 1927 (option == LOPT_OPTS ? DHOPT_BANK : 0))); 1928 break; 1929 1930 case 'M': /* --dhcp-boot */ 1931 { 1932 struct dhcp_netid *id = NULL; 1933 while (arg && strstr(arg, "net:") == arg) 1934 { 1935 struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid)); 1936 newid->next = id; 1937 id = newid; 1938 comma = split(arg); 1939 newid->net = opt_string_alloc(arg+4); 1940 arg = comma; 1941 }; 1942 1943 if (!arg) 1944 option = '?'; 1945 else 1946 { 1947 char *dhcp_file, *dhcp_sname = NULL; 1948 struct in_addr dhcp_next_server; 1949 comma = split(arg); 1950 dhcp_file = opt_string_alloc(arg); 1951 dhcp_next_server.s_addr = 0; 1952 if (comma) 1953 { 1954 arg = comma; 1955 comma = split(arg); 1956 dhcp_sname = opt_string_alloc(arg); 1957 if (comma) 1958 { 1959 unhide_metas(comma); 1960 if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) 1961 option = '?'; 1962 } 1963 } 1964 if (option != '?') 1965 { 1966 struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot)); 1967 new->file = dhcp_file; 1968 new->sname = dhcp_sname; 1969 new->next_server = dhcp_next_server; 1970 new->netid = id; 1971 new->next = daemon->boot_config; 1972 daemon->boot_config = new; 1973 } 1974 } 1975 1976 break; 1977 } 1978 1979 case LOPT_PXE_PROMT: /* --pxe-prompt */ 1980 { 1981 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt)); 1982 int timeout; 1983 1984 new->netid = NULL; 1985 new->opt = 10; /* PXE_MENU_PROMPT */ 1986 1987 while (arg && strstr(arg, "net:") == arg) 1988 { 1989 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); 1990 comma = split(arg); 1991 nn->next = new->netid; 1992 new->netid = nn; 1993 nn->net = opt_string_alloc(arg+4); 1994 arg = comma; 1995 } 1996 1997 if (!arg) 1998 option = '?'; 1999 else 2000 { 2001 comma = split(arg); 2002 unhide_metas(arg); 2003 new->len = strlen(arg) + 1; 2004 new->val = opt_malloc(new->len); 2005 memcpy(new->val + 1, arg, new->len - 1); 2006 2007 new->u.vendor_class = (unsigned char *)"PXEClient"; 2008 new->flags = DHOPT_VENDOR; 2009 2010 if (comma && atoi_check(comma, &timeout)) 2011 *(new->val) = timeout; 2012 else 2013 *(new->val) = 255; 2014 2015 new->next = daemon->dhcp_opts; 2016 daemon->dhcp_opts = new; 2017 daemon->enable_pxe = 1; 2018 } 2019 2020 break; 2021 } 2022 2023 case LOPT_PXE_SERV: /* --pxe-service */ 2024 { 2025 struct pxe_service *new = opt_malloc(sizeof(struct pxe_service)); 2026 char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client", 2027 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL }; 2028 static int boottype = 32768; 2029 2030 new->netid = NULL; 2031 new->server.s_addr = 0; 2032 2033 while (arg && strstr(arg, "net:") == arg) 2034 { 2035 struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); 2036 comma = split(arg); 2037 nn->next = new->netid; 2038 new->netid = nn; 2039 nn->net = opt_string_alloc(arg+4); 2040 arg = comma; 2041 } 2042 2043 if (arg && (comma = split(arg))) 2044 { 2045 for (i = 0; CSA[i]; i++) 2046 if (strcasecmp(CSA[i], arg) == 0) 2047 break; 2048 2049 if (CSA[i] || atoi_check(arg, &i)) 2050 { 2051 arg = comma; 2052 comma = split(arg); 2053 2054 new->CSA = i; 2055 new->menu = opt_string_alloc(arg); 2056 2057 if (comma) 2058 { 2059 arg = comma; 2060 comma = split(arg); 2061 if (atoi_check(arg, &i)) 2062 { 2063 new->type = i; 2064 new->basename = NULL; 2065 } 2066 else 2067 { 2068 new->type = boottype++; 2069 new->basename = opt_string_alloc(arg); 2070 } 2071 2072 if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1) 2073 option = '?'; 2074 2075 /* Order matters */ 2076 new->next = NULL; 2077 if (!daemon->pxe_services) 2078 daemon->pxe_services = new; 2079 else 2080 { 2081 struct pxe_service *s; 2082 for (s = daemon->pxe_services; s->next; s = s->next); 2083 s->next = new; 2084 } 2085 2086 daemon->enable_pxe = 1; 2087 break; 2088 } 2089 } 2090 } 2091 2092 option = '?'; 2093 break; 2094 } 2095 2096 case '4': /* --dhcp-mac */ 2097 { 2098 if (!(comma = split(arg))) 2099 option = '?'; 2100 else 2101 { 2102 struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac)); 2103 if (strstr(arg, "net:") == arg) 2104 new->netid.net = opt_string_alloc(arg+4); 2105 else 2106 new->netid.net = opt_string_alloc(arg); 2107 unhide_metas(comma); 2108 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type); 2109 new->next = daemon->dhcp_macs; 2110 daemon->dhcp_macs = new; 2111 } 2112 } 2113 break; 2114 2115 case 'U': /* --dhcp-vendorclass */ 2116 case 'j': /* --dhcp-userclass */ 2117 case LOPT_CIRCUIT: /* --dhcp-circuitid */ 2118 case LOPT_REMOTE: /* --dhcp-remoteid */ 2119 case LOPT_SUBSCR: /* --dhcp-subscrid */ 2120 { 2121 if (!(comma = split(arg))) 2122 option = '?'; 2123 else 2124 { 2125 char *p; 2126 int dig = 0; 2127 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor)); 2128 if (strstr(arg, "net:") == arg) 2129 new->netid.net = opt_string_alloc(arg+4); 2130 else 2131 new->netid.net = opt_string_alloc(arg); 2132 /* check for hex string - must digits may include : must not have nothing else, 2133 only allowed for agent-options. */ 2134 for (p = comma; *p; p++) 2135 if (isxdigit((int)*p)) 2136 dig = 1; 2137 else if (*p != ':') 2138 break; 2139 unhide_metas(comma); 2140 if (option == 'U' || option == 'j' || *p || !dig) 2141 { 2142 new->len = strlen(comma); 2143 new->data = opt_malloc(new->len); 2144 memcpy(new->data, comma, new->len); 2145 } 2146 else 2147 { 2148 new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL); 2149 new->data = opt_malloc(new->len); 2150 memcpy(new->data, comma, new->len); 2151 } 2152 2153 switch (option) 2154 { 2155 case 'j': 2156 new->match_type = MATCH_USER; 2157 break; 2158 case 'U': 2159 new->match_type = MATCH_VENDOR; 2160 break; 2161 case LOPT_CIRCUIT: 2162 new->match_type = MATCH_CIRCUIT; 2163 break; 2164 case LOPT_REMOTE: 2165 new->match_type = MATCH_REMOTE; 2166 break; 2167 case LOPT_SUBSCR: 2168 new->match_type = MATCH_SUBSCRIBER; 2169 break; 2170 } 2171 new->next = daemon->dhcp_vendors; 2172 daemon->dhcp_vendors = new; 2173 } 2174 break; 2175 } 2176 2177 case LOPT_ALTPORT: /* --dhcp-alternate-port */ 2178 if (!arg) 2179 { 2180 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT; 2181 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT; 2182 } 2183 else 2184 { 2185 comma = split(arg); 2186 if (!atoi_check16(arg, &daemon->dhcp_server_port) || 2187 (comma && !atoi_check16(comma, &daemon->dhcp_client_port))) 2188 problem = _("invalid port number"); 2189 if (!comma) 2190 daemon->dhcp_client_port = daemon->dhcp_server_port+1; 2191 } 2192 break; 2193 2194 case 'J': /* --dhcp-ignore */ 2195 case LOPT_NO_NAMES: /* --dhcp-ignore-names */ 2196 case LOPT_BROADCAST: /* --dhcp-broadcast */ 2197 case '3': /* --bootp-dynamic */ 2198 { 2199 struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list)); 2200 struct dhcp_netid *list = NULL; 2201 if (option == 'J') 2202 { 2203 new->next = daemon->dhcp_ignore; 2204 daemon->dhcp_ignore = new; 2205 } 2206 else if (option == LOPT_BROADCAST) 2207 { 2208 new->next = daemon->force_broadcast; 2209 daemon->force_broadcast = new; 2210 } 2211 else if (option == '3') 2212 { 2213 new->next = daemon->bootp_dynamic; 2214 daemon->bootp_dynamic = new; 2215 } 2216 else 2217 { 2218 new->next = daemon->dhcp_ignore_names; 2219 daemon->dhcp_ignore_names = new; 2220 } 2221 2222 while (arg) { 2223 struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid)); 2224 comma = split(arg); 2225 member->next = list; 2226 list = member; 2227 if (strstr(arg, "net:") == arg) 2228 member->net = opt_string_alloc(arg+4); 2229 else 2230 member->net = opt_string_alloc(arg); 2231 arg = comma; 2232 } 2233 2234 new->list = list; 2235 break; 2236 } 2237 #endif 2238 2239 case 'V': /* --alias */ 2240 { 2241 char *dash, *a[3] = { NULL, NULL, NULL }; 2242 int k = 0; 2243 struct doctor *new = opt_malloc(sizeof(struct doctor)); 2244 new->next = daemon->doctors; 2245 daemon->doctors = new; 2246 new->mask.s_addr = 0xffffffff; 2247 new->end.s_addr = 0; 2248 2249 if ((a[0] = arg)) 2250 for (k = 1; k < 3; k++) 2251 { 2252 if (!(a[k] = split(a[k-1]))) 2253 break; 2254 unhide_metas(a[k]); 2255 } 2256 2257 dash = split_chr(a[0], '-'); 2258 2259 if ((k < 2) || 2260 ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) || 2261 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1)) 2262 option = '?'; 2263 2264 if (k == 3) 2265 new->mask.s_addr = inet_addr(a[2]); 2266 2267 if (dash && 2268 ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 || 2269 !is_same_net(new->in, new->end, new->mask) || 2270 ntohl(new->in.s_addr) > ntohl(new->end.s_addr))) 2271 problem = _("invalid alias range"); 2272 2273 break; 2274 } 2275 2276 case LOPT_INTNAME: /* --interface-name */ 2277 { 2278 struct interface_name *new, **up; 2279 char *domain = NULL; 2280 2281 comma = split(arg); 2282 2283 if (!comma || !(domain = canonicalise_opt(arg))) 2284 problem = _("bad interface name"); 2285 2286 new = opt_malloc(sizeof(struct interface_name)); 2287 new->next = NULL; 2288 /* Add to the end of the list, so that first name 2289 of an interface is used for PTR lookups. */ 2290 for (up = &daemon->int_names; *up; up = &((*up)->next)); 2291 *up = new; 2292 new->name = domain; 2293 new->intr = opt_string_alloc(comma); 2294 break; 2295 } 2296 2297 case LOPT_CNAME: /* --cname */ 2298 { 2299 struct cname *new; 2300 2301 if (!(comma = split(arg))) 2302 option = '?'; 2303 else 2304 { 2305 char *alias = canonicalise_opt(arg); 2306 char *target = canonicalise_opt(comma); 2307 2308 if (!alias || !target) 2309 problem = _("bad CNAME"); 2310 else 2311 { 2312 for (new = daemon->cnames; new; new = new->next) 2313 if (hostname_isequal(new->alias, arg)) 2314 problem = _("duplicate CNAME"); 2315 new = opt_malloc(sizeof(struct cname)); 2316 new->next = daemon->cnames; 2317 daemon->cnames = new; 2318 new->alias = alias; 2319 new->target = target; 2320 } 2321 } 2322 break; 2323 } 2324 2325 case LOPT_PTR: /* --ptr-record */ 2326 { 2327 struct ptr_record *new; 2328 char *dom, *target = NULL; 2329 2330 comma = split(arg); 2331 2332 if (!(dom = canonicalise_opt(arg)) || 2333 (comma && !(target = canonicalise_opt(comma)))) 2334 problem = _("bad PTR record"); 2335 else 2336 { 2337 new = opt_malloc(sizeof(struct ptr_record)); 2338 new->next = daemon->ptr; 2339 daemon->ptr = new; 2340 new->name = dom; 2341 new->ptr = target; 2342 } 2343 break; 2344 } 2345 2346 case LOPT_NAPTR: /* --naptr-record */ 2347 { 2348 char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; 2349 int k = 0; 2350 struct naptr *new; 2351 int order, pref; 2352 char *name, *replace = NULL; 2353 2354 if ((a[0] = arg)) 2355 for (k = 1; k < 7; k++) 2356 if (!(a[k] = split(a[k-1]))) 2357 break; 2358 2359 2360 if (k < 6 || 2361 !(name = canonicalise_opt(a[0])) || 2362 !atoi_check16(a[1], &order) || 2363 !atoi_check16(a[2], &pref) || 2364 (k == 7 && !(replace = canonicalise_opt(a[6])))) 2365 problem = _("bad NAPTR record"); 2366 else 2367 { 2368 new = opt_malloc(sizeof(struct naptr)); 2369 new->next = daemon->naptr; 2370 daemon->naptr = new; 2371 new->name = name; 2372 new->flags = opt_string_alloc(a[3]); 2373 new->services = opt_string_alloc(a[4]); 2374 new->regexp = opt_string_alloc(a[5]); 2375 new->replace = replace; 2376 new->order = order; 2377 new->pref = pref; 2378 } 2379 break; 2380 } 2381 2382 case 'Y': /* --txt-record */ 2383 { 2384 struct txt_record *new; 2385 unsigned char *p, *q; 2386 2387 if ((comma = split(arg))) 2388 comma--; 2389 2390 gen_prob = _("TXT record string too long"); 2391 2392 if ((q = (unsigned char *)comma)) 2393 while (1) 2394 { 2395 size_t len; 2396 if ((p = (unsigned char *)strchr((char*)q+1, ','))) 2397 { 2398 if ((len = p - q - 1) > 255) 2399 option = '?'; 2400 *q = len; 2401 for (q = q+1; q < p; q++) 2402 *q = unhide_meta(*q); 2403 } 2404 else 2405 { 2406 if ((len = strlen((char *)q+1)) > 255) 2407 option = '?'; 2408 *q = len; 2409 for (q = q+1; *q; q++) 2410 *q = unhide_meta(*q); 2411 break; 2412 } 2413 } 2414 2415 new = opt_malloc(sizeof(struct txt_record)); 2416 new->next = daemon->txt; 2417 daemon->txt = new; 2418 new->class = C_IN; 2419 if (comma) 2420 { 2421 new->len = q - ((unsigned char *)comma); 2422 new->txt = opt_malloc(new->len); 2423 memcpy(new->txt, comma, new->len); 2424 } 2425 else 2426 { 2427 static char empty[] = ""; 2428 new->len = 1; 2429 new->txt = empty; 2430 } 2431 2432 /* ensure arg is terminated */ 2433 if (comma) 2434 *comma = 0; 2435 2436 if (!(new->name = canonicalise_opt(arg))) 2437 { 2438 problem = _("bad TXT record"); 2439 break; 2440 } 2441 2442 break; 2443 } 2444 2445 case 'W': /* --srv-host */ 2446 { 2447 int port = 1, priority = 0, weight = 0; 2448 char *name, *target = NULL; 2449 struct mx_srv_record *new; 2450 2451 comma = split(arg); 2452 2453 if (!(name = canonicalise_opt(arg))) 2454 problem = _("bad SRV record"); 2455 2456 if (comma) 2457 { 2458 arg = comma; 2459 comma = split(arg); 2460 if (!(target = canonicalise_opt(arg)) 2461 ) problem = _("bad SRV target"); 2462 2463 if (comma) 2464 { 2465 arg = comma; 2466 comma = split(arg); 2467 if (!atoi_check16(arg, &port)) 2468 problem = _("invalid port number"); 2469 2470 if (comma) 2471 { 2472 arg = comma; 2473 comma = split(arg); 2474 if (!atoi_check16(arg, &priority)) 2475 problem = _("invalid priority"); 2476 2477 if (comma) 2478 { 2479 arg = comma; 2480 comma = split(arg); 2481 if (!atoi_check16(arg, &weight)) 2482 problem = _("invalid weight"); 2483 } 2484 } 2485 } 2486 } 2487 2488 new = opt_malloc(sizeof(struct mx_srv_record)); 2489 new->next = daemon->mxnames; 2490 daemon->mxnames = new; 2491 new->issrv = 1; 2492 new->name = name; 2493 new->target = target; 2494 new->srvport = port; 2495 new->priority = priority; 2496 new->weight = weight; 2497 break; 2498 } 2499 2500 default: 2501 return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"); 2502 2503 } 2504 2505 if (problem) 2506 return problem; 2507 2508 if (option == '?') 2509 return gen_prob; 2510 2511 return NULL; 2512 } 2513 2514 static void one_file(char *file, int nest, int hard_opt) 2515 { 2516 volatile int lineno = 0; 2517 int i, option; 2518 FILE *f; 2519 char *p, *arg, *start, *buff = daemon->namebuff; 2520 static struct fileread { 2521 dev_t dev; 2522 ino_t ino; 2523 struct fileread *next; 2524 } *filesread = NULL; 2525 struct stat statbuf; 2526 2527 /* ignore repeated files. */ 2528 if (hard_opt == 0 && stat(file, &statbuf) == 0) 2529 { 2530 struct fileread *r; 2531 2532 for (r = filesread; r; r = r->next) 2533 if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino) 2534 return; 2535 2536 r = safe_malloc(sizeof(struct fileread)); 2537 r->next = filesread; 2538 filesread = r; 2539 r->dev = statbuf.st_dev; 2540 r->ino = statbuf.st_ino; 2541 } 2542 2543 if (nest > 20) 2544 die(_("files nested too deep in %s"), file, EC_BADCONF); 2545 2546 if (!(f = fopen(file, "r"))) 2547 { 2548 if (errno == ENOENT && nest == 0) 2549 return; /* No conffile, all done. */ 2550 else 2551 { 2552 char *str = _("cannot read %s: %s"); 2553 if (hard_opt != 0) 2554 { 2555 my_syslog(LOG_ERR, str, file, strerror(errno)); 2556 return; 2557 } 2558 else 2559 die(str, file, EC_FILE); 2560 } 2561 } 2562 2563 while (fgets(buff, MAXDNAME, f)) 2564 { 2565 int white; 2566 unsigned int lastquote; 2567 char *errmess; 2568 2569 /* Memory allocation failure longjmps here if mem_recover == 1 */ 2570 if (hard_opt) 2571 { 2572 if (setjmp(mem_jmp)) 2573 continue; 2574 mem_recover = 1; 2575 } 2576 2577 lineno++; 2578 errmess = NULL; 2579 2580 /* Implement quotes, inside quotes we allow \\ \" \n and \t 2581 metacharacters get hidden also strip comments */ 2582 2583 for (white = 1, lastquote = 0, p = buff; *p; p++) 2584 { 2585 if (*p == '"') 2586 { 2587 memmove(p, p+1, strlen(p+1)+1); 2588 for(; *p && *p != '"'; p++) 2589 { 2590 if (*p == '\\' && strchr("\"tnebr\\", p[1])) 2591 { 2592 if (p[1] == 't') 2593 p[1] = '\t'; 2594 else if (p[1] == 'n') 2595 p[1] = '\n'; 2596 else if (p[1] == 'b') 2597 p[1] = '\b'; 2598 else if (p[1] == 'r') 2599 p[1] = '\r'; 2600 else if (p[1] == 'e') /* escape */ 2601 p[1] = '\033'; 2602 memmove(p, p+1, strlen(p+1)+1); 2603 } 2604 *p = hide_meta(*p); 2605 } 2606 if (*p == '"') 2607 { 2608 memmove(p, p+1, strlen(p+1)+1); 2609 lastquote = p - buff; 2610 } 2611 else 2612 { 2613 errmess = _("missing \""); 2614 goto oops; 2615 } 2616 } 2617 2618 if (white && *p == '#') 2619 { 2620 *p = 0; 2621 break; 2622 } 2623 white = isspace((int)unhide_meta(*p)); 2624 } 2625 2626 /* fgets gets end of line char too. */ 2627 while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1]))) 2628 buff[strlen(buff)-1] = 0; 2629 2630 if (*buff == 0) 2631 continue; 2632 2633 if (hard_opt != 0) 2634 arg = buff; 2635 else if ((p=strchr(buff, '='))) 2636 { 2637 /* allow spaces around "=" */ 2638 arg = p+1; 2639 for (; p >= buff && (isspace((int)*p) || *p == '='); p--) 2640 *p = 0; 2641 } 2642 else 2643 arg = NULL; 2644 2645 if (hard_opt != 0) 2646 option = hard_opt; 2647 else 2648 { 2649 /* skip leading space */ 2650 for (start = buff; *start && isspace((int)*start); start++); 2651 2652 for (option = 0, i = 0; opts[i].name; i++) 2653 if (strcmp(opts[i].name, start) == 0) 2654 { 2655 option = opts[i].val; 2656 break; 2657 } 2658 2659 if (!option) 2660 errmess = _("bad option"); 2661 else if (opts[i].has_arg == 0 && arg) 2662 errmess = _("extraneous parameter"); 2663 else if (opts[i].has_arg == 1 && !arg) 2664 errmess = _("missing parameter"); 2665 } 2666 2667 if (!errmess) 2668 { 2669 if (arg) 2670 for (; isspace((int)*arg); arg++); 2671 2672 errmess = one_opt(option, arg, _("error"), nest + 1); 2673 } 2674 2675 if (errmess) 2676 { 2677 oops: 2678 sprintf(buff, _("%s at line %d of %%s"), errmess, lineno); 2679 if (hard_opt != 0) 2680 my_syslog(LOG_ERR, buff, file); 2681 else 2682 die(buff, file, EC_BADCONF); 2683 } 2684 } 2685 2686 mem_recover = 1; 2687 fclose(f); 2688 } 2689 2690 #ifdef HAVE_DHCP 2691 void reread_dhcp(void) 2692 { 2693 if (daemon->dhcp_hosts_file) 2694 { 2695 struct dhcp_config *configs, *cp, **up; 2696 2697 /* remove existing... */ 2698 for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp) 2699 { 2700 cp = configs->next; 2701 2702 if (configs->flags & CONFIG_BANK) 2703 { 2704 struct hwaddr_config *mac, *tmp; 2705 2706 for (mac = configs->hwaddr; mac; mac = tmp) 2707 { 2708 tmp = mac->next; 2709 free(mac); 2710 } 2711 if (configs->flags & CONFIG_CLID) 2712 free(configs->clid); 2713 if (configs->flags & CONFIG_NETID) 2714 free(configs->netid.net); 2715 if (configs->flags & CONFIG_NAME) 2716 free(configs->hostname); 2717 2718 2719 *up = configs->next; 2720 free(configs); 2721 } 2722 else 2723 up = &configs->next; 2724 } 2725 2726 one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK); 2727 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file); 2728 } 2729 2730 if (daemon->dhcp_opts_file) 2731 { 2732 struct dhcp_opt *opts, *cp, **up; 2733 struct dhcp_netid *id, *next; 2734 2735 for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp) 2736 { 2737 cp = opts->next; 2738 2739 if (opts->flags & DHOPT_BANK) 2740 { 2741 if ((opts->flags & DHOPT_VENDOR)) 2742 free(opts->u.vendor_class); 2743 free(opts->val); 2744 for (id = opts->netid; id; id = next) 2745 { 2746 next = id->next; 2747 free(id->net); 2748 free(id); 2749 } 2750 *up = opts->next; 2751 free(opts); 2752 } 2753 else 2754 up = &opts->next; 2755 } 2756 2757 one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS); 2758 my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file); 2759 } 2760 } 2761 #endif 2762 2763 void read_opts(int argc, char **argv, char *compile_opts) 2764 { 2765 char *buff = opt_malloc(MAXDNAME); 2766 int option, nest = 0, testmode = 0; 2767 char *errmess, *arg, *conffile = CONFFILE; 2768 2769 opterr = 0; 2770 2771 daemon = opt_malloc(sizeof(struct daemon)); 2772 memset(daemon, 0, sizeof(struct daemon)); 2773 daemon->namebuff = buff; 2774 2775 /* Set defaults - everything else is zero or NULL */ 2776 daemon->cachesize = CACHESIZ; 2777 daemon->ftabsize = FTABSIZ; 2778 daemon->port = NAMESERVER_PORT; 2779 daemon->dhcp_client_port = DHCP_CLIENT_PORT; 2780 daemon->dhcp_server_port = DHCP_SERVER_PORT; 2781 daemon->default_resolv.is_default = 1; 2782 daemon->default_resolv.name = RESOLVFILE; 2783 daemon->resolv_files = &daemon->default_resolv; 2784 daemon->username = CHUSER; 2785 daemon->runfile = RUNFILE; 2786 daemon->dhcp_max = MAXLEASES; 2787 daemon->tftp_max = TFTP_MAX_CONNECTIONS; 2788 daemon->edns_pktsz = EDNS_PKTSZ; 2789 daemon->log_fac = -1; 2790 add_txt("version.bind", "dnsmasq-" VERSION ); 2791 add_txt("authors.bind", "Simon Kelley"); 2792 add_txt("copyright.bind", COPYRIGHT); 2793 2794 while (1) 2795 { 2796 #ifdef HAVE_GETOPT_LONG 2797 option = getopt_long(argc, argv, OPTSTRING, opts, NULL); 2798 #else 2799 option = getopt(argc, argv, OPTSTRING); 2800 #endif 2801 2802 if (option == -1) 2803 break; 2804 2805 /* Copy optarg so that argv doesn't get changed */ 2806 if (optarg) 2807 { 2808 strncpy(buff, optarg, MAXDNAME); 2809 buff[MAXDNAME-1] = 0; 2810 arg = buff; 2811 } 2812 else 2813 arg = NULL; 2814 2815 /* command-line only stuff */ 2816 if (option == LOPT_TEST) 2817 testmode = 1; 2818 else if (option == 'w') 2819 { 2820 if (argc != 3 || strcmp(argv[2], "dhcp") != 0) 2821 do_usage(); 2822 #ifdef HAVE_DHCP 2823 else 2824 display_opts(); 2825 #endif 2826 exit(0); 2827 } 2828 else if (option == 'v') 2829 { 2830 printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT); 2831 printf(_("Compile time options %s\n\n"), compile_opts); 2832 printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n")); 2833 printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n")); 2834 printf(_("under the terms of the GNU General Public License, version 2 or 3.\n")); 2835 exit(0); 2836 } 2837 else if (option == 'C') 2838 { 2839 conffile = opt_string_alloc(arg); 2840 nest++; 2841 } 2842 else 2843 { 2844 #ifdef HAVE_GETOPT_LONG 2845 errmess = one_opt(option, arg, _("try --help"), 0); 2846 #else 2847 errmess = one_opt(option, arg, _("try -w"), 0); 2848 #endif 2849 if (errmess) 2850 die(_("bad command line options: %s"), errmess, EC_BADCONF); 2851 } 2852 } 2853 2854 if (conffile) 2855 one_file(conffile, nest, 0); 2856 2857 /* port might not be known when the address is parsed - fill in here */ 2858 if (daemon->servers) 2859 { 2860 struct server *tmp; 2861 for (tmp = daemon->servers; tmp; tmp = tmp->next) 2862 if (!(tmp->flags & SERV_HAS_SOURCE)) 2863 { 2864 if (tmp->source_addr.sa.sa_family == AF_INET) 2865 tmp->source_addr.in.sin_port = htons(daemon->query_port); 2866 #ifdef HAVE_IPV6 2867 else if (tmp->source_addr.sa.sa_family == AF_INET6) 2868 tmp->source_addr.in6.sin6_port = htons(daemon->query_port); 2869 #endif 2870 } 2871 } 2872 2873 if (daemon->if_addrs) 2874 { 2875 struct iname *tmp; 2876 for(tmp = daemon->if_addrs; tmp; tmp = tmp->next) 2877 if (tmp->addr.sa.sa_family == AF_INET) 2878 tmp->addr.in.sin_port = htons(daemon->port); 2879 #ifdef HAVE_IPV6 2880 else if (tmp->addr.sa.sa_family == AF_INET6) 2881 tmp->addr.in6.sin6_port = htons(daemon->port); 2882 #endif /* IPv6 */ 2883 } 2884 2885 /* only one of these need be specified: the other defaults to the host-name */ 2886 if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget) 2887 { 2888 struct mx_srv_record *mx; 2889 2890 if (gethostname(buff, MAXDNAME) == -1) 2891 die(_("cannot get host-name: %s"), NULL, EC_MISC); 2892 2893 for (mx = daemon->mxnames; mx; mx = mx->next) 2894 if (!mx->issrv && hostname_isequal(mx->name, buff)) 2895 break; 2896 2897 if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx) 2898 { 2899 mx = opt_malloc(sizeof(struct mx_srv_record)); 2900 mx->next = daemon->mxnames; 2901 mx->issrv = 0; 2902 mx->target = NULL; 2903 mx->name = opt_string_alloc(buff); 2904 daemon->mxnames = mx; 2905 } 2906 2907 if (!daemon->mxtarget) 2908 daemon->mxtarget = opt_string_alloc(buff); 2909 2910 for (mx = daemon->mxnames; mx; mx = mx->next) 2911 if (!mx->issrv && !mx->target) 2912 mx->target = daemon->mxtarget; 2913 } 2914 2915 if (!(daemon->options & OPT_NO_RESOLV) && 2916 daemon->resolv_files && 2917 daemon->resolv_files->next && 2918 (daemon->options & OPT_NO_POLL)) 2919 die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF); 2920 2921 if (daemon->options & OPT_RESOLV_DOMAIN) 2922 { 2923 char *line; 2924 FILE *f; 2925 2926 if ((daemon->options & OPT_NO_RESOLV) || 2927 !daemon->resolv_files || 2928 (daemon->resolv_files)->next) 2929 die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF); 2930 2931 if (!(f = fopen((daemon->resolv_files)->name, "r"))) 2932 die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE); 2933 2934 while ((line = fgets(buff, MAXDNAME, f))) 2935 { 2936 char *token = strtok(line, " \t\n\r"); 2937 2938 if (!token || strcmp(token, "search") != 0) 2939 continue; 2940 2941 if ((token = strtok(NULL, " \t\n\r")) && 2942 (daemon->domain_suffix = canonicalise_opt(token))) 2943 break; 2944 } 2945 2946 fclose(f); 2947 2948 if (!daemon->domain_suffix) 2949 die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC); 2950 } 2951 2952 if (daemon->domain_suffix) 2953 { 2954 /* add domain for any srv record without one. */ 2955 struct mx_srv_record *srv; 2956 2957 for (srv = daemon->mxnames; srv; srv = srv->next) 2958 if (srv->issrv && 2959 strchr(srv->name, '.') && 2960 strchr(srv->name, '.') == strrchr(srv->name, '.')) 2961 { 2962 strcpy(buff, srv->name); 2963 strcat(buff, "."); 2964 strcat(buff, daemon->domain_suffix); 2965 free(srv->name); 2966 srv->name = opt_string_alloc(buff); 2967 } 2968 } 2969 else if (daemon->options & OPT_DHCP_FQDN) 2970 die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF); 2971 2972 if (testmode) 2973 { 2974 fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK")); 2975 exit(0); 2976 } 2977 } 2978