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