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