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