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