"Fossies" - the Fresh Open Source Software Archive

Member "dnsmasq-2.85/src/option.c" (7 Apr 2021, 144218 Bytes) of package /linux/misc/dns/dnsmasq-2.85.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "option.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.84_vs_2.85.

    1 /* dnsmasq is Copyright (c) 2000-2021 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 int one_file(char *file, int hard_opt);
   25 
   26 /* Solaris headers don't have facility names. */
   27 #ifdef HAVE_SOLARIS_NETWORK
   28 static const struct {
   29   char *c_name;
   30   unsigned int c_val;
   31 }  facilitynames[] = {
   32   { "kern",   LOG_KERN },
   33   { "user",   LOG_USER },
   34   { "mail",   LOG_MAIL },
   35   { "daemon", LOG_DAEMON },
   36   { "auth",   LOG_AUTH },
   37   { "syslog", LOG_SYSLOG },
   38   { "lpr",    LOG_LPR },
   39   { "news",   LOG_NEWS },
   40   { "uucp",   LOG_UUCP },
   41   { "audit",  LOG_AUDIT },
   42   { "cron",   LOG_CRON },
   43   { "local0", LOG_LOCAL0 },
   44   { "local1", LOG_LOCAL1 },
   45   { "local2", LOG_LOCAL2 },
   46   { "local3", LOG_LOCAL3 },
   47   { "local4", LOG_LOCAL4 },
   48   { "local5", LOG_LOCAL5 },
   49   { "local6", LOG_LOCAL6 },
   50   { "local7", LOG_LOCAL7 },
   51   { NULL, 0 }
   52 };
   53 #endif
   54 
   55 #ifndef HAVE_GETOPT_LONG
   56 struct myoption {
   57   const char *name;
   58   int has_arg;
   59   int *flag;
   60   int val;
   61 };
   62 #endif
   63 
   64 #define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
   65 
   66 /* options which don't have a one-char version */
   67 #define LOPT_RELOAD        256
   68 #define LOPT_NO_NAMES      257
   69 #define LOPT_TFTP          258
   70 #define LOPT_SECURE        259
   71 #define LOPT_PREFIX        260
   72 #define LOPT_PTR           261
   73 #define LOPT_BRIDGE        262
   74 #define LOPT_TFTP_MAX      263
   75 #define LOPT_FORCE         264
   76 #define LOPT_NOBLOCK       265
   77 #define LOPT_LOG_OPTS      266
   78 #define LOPT_MAX_LOGS      267
   79 #define LOPT_CIRCUIT       268
   80 #define LOPT_REMOTE        269
   81 #define LOPT_SUBSCR        270
   82 #define LOPT_INTNAME       271
   83 #define LOPT_BANK          272
   84 #define LOPT_DHCP_HOST     273
   85 #define LOPT_APREF         274
   86 #define LOPT_OVERRIDE      275
   87 #define LOPT_TFTPPORTS     276
   88 #define LOPT_REBIND        277
   89 #define LOPT_NOLAST        278
   90 #define LOPT_OPTS          279
   91 #define LOPT_DHCP_OPTS     280
   92 #define LOPT_MATCH         281
   93 #define LOPT_BROADCAST     282
   94 #define LOPT_NEGTTL        283
   95 #define LOPT_ALTPORT       284
   96 #define LOPT_SCRIPTUSR     285
   97 #define LOPT_LOCAL         286
   98 #define LOPT_NAPTR         287
   99 #define LOPT_MINPORT       288
  100 #define LOPT_DHCP_FQDN     289
  101 #define LOPT_CNAME         290
  102 #define LOPT_PXE_PROMT     291
  103 #define LOPT_PXE_SERV      292
  104 #define LOPT_TEST          293
  105 #define LOPT_TAG_IF        294
  106 #define LOPT_PROXY         295
  107 #define LOPT_GEN_NAMES     296
  108 #define LOPT_MAXTTL        297
  109 #define LOPT_NO_REBIND     298
  110 #define LOPT_LOC_REBND     299
  111 #define LOPT_ADD_MAC       300
  112 #define LOPT_DNSSEC        301
  113 #define LOPT_INCR_ADDR     302
  114 #define LOPT_CONNTRACK     303
  115 #define LOPT_FQDN          304
  116 #define LOPT_LUASCRIPT     305
  117 #define LOPT_RA            306
  118 #define LOPT_DUID          307
  119 #define LOPT_HOST_REC      308
  120 #define LOPT_TFTP_LC       309
  121 #define LOPT_RR            310
  122 #define LOPT_CLVERBIND     311
  123 #define LOPT_MAXCTTL       312
  124 #define LOPT_AUTHZONE      313
  125 #define LOPT_AUTHSERV      314
  126 #define LOPT_AUTHTTL       315
  127 #define LOPT_AUTHSOA       316
  128 #define LOPT_AUTHSFS       317
  129 #define LOPT_AUTHPEER      318
  130 #define LOPT_IPSET         319
  131 #define LOPT_SYNTH         320
  132 #define LOPT_RELAY         323
  133 #define LOPT_RA_PARAM      324
  134 #define LOPT_ADD_SBNET     325
  135 #define LOPT_QUIET_DHCP    326
  136 #define LOPT_QUIET_DHCP6   327
  137 #define LOPT_QUIET_RA      328
  138 #define LOPT_SEC_VALID     329
  139 #define LOPT_TRUST_ANCHOR  330
  140 #define LOPT_DNSSEC_DEBUG  331
  141 #define LOPT_REV_SERV      332
  142 #define LOPT_SERVERS_FILE  333
  143 #define LOPT_DNSSEC_CHECK  334
  144 #define LOPT_LOCAL_SERVICE 335
  145 #define LOPT_DNSSEC_TIME   336
  146 #define LOPT_LOOP_DETECT   337
  147 #define LOPT_IGNORE_ADDR   338
  148 #define LOPT_MINCTTL       339
  149 #define LOPT_DHCP_INOTIFY  340
  150 #define LOPT_DHOPT_INOTIFY 341
  151 #define LOPT_HOST_INOTIFY  342
  152 #define LOPT_DNSSEC_STAMP  343
  153 #define LOPT_TFTP_NO_FAIL  344
  154 #define LOPT_MAXPORT       345
  155 #define LOPT_CPE_ID        346
  156 #define LOPT_SCRIPT_ARP    347
  157 #define LOPT_DHCPTTL       348
  158 #define LOPT_TFTP_MTU      349
  159 #define LOPT_REPLY_DELAY   350
  160 #define LOPT_RAPID_COMMIT  351
  161 #define LOPT_DUMPFILE      352
  162 #define LOPT_DUMPMASK      353
  163 #define LOPT_UBUS          354
  164 #define LOPT_NAME_MATCH    355
  165 #define LOPT_CAA           356
  166 #define LOPT_SHARED_NET    357
  167 #define LOPT_IGNORE_CLID   358
  168 #define LOPT_SINGLE_PORT   359
  169 #define LOPT_SCRIPT_TIME   360
  170 #define LOPT_PXE_VENDOR    361
  171 #define LOPT_DYNHOST       362
  172 #define LOPT_LOG_DEBUG     363
  173  
  174 #ifdef HAVE_GETOPT_LONG
  175 static const struct option opts[] =  
  176 #else
  177 static const struct myoption opts[] = 
  178 #endif
  179   { 
  180     { "version", 0, 0, 'v' },
  181     { "no-hosts", 0, 0, 'h' },
  182     { "no-poll", 0, 0, 'n' },
  183     { "help", 0, 0, 'w' },
  184     { "no-daemon", 0, 0, 'd' },
  185     { "log-queries", 2, 0, 'q' },
  186     { "user", 2, 0, 'u' },
  187     { "group", 2, 0, 'g' },
  188     { "resolv-file", 2, 0, 'r' },
  189     { "servers-file", 1, 0, LOPT_SERVERS_FILE },
  190     { "mx-host", 1, 0, 'm' },
  191     { "mx-target", 1, 0, 't' },
  192     { "cache-size", 2, 0, 'c' },
  193     { "port", 1, 0, 'p' },
  194     { "dhcp-leasefile", 2, 0, 'l' },
  195     { "dhcp-lease", 1, 0, 'l' },
  196     { "dhcp-host", 1, 0, 'G' },
  197     { "dhcp-range", 1, 0, 'F' },
  198     { "dhcp-option", 1, 0, 'O' },
  199     { "dhcp-boot", 1, 0, 'M' },
  200     { "domain", 1, 0, 's' },
  201     { "domain-suffix", 1, 0, 's' },
  202     { "interface", 1, 0, 'i' },
  203     { "listen-address", 1, 0, 'a' },
  204     { "local-service", 0, 0, LOPT_LOCAL_SERVICE },
  205     { "bogus-priv", 0, 0, 'b' },
  206     { "bogus-nxdomain", 1, 0, 'B' },
  207     { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
  208     { "selfmx", 0, 0, 'e' },
  209     { "filterwin2k", 0, 0, 'f' },
  210     { "pid-file", 2, 0, 'x' },
  211     { "strict-order", 0, 0, 'o' },
  212     { "server", 1, 0, 'S' },
  213     { "rev-server", 1, 0, LOPT_REV_SERV },
  214     { "local", 1, 0, LOPT_LOCAL },
  215     { "address", 1, 0, 'A' },
  216     { "conf-file", 2, 0, 'C' },
  217     { "no-resolv", 0, 0, 'R' },
  218     { "expand-hosts", 0, 0, 'E' },
  219     { "localmx", 0, 0, 'L' },
  220     { "local-ttl", 1, 0, 'T' },
  221     { "no-negcache", 0, 0, 'N' },
  222     { "addn-hosts", 1, 0, 'H' },
  223     { "hostsdir", 1, 0, LOPT_HOST_INOTIFY },
  224     { "query-port", 1, 0, 'Q' },
  225     { "except-interface", 1, 0, 'I' },
  226     { "no-dhcp-interface", 1, 0, '2' },
  227     { "domain-needed", 0, 0, 'D' },
  228     { "dhcp-lease-max", 1, 0, 'X' },
  229     { "bind-interfaces", 0, 0, 'z' },
  230     { "read-ethers", 0, 0, 'Z' },
  231     { "alias", 1, 0, 'V' },
  232     { "dhcp-vendorclass", 1, 0, 'U' },
  233     { "dhcp-userclass", 1, 0, 'j' },
  234     { "dhcp-ignore", 1, 0, 'J' },
  235     { "edns-packet-max", 1, 0, 'P' },
  236     { "keep-in-foreground", 0, 0, 'k' },
  237     { "dhcp-authoritative", 0, 0, 'K' },
  238     { "srv-host", 1, 0, 'W' },
  239     { "localise-queries", 0, 0, 'y' },
  240     { "txt-record", 1, 0, 'Y' },
  241     { "caa-record", 1, 0 , LOPT_CAA },
  242     { "dns-rr", 1, 0, LOPT_RR },
  243     { "enable-dbus", 2, 0, '1' },
  244     { "enable-ubus", 2, 0, LOPT_UBUS },
  245     { "bootp-dynamic", 2, 0, '3' },
  246     { "dhcp-mac", 1, 0, '4' },
  247     { "no-ping", 0, 0, '5' },
  248     { "dhcp-script", 1, 0, '6' },
  249     { "conf-dir", 1, 0, '7' },
  250     { "log-facility", 1, 0 ,'8' },
  251     { "leasefile-ro", 0, 0, '9' },
  252     { "script-on-renewal", 0, 0, LOPT_SCRIPT_TIME},
  253     { "dns-forward-max", 1, 0, '0' },
  254     { "clear-on-reload", 0, 0, LOPT_RELOAD },
  255     { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
  256     { "enable-tftp", 2, 0, LOPT_TFTP },
  257     { "tftp-secure", 0, 0, LOPT_SECURE },
  258     { "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL },
  259     { "tftp-unique-root", 2, 0, LOPT_APREF },
  260     { "tftp-root", 1, 0, LOPT_PREFIX },
  261     { "tftp-max", 1, 0, LOPT_TFTP_MAX },
  262     { "tftp-mtu", 1, 0, LOPT_TFTP_MTU },
  263     { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
  264     { "tftp-single-port", 0, 0, LOPT_SINGLE_PORT },
  265     { "ptr-record", 1, 0, LOPT_PTR },
  266     { "naptr-record", 1, 0, LOPT_NAPTR },
  267     { "bridge-interface", 1, 0 , LOPT_BRIDGE },
  268     { "shared-network", 1, 0, LOPT_SHARED_NET },
  269     { "dhcp-option-force", 1, 0, LOPT_FORCE },
  270     { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
  271     { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
  272     { "log-async", 2, 0, LOPT_MAX_LOGS },
  273     { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
  274     { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
  275     { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
  276     { "dhcp-pxe-vendor", 1, 0, LOPT_PXE_VENDOR },
  277     { "interface-name", 1, 0, LOPT_INTNAME },
  278     { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
  279     { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
  280     { "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY },
  281     { "dhcp-optsdir", 1, 0, LOPT_DHOPT_INOTIFY },
  282     { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
  283     { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
  284     { "stop-dns-rebind", 0, 0, LOPT_REBIND },
  285     { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
  286     { "all-servers", 0, 0, LOPT_NOLAST }, 
  287     { "dhcp-match", 1, 0, LOPT_MATCH },
  288     { "dhcp-name-match", 1, 0, LOPT_NAME_MATCH },
  289     { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
  290     { "neg-ttl", 1, 0, LOPT_NEGTTL },
  291     { "max-ttl", 1, 0, LOPT_MAXTTL },
  292     { "min-cache-ttl", 1, 0, LOPT_MINCTTL },
  293     { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
  294     { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
  295     { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
  296     { "min-port", 1, 0, LOPT_MINPORT },
  297     { "max-port", 1, 0, LOPT_MAXPORT },
  298     { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
  299     { "cname", 1, 0, LOPT_CNAME },
  300     { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
  301     { "pxe-service", 1, 0, LOPT_PXE_SERV },
  302     { "test", 0, 0, LOPT_TEST },
  303     { "tag-if", 1, 0, LOPT_TAG_IF },
  304     { "dhcp-proxy", 2, 0, LOPT_PROXY },
  305     { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
  306     { "rebind-localhost-ok", 0, 0,  LOPT_LOC_REBND },
  307     { "add-mac", 2, 0, LOPT_ADD_MAC },
  308     { "add-subnet", 2, 0, LOPT_ADD_SBNET },
  309     { "add-cpe-id", 1, 0 , LOPT_CPE_ID },
  310     { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
  311     { "dhcp-sequential-ip", 0, 0,  LOPT_INCR_ADDR },
  312     { "conntrack", 0, 0, LOPT_CONNTRACK },
  313     { "dhcp-client-update", 0, 0, LOPT_FQDN },
  314     { "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
  315     { "enable-ra", 0, 0, LOPT_RA },
  316     { "dhcp-duid", 1, 0, LOPT_DUID },
  317     { "host-record", 1, 0, LOPT_HOST_REC },
  318     { "bind-dynamic", 0, 0, LOPT_CLVERBIND },
  319     { "auth-zone", 1, 0, LOPT_AUTHZONE },
  320     { "auth-server", 1, 0, LOPT_AUTHSERV },
  321     { "auth-ttl", 1, 0, LOPT_AUTHTTL },
  322     { "auth-soa", 1, 0, LOPT_AUTHSOA },
  323     { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
  324     { "auth-peer", 1, 0, LOPT_AUTHPEER }, 
  325     { "ipset", 1, 0, LOPT_IPSET },
  326     { "synth-domain", 1, 0, LOPT_SYNTH },
  327     { "dnssec", 0, 0, LOPT_SEC_VALID },
  328     { "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
  329     { "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
  330     { "dnssec-check-unsigned", 2, 0, LOPT_DNSSEC_CHECK },
  331     { "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
  332     { "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP },
  333     { "dhcp-relay", 1, 0, LOPT_RELAY },
  334     { "ra-param", 1, 0, LOPT_RA_PARAM },
  335     { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
  336     { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
  337     { "quiet-ra", 0, 0, LOPT_QUIET_RA },
  338     { "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT },
  339     { "script-arp", 0, 0, LOPT_SCRIPT_ARP },
  340     { "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
  341     { "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY },
  342     { "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT },
  343     { "dumpfile", 1, 0, LOPT_DUMPFILE },
  344     { "dumpmask", 1, 0, LOPT_DUMPMASK },
  345     { "dhcp-ignore-clid", 0, 0,  LOPT_IGNORE_CLID },
  346     { "dynamic-host", 1, 0, LOPT_DYNHOST },
  347     { "log-debug", 0, 0, LOPT_LOG_DEBUG },
  348     { NULL, 0, 0, 0 }
  349   };
  350 
  351 
  352 #define ARG_DUP       OPT_LAST
  353 #define ARG_ONE       OPT_LAST + 1
  354 #define ARG_USED_CL   OPT_LAST + 2
  355 #define ARG_USED_FILE OPT_LAST + 3
  356 
  357 static struct {
  358   int opt;
  359   unsigned int rept;
  360   char * const flagdesc;
  361   char * const desc;
  362   char * const arg;
  363 } usage[] = {
  364   { 'a', ARG_DUP, "<ipaddr>",  gettext_noop("Specify local address(es) to listen on."), NULL },
  365   { 'A', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
  366   { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
  367   { 'B', ARG_DUP, "<ipaddr>", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL }, 
  368   { 'c', ARG_ONE, "<integer>", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
  369   { 'C', ARG_DUP, "<path>", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
  370   { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
  371   { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL }, 
  372   { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
  373   { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
  374   { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
  375   { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
  376   { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
  377   { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
  378   { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
  379   { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
  380   { LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL }, 
  381   { LOPT_DHOPT_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP options from a directory."), NULL }, 
  382   { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
  383   { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
  384   { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
  385   { LOPT_HOST_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read hosts files from a directory."), NULL },
  386   { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
  387   { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
  388   { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
  389   { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
  390   { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
  391   { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
  392   { LOPT_PXE_VENDOR, ARG_DUP, "<vendor>[,...]", gettext_noop("Specify vendor class to match for PXE requests."), NULL },
  393   { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
  394   { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL }, 
  395   { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
  396   { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
  397   { 'l', ARG_ONE, "<path>", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
  398   { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
  399   { 'm', ARG_DUP, "<host_name>,<target>,<pref>", gettext_noop("Specify an MX record."), NULL },
  400   { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
  401   { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE }, 
  402   { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
  403   { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
  404   { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
  405   { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
  406   { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
  407   { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
  408   { 'q', ARG_DUP, NULL, gettext_noop("Log DNS queries."), NULL },
  409   { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
  410   { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
  411   { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, 
  412   { LOPT_SERVERS_FILE, ARG_ONE, "<path>", gettext_noop("Specify path to file with server= options"), NULL },
  413   { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
  414   { LOPT_REV_SERV, ARG_DUP, "<addr>/<prefix>,<ipaddr>", gettext_noop("Specify address of upstream servers for reverse address queries"), NULL },
  415   { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
  416   { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
  417   { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
  418   { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
  419   { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
  420   { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
  421   { LOPT_MAXCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live ceiling for cache."), NULL },
  422   { LOPT_MINCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live floor for cache."), NULL },
  423   { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER }, 
  424   { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
  425   { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
  426   { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
  427   { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
  428   { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL },
  429   { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
  430   { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
  431   { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
  432   { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record."), NULL },
  433   { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record."), NULL },
  434   { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
  435   { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
  436   { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
  437   { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
  438   { LOPT_UBUS, ARG_ONE, "[=<busname>]", gettext_noop("Enable the UBus interface."), NULL },
  439   { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
  440   { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
  441   { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
  442   { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
  443   { LOPT_SHARED_NET, ARG_DUP, "<iface>|<addr>,<addr>", gettext_noop("Specify extra networks sharing a broadcast domain for DHCP"), NULL},
  444   { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
  445   { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
  446   { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
  447   { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
  448   { LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL },
  449   { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
  450   { '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
  451   { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
  452   { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, 
  453   { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
  454   { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
  455   { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
  456   { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
  457   { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
  458   { LOPT_APREF, ARG_DUP, "[=ip|mac]", gettext_noop("Add client IP or hardware address to tftp-root."), NULL },
  459   { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
  460   { LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate the service if TFTP directories are inaccessible."), NULL },
  461   { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent TFTP transfers (defaults to %s)."), "#" },
  462   { LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum MTU to use for TFTP transfers."), NULL },
  463   { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
  464   { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
  465   { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
  466   { LOPT_SINGLE_PORT, OPT_SINGLE_PORT, NULL, gettext_noop("Use only one port for TFTP server."), NULL },
  467   { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
  468   { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
  469   { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
  470   { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
  471   { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
  472   { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
  473   { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
  474   { LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL },
  475   { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
  476   { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
  477   { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
  478   { LOPT_MAXPORT, ARG_ONE, "<port>", gettext_noop("Specify highest port available for DNS query transmission."), NULL },
  479   { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
  480   { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
  481   { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
  482   { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<iface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
  483   { LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
  484   { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
  485   { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
  486   { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
  487   { LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
  488   { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL },
  489   { LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client identification to forwarded DNS queries."), NULL },
  490   { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
  491   { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
  492   { LOPT_IGNORE_CLID, OPT_IGNORE_CLID, NULL, gettext_noop("Ignore client identifier option sent by DHCP clients."), NULL },
  493   { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
  494   { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
  495   { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
  496   { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
  497   { LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
  498   { LOPT_DYNHOST, ARG_DUP, "<name>,[<IPv4>][,<IPv6>],<interface-name>", gettext_noop("Specify host record in interface subnet"), NULL },
  499   { LOPT_CAA, ARG_DUP, "<name>,<flags>,<tag>,<value>", gettext_noop("Specify certification authority authorization record"), NULL },  
  500   { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
  501   { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
  502   { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
  503   { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
  504   { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
  505   { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritative zone information"), NULL },
  506   { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
  507   { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
  508   { LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
  509   { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
  510   { LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
  511   { LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
  512   { LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
  513   { LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
  514   { LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
  515   { LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL },
  516   { LOPT_RA_PARAM, ARG_DUP, "<iface>,[mtu:<value>|<interface>|off,][<prio>,]<intval>[,<lifetime>]", gettext_noop("Set MTU, priority, resend-interval and router-lifetime"), NULL },
  517   { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
  518   { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
  519   { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
  520   { LOPT_LOG_DEBUG, OPT_LOG_DEBUG, NULL, gettext_noop("Log debugging information."), NULL }, 
  521   { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks."), NULL },
  522   { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops."), NULL },
  523   { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL }, 
  524   { LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL }, 
  525   { LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
  526   { LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapid Commit option."), NULL },
  527   { LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump file"), NULL },
  528   { LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
  529   { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL },
  530   { 0, 0, NULL, NULL, NULL }
  531 }; 
  532 
  533 /* We hide metacharacters in quoted strings by mapping them into the ASCII control
  534    character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
  535    following sequence so that they map to themselves: it is therefore possible to call
  536    unhide_metas repeatedly on string without breaking things.
  537    The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a 
  538    couple of other places. 
  539    Note that space is included here so that
  540    --dhcp-option=3, string
  541    has five characters, whilst
  542    --dhcp-option=3," string"
  543    has six.
  544 */
  545 
  546 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
  547 
  548 static char hide_meta(char c)
  549 {
  550   unsigned int i;
  551 
  552   for (i = 0; i < (sizeof(meta) - 1); i++)
  553     if (c == meta[i])
  554       return (char)i;
  555   
  556   return c;
  557 }
  558 
  559 static char unhide_meta(char cr)
  560 { 
  561   unsigned int c = cr;
  562   
  563   if (c < (sizeof(meta) - 1))
  564     cr = meta[c];
  565   
  566   return cr;
  567 }
  568 
  569 static void unhide_metas(char *cp)
  570 {
  571   if (cp)
  572     for(; *cp; cp++)
  573       *cp = unhide_meta(*cp);
  574 }
  575 
  576 static void *opt_malloc(size_t size)
  577 {
  578   void *ret;
  579 
  580   if (mem_recover)
  581     {
  582       ret = whine_malloc(size);
  583       if (!ret)
  584     longjmp(mem_jmp, 1);
  585     }
  586   else
  587     ret = safe_malloc(size);
  588   
  589   return ret;
  590 }
  591 
  592 static char *opt_string_alloc(const char *cp)
  593 {
  594   char *ret = NULL;
  595   size_t len;
  596   
  597   if (cp && (len = strlen(cp)) != 0)
  598     {
  599       ret = opt_malloc(len+1);
  600       memcpy(ret, cp, len+1); 
  601       
  602       /* restore hidden metachars */
  603       unhide_metas(ret);
  604     }
  605     
  606   return ret;
  607 }
  608 
  609 
  610 /* find next comma, split string with zero and eliminate spaces.
  611    return start of string following comma */
  612 
  613 static char *split_chr(char *s, char c)
  614 {
  615   char *comma, *p;
  616 
  617   if (!s || !(comma = strchr(s, c)))
  618     return NULL;
  619   
  620   p = comma;
  621   *comma = ' ';
  622   
  623   for (; *comma == ' '; comma++);
  624  
  625   for (; (p >= s) && *p == ' '; p--)
  626     *p = 0;
  627     
  628   return comma;
  629 }
  630 
  631 static char *split(char *s)
  632 {
  633   return split_chr(s, ',');
  634 }
  635 
  636 static char *canonicalise_opt(char *s)
  637 {
  638   char *ret;
  639   int nomem;
  640 
  641   if (!s)
  642     return 0;
  643 
  644   unhide_metas(s);
  645   if (!(ret = canonicalise(s, &nomem)) && nomem)
  646     {
  647       if (mem_recover)
  648     longjmp(mem_jmp, 1);
  649       else
  650     die(_("could not get memory"), NULL, EC_NOMEM);
  651     }
  652 
  653   return ret;
  654 }
  655 
  656 static int atoi_check(char *a, int *res)
  657 {
  658   char *p;
  659 
  660   if (!a)
  661     return 0;
  662 
  663   unhide_metas(a);
  664   
  665   for (p = a; *p; p++)
  666      if (*p < '0' || *p > '9')
  667        return 0;
  668 
  669   *res = atoi(a);
  670   return 1;
  671 }
  672 
  673 static int atoi_check16(char *a, int *res)
  674 {
  675   if (!(atoi_check(a, res)) ||
  676       *res < 0 ||
  677       *res > 0xffff)
  678     return 0;
  679 
  680   return 1;
  681 }
  682 
  683 #ifdef HAVE_DNSSEC
  684 static int atoi_check8(char *a, int *res)
  685 {
  686   if (!(atoi_check(a, res)) ||
  687       *res < 0 ||
  688       *res > 0xff)
  689     return 0;
  690 
  691   return 1;
  692 }
  693 #endif
  694 
  695 #ifndef NO_ID
  696 static void add_txt(char *name, char *txt, int stat)
  697 {
  698   struct txt_record *r = opt_malloc(sizeof(struct txt_record));
  699 
  700   if (txt)
  701     {
  702       size_t len = strlen(txt);
  703       r->txt = opt_malloc(len+1);
  704       r->len = len+1;
  705       *(r->txt) = len;
  706       memcpy((r->txt)+1, txt, len);
  707     }
  708 
  709   r->stat = stat;
  710   r->name = opt_string_alloc(name);
  711   r->next = daemon->txt;
  712   daemon->txt = r;
  713   r->class = C_CHAOS;
  714 }
  715 #endif
  716 
  717 static void do_usage(void)
  718 {
  719   char buff[100];
  720   int i, j;
  721 
  722   struct {
  723     char handle;
  724     int val;
  725   } tab[] = {
  726     { '$', CACHESIZ },
  727     { '*', EDNS_PKTSZ },
  728     { '&', MAXLEASES },
  729     { '!', FTABSIZ },
  730     { '#', TFTP_MAX_CONNECTIONS },
  731     { '\0', 0 }
  732   };
  733 
  734   printf(_("Usage: dnsmasq [options]\n\n"));
  735 #ifndef HAVE_GETOPT_LONG
  736   printf(_("Use short options only on the command line.\n"));
  737 #endif
  738   printf(_("Valid options are:\n"));
  739   
  740   for (i = 0; usage[i].opt != 0; i++)
  741     {
  742       char *desc = usage[i].flagdesc; 
  743       char *eq = "=";
  744       
  745       if (!desc || *desc == '[')
  746     eq = "";
  747       
  748       if (!desc)
  749     desc = "";
  750 
  751       for ( j = 0; opts[j].name; j++)
  752     if (opts[j].val == usage[i].opt)
  753       break;
  754       if (usage[i].opt < 256)
  755     sprintf(buff, "-%c, ", usage[i].opt);
  756       else
  757     sprintf(buff, "    ");
  758       
  759       sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
  760       printf("%-55.55s", buff);
  761          
  762       if (usage[i].arg)
  763     {
  764       strcpy(buff, usage[i].arg);
  765       for (j = 0; tab[j].handle; j++)
  766         if (tab[j].handle == *(usage[i].arg))
  767           sprintf(buff, "%d", tab[j].val);
  768     }
  769       printf(_(usage[i].desc), buff);
  770       printf("\n");
  771     }
  772 }
  773 
  774 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
  775 #define ret_err_free(x,m) do { strcpy(errstr, (x)); free((m)); return 0; } while (0)
  776 #define goto_err(x) do { strcpy(errstr, (x)); goto on_error; } while (0)
  777 
  778 static char *parse_mysockaddr(char *arg, union mysockaddr *addr) 
  779 {
  780   if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
  781     addr->sa.sa_family = AF_INET;
  782   else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
  783     addr->sa.sa_family = AF_INET6;
  784   else
  785     return _("bad address");
  786    
  787   return NULL;
  788 }
  789 
  790 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
  791 {
  792   int source_port = 0, serv_port = NAMESERVER_PORT;
  793   char *portno, *source;
  794   char *interface_opt = NULL;
  795   int scope_index = 0;
  796   char *scope_id;
  797   
  798   if (!arg || strlen(arg) == 0)
  799     {
  800       *flags |= SERV_NO_ADDR;
  801       *interface = 0;
  802       return NULL;
  803     }
  804 
  805   if ((source = split_chr(arg, '@')) && /* is there a source. */
  806       (portno = split_chr(source, '#')) &&
  807       !atoi_check16(portno, &source_port))
  808     return _("bad port");
  809   
  810   if ((portno = split_chr(arg, '#')) && /* is there a port no. */
  811       !atoi_check16(portno, &serv_port))
  812     return _("bad port");
  813   
  814   scope_id = split_chr(arg, '%');
  815   
  816   if (source) {
  817     interface_opt = split_chr(source, '@');
  818 
  819     if (interface_opt)
  820       {
  821 #if defined(SO_BINDTODEVICE)
  822     safe_strncpy(interface, source, IF_NAMESIZE);
  823     source = interface_opt;
  824 #else
  825     return _("interface binding not supported");
  826 #endif
  827       }
  828   }
  829 
  830   if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
  831     {
  832       addr->in.sin_port = htons(serv_port); 
  833       addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
  834 #ifdef HAVE_SOCKADDR_SA_LEN
  835       source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
  836 #endif
  837       source_addr->in.sin_addr.s_addr = INADDR_ANY;
  838       source_addr->in.sin_port = htons(daemon->query_port);
  839       
  840       if (source)
  841     {
  842       if (flags)
  843         *flags |= SERV_HAS_SOURCE;
  844       source_addr->in.sin_port = htons(source_port);
  845       if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
  846         {
  847 #if defined(SO_BINDTODEVICE)
  848           if (interface_opt)
  849         return _("interface can only be specified once");
  850           
  851           source_addr->in.sin_addr.s_addr = INADDR_ANY;
  852           safe_strncpy(interface, source, IF_NAMESIZE);
  853 #else
  854           return _("interface binding not supported");
  855 #endif
  856         }
  857     }
  858     }
  859   else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
  860     {
  861       if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
  862     return _("bad interface name");
  863       
  864       addr->in6.sin6_port = htons(serv_port);
  865       addr->in6.sin6_scope_id = scope_index;
  866       source_addr->in6.sin6_addr = in6addr_any; 
  867       source_addr->in6.sin6_port = htons(daemon->query_port);
  868       source_addr->in6.sin6_scope_id = 0;
  869       addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
  870       addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
  871 #ifdef HAVE_SOCKADDR_SA_LEN
  872       addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
  873 #endif
  874       if (source)
  875     {
  876       if (flags)
  877         *flags |= SERV_HAS_SOURCE;
  878       source_addr->in6.sin6_port = htons(source_port);
  879       if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
  880         {
  881 #if defined(SO_BINDTODEVICE)
  882           if (interface_opt)
  883         return _("interface can only be specified once");
  884           
  885           source_addr->in6.sin6_addr = in6addr_any;
  886           safe_strncpy(interface, source, IF_NAMESIZE);
  887 #else
  888           return _("interface binding not supported");
  889 #endif
  890         }
  891     }
  892     }
  893   else
  894     return _("bad address");
  895 
  896   return NULL;
  897 }
  898 
  899 static struct server *add_rev4(struct in_addr addr, int msize)
  900 {
  901   struct server *serv = opt_malloc(sizeof(struct server));
  902   in_addr_t  a = ntohl(addr.s_addr);
  903   char *p;
  904 
  905   memset(serv, 0, sizeof(struct server));
  906   p = serv->domain = opt_malloc(29); /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
  907 
  908   switch (msize)
  909     {
  910     case 32:
  911       p += sprintf(p, "%u.", a & 0xff);
  912       /* fall through */
  913     case 24:
  914       p += sprintf(p, "%d.", (a >> 8) & 0xff);
  915       /* fall through */
  916     case 16:
  917       p += sprintf(p, "%d.", (a >> 16) & 0xff);
  918       /* fall through */
  919     case 8:
  920       p += sprintf(p, "%d.", (a >> 24) & 0xff);
  921       break;
  922     default:
  923       free(serv->domain);
  924       free(serv);
  925       return NULL;
  926     }
  927 
  928   p += sprintf(p, "in-addr.arpa");
  929   
  930   serv->flags = SERV_HAS_DOMAIN;
  931   serv->next = daemon->servers;
  932   daemon->servers = serv;
  933 
  934   return serv;
  935 
  936 }
  937 
  938 static struct server *add_rev6(struct in6_addr *addr, int msize)
  939 {
  940   struct server *serv = opt_malloc(sizeof(struct server));
  941   char *p;
  942   int i;
  943                   
  944   memset(serv, 0, sizeof(struct server));
  945   p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
  946   
  947   for (i = msize-1; i >= 0; i -= 4)
  948     { 
  949       int dig = ((unsigned char *)addr)[i>>3];
  950       p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
  951     }
  952   p += sprintf(p, "ip6.arpa");
  953   
  954   serv->flags = SERV_HAS_DOMAIN;
  955   serv->next = daemon->servers;
  956   daemon->servers = serv;
  957   
  958   return serv;
  959 }
  960 
  961 #ifdef HAVE_DHCP
  962 
  963 static int is_tag_prefix(char *arg)
  964 {
  965   if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
  966     return 1;
  967   
  968   return 0;
  969 }
  970 
  971 static char *set_prefix(char *arg)
  972 {
  973    if (strstr(arg, "set:") == arg)
  974      return arg+4;
  975    
  976    return arg;
  977 }
  978 
  979 static struct dhcp_netid *dhcp_netid_create(const char *net, struct dhcp_netid *next)
  980 {
  981   struct dhcp_netid *tt;
  982   tt = opt_malloc(sizeof (struct dhcp_netid));
  983   tt->net = opt_string_alloc(net);
  984   tt->next = next;
  985   return tt;
  986 }
  987 
  988 static void dhcp_netid_free(struct dhcp_netid *nid)
  989 {
  990   while (nid)
  991     {
  992       struct dhcp_netid *tmp = nid;
  993       nid = nid->next;
  994       free(tmp->net);
  995       free(tmp);
  996     }
  997 }
  998 
  999 /* Parse one or more tag:s before parameters.
 1000  * Moves arg to the end of tags. */
 1001 static struct dhcp_netid * dhcp_tags(char **arg)
 1002 {
 1003   struct dhcp_netid *id = NULL;
 1004 
 1005   while (is_tag_prefix(*arg))
 1006     {
 1007       char *comma = split(*arg);
 1008       id = dhcp_netid_create((*arg)+4, id);
 1009       *arg = comma;
 1010     };
 1011   if (!*arg)
 1012     {
 1013       dhcp_netid_free(id);
 1014       id = NULL;
 1015     }
 1016   return id;
 1017 }
 1018 
 1019 static void dhcp_netid_list_free(struct dhcp_netid_list *netid)
 1020 {
 1021   while (netid)
 1022     {
 1023       struct dhcp_netid_list *tmplist = netid;
 1024       netid = netid->next;
 1025       dhcp_netid_free(tmplist->list);
 1026       free(tmplist);
 1027     }
 1028 }
 1029 
 1030 static void dhcp_config_free(struct dhcp_config *config)
 1031 {
 1032   if (config)
 1033     {
 1034       struct hwaddr_config *hwaddr = config->hwaddr;
 1035       
 1036       while (hwaddr)
 1037         {
 1038       struct hwaddr_config *tmp = hwaddr;
 1039           hwaddr = hwaddr->next;
 1040       free(tmp);
 1041         }
 1042       
 1043       dhcp_netid_list_free(config->netid);
 1044       dhcp_netid_free(config->filter);
 1045       
 1046       if (config->flags & CONFIG_CLID)
 1047         free(config->clid);
 1048 
 1049 #ifdef HAVE_DHCP6
 1050       if (config->flags & CONFIG_ADDR6)
 1051     {
 1052       struct addrlist *addr, *tmp;
 1053       
 1054       for (addr = config->addr6; addr; addr = tmp)
 1055         {
 1056           tmp = addr->next;
 1057           free(addr);
 1058         }
 1059     }
 1060 #endif
 1061 
 1062       free(config);
 1063     }
 1064 }
 1065 
 1066 static void dhcp_context_free(struct dhcp_context *ctx)
 1067 {
 1068   if (ctx)
 1069     {
 1070       dhcp_netid_free(ctx->filter);
 1071       free(ctx->netid.net);
 1072 #ifdef HAVE_DHCP6
 1073       free(ctx->template_interface);
 1074 #endif
 1075       free(ctx);
 1076     }
 1077 }
 1078 
 1079 static void dhcp_opt_free(struct dhcp_opt *opt)
 1080 {
 1081   if (opt->flags & DHOPT_VENDOR)
 1082     free(opt->u.vendor_class);
 1083   dhcp_netid_free(opt->netid);
 1084   free(opt->val);
 1085   free(opt);
 1086 }
 1087 
 1088 
 1089 /* This is too insanely large to keep in-line in the switch */
 1090 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
 1091 {
 1092   struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
 1093   char lenchar = 0, *cp;
 1094   int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
 1095   char *comma = NULL;
 1096   u16 opt_len = 0;
 1097   int is6 = 0;
 1098   int option_ok = 0;
 1099 
 1100   new->len = 0;
 1101   new->flags = flags;
 1102   new->netid = NULL;
 1103   new->val = NULL;
 1104   new->opt = 0;
 1105   
 1106   while (arg)
 1107     {
 1108       comma = split(arg);      
 1109 
 1110       for (cp = arg; *cp; cp++)
 1111     if (*cp < '0' || *cp > '9')
 1112       break;
 1113       
 1114       if (!*cp)
 1115     {
 1116       new->opt = atoi(arg);
 1117       opt_len = 0;
 1118       option_ok = 1;
 1119       break;
 1120     }
 1121       
 1122       if (strstr(arg, "option:") == arg)
 1123     {
 1124       if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
 1125         {
 1126           opt_len = lookup_dhcp_len(AF_INET, new->opt);
 1127           /* option:<optname> must follow tag and vendor string. */
 1128           if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
 1129         option_ok = 1;
 1130         }
 1131       break;
 1132     }
 1133 #ifdef HAVE_DHCP6
 1134       else if (strstr(arg, "option6:") == arg)
 1135     {
 1136       for (cp = arg+8; *cp; cp++)
 1137         if (*cp < '0' || *cp > '9')
 1138           break;
 1139      
 1140       if (!*cp)
 1141         {
 1142           new->opt = atoi(arg+8);
 1143           opt_len = 0;
 1144           option_ok = 1;
 1145         }
 1146       else
 1147         {
 1148           if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
 1149         {
 1150           opt_len = lookup_dhcp_len(AF_INET6, new->opt);
 1151           if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
 1152             option_ok = 1;
 1153         }
 1154         }
 1155       /* option6:<opt>|<optname> must follow tag and vendor string. */
 1156       is6 = 1;
 1157       break;
 1158     }
 1159 #endif
 1160       else if (strstr(arg, "vendor:") == arg)
 1161     {
 1162       new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
 1163       new->flags |= DHOPT_VENDOR;
 1164     }
 1165       else if (strstr(arg, "encap:") == arg)
 1166     {
 1167       new->u.encap = atoi(arg+6);
 1168       new->flags |= DHOPT_ENCAPSULATE;
 1169     }
 1170       else if (strstr(arg, "vi-encap:") == arg)
 1171     {
 1172       new->u.encap = atoi(arg+9);
 1173       new->flags |= DHOPT_RFC3925;
 1174       if (flags == DHOPT_MATCH)
 1175         {
 1176           option_ok = 1;
 1177           break;
 1178         }
 1179     }
 1180       else
 1181     {
 1182       /* allow optional "net:" or "tag:" for consistency */
 1183       const char *name = (is_tag_prefix(arg)) ? arg+4 : set_prefix(arg);
 1184       new->netid = dhcp_netid_create(name, new->netid);
 1185     }
 1186       
 1187       arg = comma; 
 1188     }
 1189 
 1190 #ifdef HAVE_DHCP6
 1191   if (is6)
 1192     {
 1193       if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
 1194     goto_err(_("unsupported encapsulation for IPv6 option"));
 1195       
 1196       if (opt_len == 0 &&
 1197       !(new->flags & DHOPT_RFC3925))
 1198     opt_len = lookup_dhcp_len(AF_INET6, new->opt);
 1199     }
 1200   else
 1201 #endif
 1202     if (opt_len == 0 &&
 1203     !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
 1204       opt_len = lookup_dhcp_len(AF_INET, new->opt);
 1205   
 1206   /* option may be missing with rfc3925 match */
 1207   if (!option_ok)
 1208     goto_err(_("bad dhcp-option"));
 1209   
 1210   if (comma)
 1211     {
 1212       /* characterise the value */
 1213       char c;
 1214       int found_dig = 0, found_colon = 0;
 1215       is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
 1216       addrs = digs = 1;
 1217       dots = 0;
 1218       for (cp = comma; (c = *cp); cp++)
 1219     if (c == ',')
 1220       {
 1221         addrs++;
 1222         is_dec = is_hex = 0;
 1223       }
 1224     else if (c == ':')
 1225       {
 1226         digs++;
 1227         is_dec = is_addr = 0;
 1228         found_colon = 1;
 1229       }
 1230     else if (c == '/') 
 1231       {
 1232         is_addr6 = is_dec = is_hex = 0;
 1233         if (cp == comma) /* leading / means a pathname */
 1234           is_addr = 0;
 1235       } 
 1236     else if (c == '.')  
 1237       {
 1238         is_dec = is_hex = 0;
 1239         dots++;
 1240       }
 1241     else if (c == '-')
 1242       is_hex = is_addr = is_addr6 = 0;
 1243     else if (c == ' ')
 1244       is_dec = is_hex = 0;
 1245     else if (!(c >='0' && c <= '9'))
 1246       {
 1247         is_addr = 0;
 1248         if (cp[1] == 0 && is_dec &&
 1249         (c == 'b' || c == 's' || c == 'i'))
 1250           {
 1251         lenchar = c;
 1252         *cp = 0;
 1253           }
 1254         else
 1255           is_dec = 0;
 1256         if (!((c >='A' && c <= 'F') ||
 1257           (c >='a' && c <= 'f') || 
 1258           (c == '*' && (flags & DHOPT_MATCH))))
 1259           {
 1260         is_hex = 0;
 1261         if (c != '[' && c != ']')
 1262           is_addr6 = 0;
 1263           }
 1264       }
 1265     else
 1266       found_dig = 1;
 1267      
 1268       if (!found_dig)
 1269     is_dec = is_addr = 0;
 1270 
 1271       if (!found_colon)
 1272     is_addr6 = 0;
 1273 
 1274 #ifdef HAVE_DHCP6
 1275       /* NTP server option takes hex, addresses or FQDN */
 1276       if (is6 && new->opt == OPTION6_NTP_SERVER && !is_hex)
 1277     opt_len |= is_addr6 ? OT_ADDR_LIST : OT_RFC1035_NAME;
 1278 #endif
 1279      
 1280       /* We know that some options take addresses */
 1281       if (opt_len & OT_ADDR_LIST)
 1282     {
 1283       is_string = is_dec = is_hex = 0;
 1284       
 1285       if (!is6 && (!is_addr || dots == 0))
 1286         goto_err(_("bad IP address"));
 1287 
 1288        if (is6 && !is_addr6)
 1289          goto_err(_("bad IPv6 address"));
 1290     }
 1291       /* or names */
 1292       else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
 1293     is_addr6 = is_addr = is_dec = is_hex = 0;
 1294       
 1295       if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
 1296     {
 1297       int val, fac = 1;
 1298 
 1299       switch (comma[strlen(comma) - 1])
 1300         {
 1301         case 'w':
 1302         case 'W':
 1303           fac *= 7;
 1304           /* fall through */
 1305         case 'd':
 1306         case 'D':
 1307           fac *= 24;
 1308           /* fall through */
 1309         case 'h':
 1310         case 'H':
 1311           fac *= 60;
 1312           /* fall through */
 1313         case 'm':
 1314         case 'M':
 1315           fac *= 60;
 1316           /* fall through */
 1317         case 's':
 1318         case 'S':
 1319           comma[strlen(comma) - 1] = 0;
 1320         }
 1321       
 1322       new->len = 4;
 1323       new->val = opt_malloc(4);
 1324       val = atoi(comma);
 1325       *((int *)new->val) = htonl(val * fac);      
 1326     }  
 1327       else if (is_hex && digs > 1)
 1328     {
 1329       new->len = digs;
 1330       new->val = opt_malloc(new->len);
 1331       parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
 1332       new->flags |= DHOPT_HEX;
 1333     }
 1334       else if (is_dec)
 1335     {
 1336       int i, val = atoi(comma);
 1337       /* assume numeric arg is 1 byte except for
 1338          options where it is known otherwise.
 1339          For vendor class option, we have to hack. */
 1340       if (opt_len != 0)
 1341         new->len = opt_len;
 1342       else if (val & 0xffff0000)
 1343         new->len = 4;
 1344       else if (val & 0xff00)
 1345         new->len = 2;
 1346       else
 1347         new->len = 1;
 1348 
 1349       if (lenchar == 'b')
 1350         new->len = 1;
 1351       else if (lenchar == 's')
 1352         new->len = 2;
 1353       else if (lenchar == 'i')
 1354         new->len = 4;
 1355       
 1356       new->val = opt_malloc(new->len);
 1357       for (i=0; i<new->len; i++)
 1358         new->val[i] = val>>((new->len - i - 1)*8);
 1359     }
 1360       else if (is_addr && !is6) 
 1361     {
 1362       struct in_addr in;
 1363       unsigned char *op;
 1364       char *slash;
 1365       /* max length of address/subnet descriptor is five bytes,
 1366          add one for the option 120 enc byte too */
 1367       new->val = op = opt_malloc((5 * addrs) + 1);
 1368       new->flags |= DHOPT_ADDR;
 1369 
 1370       if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) && 
 1371           new->opt == OPTION_SIP_SERVER)
 1372         {
 1373           *(op++) = 1; /* RFC 3361 "enc byte" */
 1374           new->flags &= ~DHOPT_ADDR;
 1375         }
 1376       while (addrs--) 
 1377         {
 1378           cp = comma;
 1379           comma = split(cp);
 1380           slash = split_chr(cp, '/');
 1381           if (!inet_pton(AF_INET, cp, &in))
 1382         goto_err(_("bad IPv4 address"));
 1383           if (!slash)
 1384         {
 1385           memcpy(op, &in, INADDRSZ);
 1386           op += INADDRSZ;
 1387         }
 1388           else
 1389         {
 1390           unsigned char *p = (unsigned char *)&in;
 1391           int netsize = atoi(slash);
 1392           *op++ = netsize;
 1393           if (netsize > 0)
 1394             *op++ = *p++;
 1395           if (netsize > 8)
 1396             *op++ = *p++;
 1397           if (netsize > 16)
 1398             *op++ = *p++;
 1399           if (netsize > 24)
 1400             *op++ = *p++;
 1401           new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
 1402         } 
 1403         }
 1404       new->len = op - new->val;
 1405     }
 1406       else if (is_addr6 && is6)
 1407     {
 1408       unsigned char *op;
 1409       new->val = op = opt_malloc(16 * addrs);
 1410       new->flags |= DHOPT_ADDR6;
 1411       while (addrs--) 
 1412         {
 1413           cp = comma;
 1414           comma = split(cp);
 1415           
 1416           /* check for [1234::7] */
 1417           if (*cp == '[')
 1418         cp++;
 1419           if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
 1420         cp[strlen(cp)-1] = 0;
 1421           
 1422           if (inet_pton(AF_INET6, cp, op))
 1423         {
 1424           op += IN6ADDRSZ;
 1425           continue;
 1426         }
 1427 
 1428           goto_err(_("bad IPv6 address"));
 1429         } 
 1430       new->len = op - new->val;
 1431     }
 1432       else if (is_string)
 1433     {
 1434       /* text arg */
 1435       if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
 1436           !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
 1437         {
 1438           /* dns search, RFC 3397, or SIP, RFC 3361 */
 1439           unsigned char *q, *r, *tail;
 1440           unsigned char *p, *m = NULL, *newp;
 1441           size_t newlen, len = 0;
 1442           int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
 1443           
 1444           arg = comma;
 1445           comma = split(arg);
 1446           
 1447           while (arg && *arg)
 1448         {
 1449           char *in, *dom = NULL;
 1450           size_t domlen = 1;
 1451           /* Allow "." as an empty domain */
 1452           if (strcmp (arg, ".") != 0)
 1453             {
 1454               if (!(dom = canonicalise_opt(arg)))
 1455             goto_err(_("bad domain in dhcp-option"));
 1456             
 1457               domlen = strlen(dom) + 2;
 1458             }
 1459               
 1460           newp = opt_malloc(len + domlen + header_size);
 1461           if (m)
 1462             {
 1463               memcpy(newp, m, header_size + len);
 1464               free(m);
 1465             }
 1466           m = newp;
 1467           p = m + header_size;
 1468           q = p + len;
 1469           
 1470           /* add string on the end in RFC1035 format */
 1471           for (in = dom; in && *in;) 
 1472             {
 1473               unsigned char *cp = q++;
 1474               int j;
 1475               for (j = 0; *in && (*in != '.'); in++, j++)
 1476             *q++ = *in;
 1477               *cp = j;
 1478               if (*in)
 1479             in++;
 1480             }
 1481           *q++ = 0;
 1482           free(dom);
 1483           
 1484           /* Now tail-compress using earlier names. */
 1485           newlen = q - p;
 1486           for (tail = p + len; *tail; tail += (*tail) + 1)
 1487             for (r = p; r - p < (int)len; r += (*r) + 1)
 1488               if (strcmp((char *)r, (char *)tail) == 0)
 1489             {
 1490               PUTSHORT((r - p) | 0xc000, tail); 
 1491               newlen = tail - p;
 1492               goto end;
 1493             }
 1494         end:
 1495           len = newlen;
 1496           
 1497           arg = comma;
 1498           comma = split(arg);
 1499         }
 1500       
 1501           /* RFC 3361, enc byte is zero for names */
 1502           if (new->opt == OPTION_SIP_SERVER && m)
 1503         m[0] = 0;
 1504           new->len = (int) len + header_size;
 1505           new->val = m;
 1506         }
 1507 #ifdef HAVE_DHCP6
 1508       else if (comma && (opt_len & OT_CSTRING))
 1509         {
 1510           /* length fields are two bytes so need 16 bits for each string */
 1511           int i, commas = 1;
 1512           unsigned char *p, *newp;
 1513 
 1514           for (i = 0; comma[i]; i++)
 1515         if (comma[i] == ',')
 1516           commas++;
 1517           
 1518           newp = opt_malloc(strlen(comma)+(2*commas));    
 1519           p = newp;
 1520           arg = comma;
 1521           comma = split(arg);
 1522           
 1523           while (arg && *arg)
 1524         {
 1525           u16 len = strlen(arg);
 1526           unhide_metas(arg);
 1527           PUTSHORT(len, p);
 1528           memcpy(p, arg, len);
 1529           p += len; 
 1530 
 1531           arg = comma;
 1532           comma = split(arg);
 1533         }
 1534 
 1535           new->val = newp;
 1536           new->len = p - newp;
 1537         }
 1538       else if (comma && (opt_len & OT_RFC1035_NAME))
 1539         {
 1540           unsigned char *p = NULL, *q, *newp, *end;
 1541           int len = 0;
 1542           int header_size = (is6 && new->opt == OPTION6_NTP_SERVER) ? 4 : 0;
 1543           arg = comma;
 1544           comma = split(arg);
 1545           
 1546           while (arg && *arg)
 1547         {
 1548           char *dom = canonicalise_opt(arg);
 1549           if (!dom)
 1550             goto_err(_("bad domain in dhcp-option"));
 1551                       
 1552           newp = opt_malloc(len + header_size + strlen(dom) + 2);
 1553           
 1554           if (p)
 1555             {
 1556               memcpy(newp, p, len);
 1557               free(p);
 1558             }
 1559           
 1560           p = newp;
 1561           q = p + len;
 1562           end = do_rfc1035_name(q + header_size, dom, NULL);
 1563           *end++ = 0;
 1564           if (is6 && new->opt == OPTION6_NTP_SERVER)
 1565             {
 1566               PUTSHORT(NTP_SUBOPTION_SRV_FQDN, q);
 1567               PUTSHORT(end - q - 2, q);
 1568             }
 1569           len = end - p;
 1570           free(dom);
 1571 
 1572           arg = comma;
 1573           comma = split(arg);
 1574         }
 1575           
 1576           new->val = p;
 1577           new->len = len;
 1578         }
 1579 #endif
 1580       else
 1581         {
 1582           new->len = strlen(comma);
 1583           /* keep terminating zero on string */
 1584           new->val = (unsigned char *)opt_string_alloc(comma);
 1585           new->flags |= DHOPT_STRING;
 1586         }
 1587     }
 1588     }
 1589 
 1590   if (!is6 && 
 1591       ((new->len > 255) || 
 1592       (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
 1593        (new->len > 250 && (new->flags & DHOPT_RFC3925))))
 1594     goto_err(_("dhcp-option too long"));
 1595   
 1596   if (flags == DHOPT_MATCH)
 1597     {
 1598       if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
 1599       !new->netid ||
 1600       new->netid->next)
 1601     goto_err(_("illegal dhcp-match"));
 1602        
 1603       if (is6)
 1604     {
 1605       new->next = daemon->dhcp_match6;
 1606       daemon->dhcp_match6 = new;
 1607     }
 1608       else
 1609     {
 1610       new->next = daemon->dhcp_match;
 1611       daemon->dhcp_match = new;
 1612     }
 1613     }
 1614   else if (is6)
 1615     {
 1616       new->next = daemon->dhcp_opts6;
 1617       daemon->dhcp_opts6 = new;
 1618     }
 1619   else
 1620     {
 1621       new->next = daemon->dhcp_opts;
 1622       daemon->dhcp_opts = new;
 1623     }
 1624     
 1625   return 1;
 1626 on_error:
 1627   dhcp_opt_free(new);
 1628   return 0;
 1629 }
 1630 
 1631 #endif
 1632 
 1633 void set_option_bool(unsigned int opt)
 1634 {
 1635   option_var(opt) |= option_val(opt);
 1636 }
 1637 
 1638 void reset_option_bool(unsigned int opt)
 1639 {
 1640   option_var(opt) &= ~(option_val(opt));
 1641 }
 1642 
 1643 static void server_list_free(struct server *list)
 1644 {
 1645   while (list)
 1646     {
 1647       struct server *tmp = list;
 1648       list = list->next;
 1649       free(tmp);
 1650     }
 1651 }
 1652 
 1653 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only)
 1654 {      
 1655   int i;
 1656   char *comma;
 1657 
 1658   if (option == '?')
 1659     ret_err(gen_err);
 1660   
 1661   for (i=0; usage[i].opt != 0; i++)
 1662     if (usage[i].opt == option)
 1663       {
 1664      int rept = usage[i].rept;
 1665      
 1666      if (command_line)
 1667        {
 1668          /* command line */
 1669          if (rept == ARG_USED_CL)
 1670            ret_err(_("illegal repeated flag"));
 1671          if (rept == ARG_ONE)
 1672            usage[i].rept = ARG_USED_CL;
 1673        }
 1674      else
 1675        {
 1676          /* allow file to override command line */
 1677          if (rept == ARG_USED_FILE)
 1678            ret_err(_("illegal repeated keyword"));
 1679          if (rept == ARG_USED_CL || rept == ARG_ONE)
 1680            usage[i].rept = ARG_USED_FILE;
 1681        }
 1682 
 1683      if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL) 
 1684        {
 1685          set_option_bool(rept);
 1686          return 1;
 1687        }
 1688        
 1689      break;
 1690       }
 1691   
 1692   switch (option)
 1693     { 
 1694     case 'C': /* --conf-file */
 1695       {
 1696     char *file = opt_string_alloc(arg);
 1697     if (file)
 1698       {
 1699         one_file(file, 0);
 1700         free(file);
 1701       }
 1702     break;
 1703       }
 1704 
 1705     case '7': /* --conf-dir */        
 1706       {
 1707     DIR *dir_stream;
 1708     struct dirent *ent;
 1709     char *directory, *path;
 1710     struct list {
 1711       char *name;
 1712       struct list *next;
 1713     } *ignore_suffix = NULL, *match_suffix = NULL, *files = NULL, *li;
 1714     
 1715     comma = split(arg);
 1716     if (!(directory = opt_string_alloc(arg)))
 1717       break;
 1718     
 1719     for (arg = comma; arg; arg = comma) 
 1720       {
 1721         comma = split(arg);
 1722         if (strlen(arg) != 0)
 1723           {
 1724         li = opt_malloc(sizeof(struct list));
 1725         if (*arg == '*')
 1726           {
 1727             /* "*" with no suffix is a no-op */
 1728             if (arg[1] == 0)
 1729               free(li);
 1730             else
 1731               {
 1732             li->next = match_suffix;
 1733             match_suffix = li;
 1734             /* Have to copy: buffer is overwritten */
 1735             li->name = opt_string_alloc(arg+1);
 1736               }
 1737           }
 1738         else
 1739           {
 1740             li->next = ignore_suffix;
 1741             ignore_suffix = li;
 1742             /* Have to copy: buffer is overwritten */
 1743             li->name = opt_string_alloc(arg);
 1744           }
 1745           }
 1746       }
 1747     
 1748     if (!(dir_stream = opendir(directory)))
 1749       die(_("cannot access directory %s: %s"), directory, EC_FILE);
 1750     
 1751     while ((ent = readdir(dir_stream)))
 1752       {
 1753         size_t len = strlen(ent->d_name);
 1754         struct stat buf;
 1755         
 1756         /* ignore emacs backups and dotfiles */
 1757         if (len == 0 ||
 1758         ent->d_name[len - 1] == '~' ||
 1759         (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
 1760         ent->d_name[0] == '.')
 1761           continue;
 1762 
 1763         if (match_suffix)
 1764           {
 1765         for (li = match_suffix; li; li = li->next)
 1766           {
 1767             /* check for required suffices */
 1768             size_t ls = strlen(li->name);
 1769             if (len > ls &&
 1770             strcmp(li->name, &ent->d_name[len - ls]) == 0)
 1771               break;
 1772           }
 1773         if (!li)
 1774           continue;
 1775           }
 1776         
 1777         for (li = ignore_suffix; li; li = li->next)
 1778           {
 1779         /* check for proscribed suffices */
 1780         size_t ls = strlen(li->name);
 1781         if (len > ls &&
 1782             strcmp(li->name, &ent->d_name[len - ls]) == 0)
 1783           break;
 1784           }
 1785         if (li)
 1786           continue;
 1787         
 1788         path = opt_malloc(strlen(directory) + len + 2);
 1789         strcpy(path, directory);
 1790         strcat(path, "/");
 1791         strcat(path, ent->d_name);
 1792 
 1793         /* files must be readable */
 1794         if (stat(path, &buf) == -1)
 1795           die(_("cannot access %s: %s"), path, EC_FILE);
 1796         
 1797         /* only reg files allowed. */
 1798         if (S_ISREG(buf.st_mode))
 1799           {
 1800         /* sort files into order. */
 1801         struct list **up, *new = opt_malloc(sizeof(struct list));
 1802         new->name = path;
 1803         
 1804         for (up = &files, li = files; li; up = &li->next, li = li->next)
 1805           if (strcmp(li->name, path) >=0)
 1806             break;
 1807 
 1808         new->next = li;
 1809         *up = new;
 1810           }
 1811 
 1812       }
 1813 
 1814     for (li = files; li; li = li->next)
 1815       one_file(li->name, 0);
 1816         
 1817     closedir(dir_stream);
 1818     free(directory);
 1819     for(; ignore_suffix; ignore_suffix = li)
 1820       {
 1821         li = ignore_suffix->next;
 1822         free(ignore_suffix->name);
 1823         free(ignore_suffix);
 1824       }
 1825     for(; match_suffix; match_suffix = li)
 1826       {
 1827         li = match_suffix->next;
 1828         free(match_suffix->name);
 1829         free(match_suffix);
 1830       }
 1831     for(; files; files = li)
 1832       {
 1833         li = files->next;
 1834         free(files->name);
 1835         free(files);
 1836       }
 1837     break;
 1838       }
 1839 
 1840     case LOPT_ADD_SBNET: /* --add-subnet */
 1841       set_option_bool(OPT_CLIENT_SUBNET);
 1842       if (arg)
 1843     {
 1844           char *err, *end;
 1845       comma = split(arg);
 1846 
 1847           struct mysubnet* new = opt_malloc(sizeof(struct mysubnet));
 1848           if ((end = split_chr(arg, '/')))
 1849         {
 1850           /* has subnet+len */
 1851           err = parse_mysockaddr(arg, &new->addr);
 1852           if (err)
 1853         ret_err_free(err, new);
 1854           if (!atoi_check(end, &new->mask))
 1855         ret_err_free(gen_err, new);
 1856           new->addr_used = 1;
 1857         } 
 1858       else if (!atoi_check(arg, &new->mask))
 1859         ret_err_free(gen_err, new);
 1860         
 1861           daemon->add_subnet4 = new;
 1862 
 1863           if (comma)
 1864             {
 1865           new = opt_malloc(sizeof(struct mysubnet));
 1866           if ((end = split_chr(comma, '/')))
 1867         {
 1868           /* has subnet+len */
 1869                   err = parse_mysockaddr(comma, &new->addr);
 1870                   if (err)
 1871                     ret_err_free(err, new);
 1872                   if (!atoi_check(end, &new->mask))
 1873                     ret_err_free(gen_err, new);
 1874                   new->addr_used = 1;
 1875                 }
 1876               else
 1877                 {
 1878                   if (!atoi_check(comma, &new->mask))
 1879                     ret_err_free(gen_err, new);
 1880                 }
 1881           
 1882           daemon->add_subnet6 = new;
 1883         }
 1884     }
 1885       break;
 1886 
 1887     case '1': /* --enable-dbus */
 1888       set_option_bool(OPT_DBUS);
 1889       if (arg)
 1890     daemon->dbus_name = opt_string_alloc(arg);
 1891       else
 1892     daemon->dbus_name = DNSMASQ_SERVICE;
 1893       break;
 1894 
 1895     case LOPT_UBUS: /* --enable-ubus */
 1896       set_option_bool(OPT_UBUS);
 1897       if (arg)
 1898     daemon->ubus_name = opt_string_alloc(arg);
 1899       else
 1900     daemon->ubus_name = DNSMASQ_UBUS_NAME;
 1901       break;
 1902 
 1903     case '8': /* --log-facility */
 1904       /* may be a filename */
 1905       if (strchr(arg, '/') || strcmp (arg, "-") == 0)
 1906     daemon->log_file = opt_string_alloc(arg);
 1907       else
 1908     {     
 1909 #ifdef __ANDROID__
 1910       ret_err(_("setting log facility is not possible under Android"));
 1911 #else
 1912       for (i = 0; facilitynames[i].c_name; i++)
 1913         if (hostname_isequal((char *)facilitynames[i].c_name, arg))
 1914           break;
 1915       
 1916       if (facilitynames[i].c_name)
 1917         daemon->log_fac = facilitynames[i].c_val;
 1918       else
 1919         ret_err(_("bad log facility"));
 1920 #endif
 1921     }
 1922       break;
 1923 
 1924     case 'x': /* --pid-file */
 1925       daemon->runfile = opt_string_alloc(arg);
 1926       break;
 1927 
 1928     case 'r': /* --resolv-file */
 1929       {
 1930     char *name = opt_string_alloc(arg);
 1931     struct resolvc *new, *list = daemon->resolv_files;
 1932     
 1933     if (list && list->is_default)
 1934       {
 1935         /* replace default resolv file - possibly with nothing */
 1936         if (name)
 1937           {
 1938         list->is_default = 0;
 1939         list->name = name;
 1940           }
 1941         else
 1942           list = NULL;
 1943       }
 1944     else if (name)
 1945       {
 1946         new = opt_malloc(sizeof(struct resolvc));
 1947         new->next = list;
 1948         new->name = name;
 1949         new->is_default = 0;
 1950         new->mtime = 0;
 1951         new->logged = 0;
 1952         list = new;
 1953       }
 1954     daemon->resolv_files = list;
 1955     break;
 1956       }
 1957 
 1958     case LOPT_SERVERS_FILE:
 1959       daemon->servers_file = opt_string_alloc(arg);
 1960       break;
 1961       
 1962     case 'm':  /* --mx-host */
 1963       {
 1964     int pref = 1;
 1965     struct mx_srv_record *new;
 1966     char *name, *target = NULL;
 1967 
 1968     if ((comma = split(arg)))
 1969       {
 1970         char *prefstr;
 1971         if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
 1972           ret_err(_("bad MX preference"));
 1973       }
 1974     
 1975     if (!(name = canonicalise_opt(arg)) || 
 1976         (comma && !(target = canonicalise_opt(comma))))
 1977       ret_err(_("bad MX name"));
 1978     
 1979     new = opt_malloc(sizeof(struct mx_srv_record));
 1980     new->next = daemon->mxnames;
 1981     daemon->mxnames = new;
 1982     new->issrv = 0;
 1983     new->name = name;
 1984     new->target = target; /* may be NULL */
 1985     new->weight = pref;
 1986     break;
 1987       }
 1988       
 1989     case 't': /*  --mx-target */
 1990       if (!(daemon->mxtarget = canonicalise_opt(arg)))
 1991     ret_err(_("bad MX target"));
 1992       break;
 1993 
 1994     case LOPT_DUMPFILE:  /* --dumpfile */
 1995       daemon->dump_file = opt_string_alloc(arg);
 1996       break;
 1997 
 1998     case LOPT_DUMPMASK:  /* --dumpmask */
 1999       daemon->dump_mask = strtol(arg, NULL, 0);
 2000       break;
 2001       
 2002 #ifdef HAVE_DHCP      
 2003     case 'l':  /* --dhcp-leasefile */
 2004       daemon->lease_file = opt_string_alloc(arg);
 2005       break;
 2006       
 2007       /* Sorry about the gross pre-processor abuse */
 2008     case '6':             /* --dhcp-script */
 2009     case LOPT_LUASCRIPT:  /* --dhcp-luascript */
 2010 #  if !defined(HAVE_SCRIPT)
 2011       ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts"));
 2012 #  else
 2013       if (option == LOPT_LUASCRIPT)
 2014 #    if !defined(HAVE_LUASCRIPT)
 2015     ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts"));
 2016 #    else
 2017         daemon->luascript = opt_string_alloc(arg);
 2018 #    endif
 2019       else
 2020         daemon->lease_change_command = opt_string_alloc(arg);
 2021 #  endif
 2022       break;
 2023 #endif /* HAVE_DHCP */
 2024 
 2025     case LOPT_DHCP_HOST:     /* --dhcp-hostsfile */
 2026     case LOPT_DHCP_OPTS:     /* --dhcp-optsfile */
 2027     case LOPT_DHCP_INOTIFY:  /* --dhcp-hostsdir */
 2028     case LOPT_DHOPT_INOTIFY: /* --dhcp-optsdir */
 2029     case LOPT_HOST_INOTIFY:  /* --hostsdir */
 2030     case 'H':                /* --addn-hosts */
 2031       {
 2032     struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
 2033     static unsigned int hosts_index = SRC_AH;
 2034     new->fname = opt_string_alloc(arg);
 2035     new->index = hosts_index++;
 2036     new->flags = 0;
 2037     if (option == 'H')
 2038       {
 2039         new->next = daemon->addn_hosts;
 2040         daemon->addn_hosts = new;
 2041       }
 2042     else if (option == LOPT_DHCP_HOST)
 2043       {
 2044         new->next = daemon->dhcp_hosts_file;
 2045         daemon->dhcp_hosts_file = new;
 2046       }
 2047     else if (option == LOPT_DHCP_OPTS)
 2048       {
 2049         new->next = daemon->dhcp_opts_file;
 2050         daemon->dhcp_opts_file = new;
 2051       }       
 2052     else 
 2053       {
 2054         new->next = daemon->dynamic_dirs;
 2055         daemon->dynamic_dirs = new; 
 2056         if (option == LOPT_DHCP_INOTIFY)
 2057           new->flags |= AH_DHCP_HST;
 2058         else if (option == LOPT_DHOPT_INOTIFY)
 2059           new->flags |= AH_DHCP_OPT;
 2060         else if (option == LOPT_HOST_INOTIFY)
 2061           new->flags |= AH_HOSTS;
 2062       }
 2063     
 2064     break;
 2065       }
 2066       
 2067     case LOPT_AUTHSERV: /* --auth-server */
 2068       comma = split(arg);
 2069       
 2070       daemon->authserver = opt_string_alloc(arg);
 2071       
 2072       while ((arg = comma))
 2073     {
 2074       struct iname *new = opt_malloc(sizeof(struct iname));
 2075       comma = split(arg);
 2076       new->name = NULL;
 2077       unhide_metas(arg);
 2078       if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
 2079         new->addr.sa.sa_family = AF_INET;
 2080       else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
 2081         new->addr.sa.sa_family = AF_INET6;
 2082       else
 2083         {
 2084           char *fam = split_chr(arg, '/');
 2085           new->name = opt_string_alloc(arg);
 2086           new->addr.sa.sa_family = 0;
 2087           if (fam)
 2088         {
 2089           if (strcmp(fam, "4") == 0)
 2090             new->addr.sa.sa_family = AF_INET;
 2091           else if (strcmp(fam, "6") == 0)
 2092             new->addr.sa.sa_family = AF_INET6;
 2093           else
 2094           {
 2095             free(new->name);
 2096             ret_err_free(gen_err, new);
 2097           }
 2098         } 
 2099         }
 2100       new->next = daemon->authinterface;
 2101       daemon->authinterface = new;
 2102     };
 2103             
 2104       break;
 2105 
 2106     case LOPT_AUTHSFS: /* --auth-sec-servers */
 2107       {
 2108     struct name_list *new;
 2109 
 2110     do {
 2111       comma = split(arg);
 2112       new = opt_malloc(sizeof(struct name_list));
 2113       new->name = opt_string_alloc(arg);
 2114       new->next = daemon->secondary_forward_server;
 2115       daemon->secondary_forward_server = new;
 2116       arg = comma;
 2117     } while (arg);
 2118     break;
 2119       }
 2120     
 2121     case LOPT_AUTHZONE: /* --auth-zone */
 2122       {
 2123     struct auth_zone *new;
 2124     
 2125     comma = split(arg);
 2126         
 2127     new = opt_malloc(sizeof(struct auth_zone));
 2128     new->domain = opt_string_alloc(arg);
 2129     new->subnet = NULL;
 2130     new->exclude = NULL;
 2131     new->interface_names = NULL;
 2132     new->next = daemon->auth_zones;
 2133     daemon->auth_zones = new;
 2134 
 2135     while ((arg = comma))
 2136       {
 2137         int prefixlen = 0;
 2138         int is_exclude = 0;
 2139         char *prefix;
 2140         struct addrlist *subnet =  NULL;
 2141         union all_addr addr;
 2142 
 2143         comma = split(arg);
 2144         prefix = split_chr(arg, '/');
 2145         
 2146         if (prefix && !atoi_check(prefix, &prefixlen))
 2147           ret_err(gen_err);
 2148         
 2149         if (strstr(arg, "exclude:") == arg)
 2150           {
 2151             is_exclude = 1;
 2152             arg = arg+8;
 2153           }
 2154 
 2155         if (inet_pton(AF_INET, arg, &addr.addr4))
 2156           {
 2157         subnet = opt_malloc(sizeof(struct addrlist));
 2158         subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
 2159         subnet->flags = ADDRLIST_LITERAL;
 2160           }
 2161         else if (inet_pton(AF_INET6, arg, &addr.addr6))
 2162           {
 2163         subnet = opt_malloc(sizeof(struct addrlist));
 2164         subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
 2165         subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
 2166           }
 2167         else 
 2168           {
 2169         struct auth_name_list *name =  opt_malloc(sizeof(struct auth_name_list));
 2170         name->name = opt_string_alloc(arg);
 2171         name->flags = AUTH4 | AUTH6;
 2172         name->next = new->interface_names;
 2173         new->interface_names = name;
 2174         if (prefix)
 2175           {
 2176             if (prefixlen == 4)
 2177               name->flags &= ~AUTH6;
 2178             else if (prefixlen == 6)
 2179               name->flags &= ~AUTH4;
 2180             else
 2181               ret_err(gen_err);
 2182           }
 2183           }
 2184         
 2185         if (subnet)
 2186           {
 2187         subnet->addr = addr;
 2188 
 2189         if (is_exclude)
 2190           {
 2191             subnet->next = new->exclude;
 2192             new->exclude = subnet;
 2193           }
 2194         else
 2195           {
 2196             subnet->next = new->subnet;
 2197             new->subnet = subnet;
 2198           }
 2199           }
 2200       }
 2201     break;
 2202       }
 2203       
 2204     case  LOPT_AUTHSOA: /* --auth-soa */
 2205       comma = split(arg);
 2206       daemon->soa_sn = (u32)atoi(arg);
 2207       if (comma)
 2208     {
 2209       char *cp;
 2210       arg = comma;
 2211       comma = split(arg);
 2212       daemon->hostmaster = opt_string_alloc(arg);
 2213       for (cp = daemon->hostmaster; *cp; cp++)
 2214         if (*cp == '@')
 2215           *cp = '.';
 2216 
 2217       if (comma)
 2218         {
 2219           arg = comma;
 2220           comma = split(arg); 
 2221           daemon->soa_refresh = (u32)atoi(arg);
 2222           if (comma)
 2223         {
 2224           arg = comma;
 2225           comma = split(arg); 
 2226           daemon->soa_retry = (u32)atoi(arg);
 2227           if (comma)
 2228             daemon->soa_expiry = (u32)atoi(comma);
 2229         }
 2230         }
 2231     }
 2232 
 2233       break;
 2234 
 2235     case 's':         /* --domain */
 2236     case LOPT_SYNTH:  /* --synth-domain */
 2237       if (strcmp (arg, "#") == 0)
 2238     set_option_bool(OPT_RESOLV_DOMAIN);
 2239       else
 2240     {
 2241       char *d;
 2242       comma = split(arg);
 2243       if (!(d = canonicalise_opt(arg)))
 2244         ret_err(gen_err);
 2245       else
 2246         {
 2247           if (comma)
 2248         {
 2249           struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
 2250           char *netpart;
 2251           
 2252           new->prefix = NULL;
 2253           new->indexed = 0;
 2254           
 2255           unhide_metas(comma);
 2256           if ((netpart = split_chr(comma, '/')))
 2257             {
 2258               int msize;
 2259 
 2260               arg = split(netpart);
 2261               if (!atoi_check(netpart, &msize))
 2262             ret_err_free(gen_err, new);
 2263               else if (inet_pton(AF_INET, comma, &new->start))
 2264             {
 2265               int mask = (1 << (32 - msize)) - 1;
 2266               new->is6 = 0;               
 2267               new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
 2268               new->end.s_addr = new->start.s_addr | htonl(mask);
 2269               if (arg)
 2270                 {
 2271                   if (option != 's')
 2272                 {
 2273                   if (!(new->prefix = canonicalise_opt(arg)) ||
 2274                       strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
 2275                     ret_err_free(_("bad prefix"), new);
 2276                 }
 2277                   else if (strcmp(arg, "local") != 0 ||
 2278                        (msize != 8 && msize != 16 && msize != 24))
 2279                 ret_err_free(gen_err, new);
 2280                   else
 2281                 {
 2282                    /* generate the equivalent of
 2283                       local=/xxx.yyy.zzz.in-addr.arpa/ */
 2284                   struct server *serv = add_rev4(new->start, msize);
 2285                   if (!serv)
 2286                     ret_err_free(_("bad prefix"), new);
 2287 
 2288                   serv->flags |= SERV_NO_ADDR;
 2289 
 2290                   /* local=/<domain>/ */
 2291                   serv = opt_malloc(sizeof(struct server));
 2292                   memset(serv, 0, sizeof(struct server));
 2293                   serv->domain = d;
 2294                   serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
 2295                   serv->next = daemon->servers;
 2296                   daemon->servers = serv;
 2297                 }
 2298                 }
 2299             }
 2300               else if (inet_pton(AF_INET6, comma, &new->start6))
 2301             {
 2302               u64 mask = (1LLU << (128 - msize)) - 1LLU;
 2303               u64 addrpart = addr6part(&new->start6);
 2304               new->is6 = 1;
 2305               
 2306               /* prefix==64 overflows the mask calculation above */
 2307               if (msize == 64)
 2308                 mask = (u64)-1LL;
 2309               
 2310               new->end6 = new->start6;
 2311               setaddr6part(&new->start6, addrpart & ~mask);
 2312               setaddr6part(&new->end6, addrpart | mask);
 2313               
 2314               if (msize < 64)
 2315                 ret_err_free(gen_err, new);
 2316               else if (arg)
 2317                 {
 2318                   if (option != 's')
 2319                 {
 2320                   if (!(new->prefix = canonicalise_opt(arg)) ||
 2321                       strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
 2322                     ret_err_free(_("bad prefix"), new);
 2323                 }   
 2324                   else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
 2325                 ret_err_free(gen_err, new);
 2326                   else 
 2327                 {
 2328                   /* generate the equivalent of
 2329                      local=/xxx.yyy.zzz.ip6.arpa/ */
 2330                   struct server *serv = add_rev6(&new->start6, msize);
 2331                   serv->flags |= SERV_NO_ADDR;
 2332                   
 2333                   /* local=/<domain>/ */
 2334                   serv = opt_malloc(sizeof(struct server));
 2335                   memset(serv, 0, sizeof(struct server));
 2336                   serv->domain = d;
 2337                   serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
 2338                   serv->next = daemon->servers;
 2339                   daemon->servers = serv;
 2340                 }
 2341                 }
 2342             }
 2343               else
 2344             ret_err_free(gen_err, new);
 2345             }
 2346           else
 2347             {
 2348               char *prefstr;
 2349               arg = split(comma);
 2350               prefstr = split(arg);
 2351 
 2352               if (inet_pton(AF_INET, comma, &new->start))
 2353             {
 2354               new->is6 = 0;
 2355               if (!arg)
 2356                 new->end.s_addr = new->start.s_addr;
 2357               else if (!inet_pton(AF_INET, arg, &new->end))
 2358                 ret_err_free(gen_err, new);
 2359             }
 2360               else if (inet_pton(AF_INET6, comma, &new->start6))
 2361             {
 2362               new->is6 = 1;
 2363               if (!arg)
 2364                 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
 2365               else if (!inet_pton(AF_INET6, arg, &new->end6))
 2366                 ret_err_free(gen_err, new);
 2367             }
 2368               else 
 2369             ret_err_free(gen_err, new);
 2370 
 2371               if (option != 's' && prefstr)
 2372             {
 2373               if (!(new->prefix = canonicalise_opt(prefstr)) ||
 2374                   strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
 2375                 ret_err_free(_("bad prefix"), new);
 2376             }
 2377             }
 2378 
 2379           new->domain = d;
 2380           if (option  == 's')
 2381             {
 2382               new->next = daemon->cond_domain;
 2383               daemon->cond_domain = new;
 2384             }
 2385           else
 2386             {
 2387               char *star;
 2388               new->next = daemon->synth_domains;
 2389               daemon->synth_domains = new;
 2390               if (new->prefix &&
 2391               (star = strrchr(new->prefix, '*'))
 2392               && *(star+1) == 0)
 2393             {
 2394               *star = 0;
 2395               new->indexed = 1;
 2396             }
 2397             }
 2398         }
 2399           else if (option == 's')
 2400         daemon->domain_suffix = d;
 2401           else 
 2402         ret_err(gen_err);
 2403         }
 2404     }
 2405       break;
 2406       
 2407     case LOPT_CPE_ID: /* --add-dns-client */
 2408       if (arg)
 2409     daemon->dns_client_id = opt_string_alloc(arg);
 2410       break;
 2411 
 2412     case LOPT_ADD_MAC: /* --add-mac */
 2413       if (!arg)
 2414     set_option_bool(OPT_ADD_MAC);
 2415       else
 2416     {
 2417       unhide_metas(arg);
 2418       if (strcmp(arg, "base64") == 0)
 2419         set_option_bool(OPT_MAC_B64);
 2420       else if (strcmp(arg, "text") == 0)
 2421         set_option_bool(OPT_MAC_HEX);
 2422       else
 2423         ret_err(gen_err);
 2424     }
 2425       break;
 2426 
 2427     case 'u':  /* --user */
 2428       daemon->username = opt_string_alloc(arg);
 2429       break;
 2430       
 2431     case 'g':  /* --group */
 2432       daemon->groupname = opt_string_alloc(arg);
 2433       daemon->group_set = 1;
 2434       break;
 2435 
 2436 #ifdef HAVE_DHCP
 2437     case LOPT_SCRIPTUSR: /* --scriptuser */
 2438       daemon->scriptuser = opt_string_alloc(arg);
 2439       break;
 2440 #endif
 2441       
 2442     case 'i':  /* --interface */
 2443       do {
 2444     struct iname *new = opt_malloc(sizeof(struct iname));
 2445     comma = split(arg);
 2446     new->next = daemon->if_names;
 2447     daemon->if_names = new;
 2448     /* new->name may be NULL if someone does
 2449        "interface=" to disable all interfaces except loop. */
 2450     new->name = opt_string_alloc(arg);
 2451     new->used = 0;
 2452     arg = comma;
 2453       } while (arg);
 2454       break;
 2455       
 2456     case LOPT_TFTP: /* --enable-tftp */
 2457       set_option_bool(OPT_TFTP);
 2458       if (!arg)
 2459     break;
 2460       /* fall through */
 2461 
 2462     case 'I':  /* --except-interface */
 2463     case '2':  /* --no-dhcp-interface */
 2464       do {
 2465     struct iname *new = opt_malloc(sizeof(struct iname));
 2466     comma = split(arg);
 2467     new->name = opt_string_alloc(arg);
 2468     if (option == 'I')
 2469       {
 2470         new->next = daemon->if_except;
 2471         daemon->if_except = new;
 2472       }
 2473     else if (option == LOPT_TFTP)
 2474        {
 2475         new->next = daemon->tftp_interfaces;
 2476         daemon->tftp_interfaces = new;
 2477       }
 2478     else
 2479       {
 2480         new->next = daemon->dhcp_except;
 2481         daemon->dhcp_except = new;
 2482       }
 2483     arg = comma;
 2484       } while (arg);
 2485       break;
 2486       
 2487     case 'B':  /* --bogus-nxdomain */
 2488     case LOPT_IGNORE_ADDR: /* --ignore-address */
 2489      {
 2490     struct in_addr addr;
 2491     int prefix = 32;
 2492     unhide_metas(arg);
 2493 
 2494     if (!arg ||
 2495         ((comma = split_chr(arg, '/')) && !atoi_check(comma, &prefix)) ||
 2496         (inet_pton(AF_INET, arg, &addr) != 1))
 2497       ret_err(gen_err); /* error */
 2498     else
 2499       {
 2500         struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
 2501         if (option == 'B')
 2502           {
 2503         baddr->next = daemon->bogus_addr;
 2504         daemon->bogus_addr = baddr;
 2505           }
 2506         else
 2507           {
 2508         baddr->next = daemon->ignore_addr;
 2509         daemon->ignore_addr = baddr;
 2510           }
 2511         baddr->mask.s_addr = htonl(~((1 << (32 - prefix)) - 1));
 2512         baddr->addr.s_addr = addr.s_addr & baddr->mask.s_addr;
 2513       }
 2514     break;
 2515      }
 2516       
 2517     case 'a':  /* --listen-address */
 2518     case LOPT_AUTHPEER: /* --auth-peer */
 2519       do {
 2520     struct iname *new = opt_malloc(sizeof(struct iname));
 2521     comma = split(arg);
 2522     unhide_metas(arg);
 2523     if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
 2524       {
 2525         new->addr.sa.sa_family = AF_INET;
 2526         new->addr.in.sin_port = 0;
 2527 #ifdef HAVE_SOCKADDR_SA_LEN
 2528         new->addr.in.sin_len = sizeof(new->addr.in);
 2529 #endif
 2530       }
 2531     else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
 2532       {
 2533         new->addr.sa.sa_family = AF_INET6;
 2534         new->addr.in6.sin6_flowinfo = 0;
 2535         new->addr.in6.sin6_scope_id = 0;
 2536         new->addr.in6.sin6_port = 0;
 2537 #ifdef HAVE_SOCKADDR_SA_LEN
 2538         new->addr.in6.sin6_len = sizeof(new->addr.in6);
 2539 #endif
 2540       }
 2541     else
 2542       ret_err_free(gen_err, new);
 2543 
 2544     new->used = 0;
 2545     if (option == 'a')
 2546       {
 2547         new->next = daemon->if_addrs;
 2548         daemon->if_addrs = new;
 2549       }
 2550     else
 2551       {
 2552         new->next = daemon->auth_peers;
 2553         daemon->auth_peers = new;
 2554       } 
 2555     arg = comma;
 2556       } while (arg);
 2557       break;
 2558       
 2559     case 'S':            /*  --server */
 2560     case LOPT_LOCAL:     /*  --local */
 2561     case 'A':            /*  --address */
 2562     case LOPT_NO_REBIND: /*  --rebind-domain-ok */
 2563       {
 2564     struct server *serv, *newlist = NULL;
 2565     
 2566     unhide_metas(arg);
 2567     
 2568     if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
 2569       {
 2570         int rebind = !(*arg == '/');
 2571         char *end = NULL;
 2572         if (!rebind)
 2573           arg++;
 2574         while (rebind || (end = split_chr(arg, '/')))
 2575           {
 2576         char *domain = NULL;
 2577         /* elide leading dots - they are implied in the search algorithm */
 2578         while (*arg == '.') arg++;
 2579         /* # matches everything and becomes a zero length domain string */
 2580         if (strcmp(arg, "#") == 0)
 2581           domain = "";
 2582         else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
 2583           ret_err(gen_err);
 2584         serv = opt_malloc(sizeof(struct server));
 2585         memset(serv, 0, sizeof(struct server));
 2586         serv->next = newlist;
 2587         newlist = serv;
 2588         serv->domain = domain;
 2589         serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
 2590         arg = end;
 2591         if (rebind)
 2592           break;
 2593           }
 2594         if (!newlist)
 2595           ret_err(gen_err);
 2596       }
 2597     else
 2598       {
 2599         newlist = opt_malloc(sizeof(struct server));
 2600         memset(newlist, 0, sizeof(struct server));
 2601 #ifdef HAVE_LOOP
 2602         newlist->uid = rand32();
 2603 #endif
 2604       }
 2605     
 2606     if (servers_only && option == 'S')
 2607       newlist->flags |= SERV_FROM_FILE;
 2608     
 2609     if (option == 'A')
 2610       {
 2611         newlist->flags |= SERV_LITERAL_ADDRESS;
 2612         if (!(newlist->flags & SERV_TYPE))
 2613           {
 2614             server_list_free(newlist);
 2615             ret_err(gen_err);
 2616           }
 2617       }
 2618     else if (option == LOPT_NO_REBIND)
 2619       newlist->flags |= SERV_NO_REBIND;
 2620     
 2621     if (!arg || !*arg)
 2622       {
 2623         if (!(newlist->flags & SERV_NO_REBIND))
 2624           newlist->flags |= SERV_NO_ADDR; /* no server */
 2625       }
 2626 
 2627     else if (strcmp(arg, "#") == 0)
 2628       newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
 2629     else
 2630       {
 2631         char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
 2632         if (err)
 2633           {
 2634             server_list_free(newlist);
 2635             ret_err(err);
 2636           }
 2637       }
 2638     
 2639     serv = newlist;
 2640     while (serv->next)
 2641       {
 2642         serv->next->flags |= serv->flags & ~(SERV_HAS_DOMAIN | SERV_FOR_NODOTS);
 2643         serv->next->addr = serv->addr;
 2644         serv->next->source_addr = serv->source_addr;
 2645         strcpy(serv->next->interface, serv->interface);
 2646         serv = serv->next;
 2647       }
 2648     serv->next = daemon->servers;
 2649     daemon->servers = newlist;
 2650     break;
 2651       }
 2652 
 2653     case LOPT_REV_SERV: /* --rev-server */
 2654       {
 2655     char *string;
 2656     int size;
 2657     struct server *serv;
 2658     struct in_addr addr4;
 2659     struct in6_addr addr6;
 2660  
 2661     unhide_metas(arg);
 2662     if (!arg)
 2663       ret_err(gen_err);
 2664     
 2665     comma=split(arg);
 2666 
 2667     if (!(string = split_chr(arg, '/')) || !atoi_check(string, &size))
 2668       ret_err(gen_err);
 2669     
 2670     if (inet_pton(AF_INET, arg, &addr4))
 2671       {
 2672         serv = add_rev4(addr4, size);
 2673         if (!serv)
 2674           ret_err(_("bad prefix"));
 2675       }
 2676     else if (inet_pton(AF_INET6, arg, &addr6))
 2677       serv = add_rev6(&addr6, size);
 2678     else
 2679       ret_err(gen_err);
 2680  
 2681     string = parse_server(comma, &serv->addr, &serv->source_addr, serv->interface, &serv->flags);
 2682     
 2683     if (string)
 2684       ret_err(string);
 2685     
 2686     if (servers_only)
 2687       serv->flags |= SERV_FROM_FILE;
 2688     
 2689     break;
 2690       }
 2691 
 2692     case LOPT_IPSET: /* --ipset */
 2693 #ifndef HAVE_IPSET
 2694       ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
 2695       break;
 2696 #else
 2697       {
 2698      struct ipsets ipsets_head;
 2699      struct ipsets *ipsets = &ipsets_head;
 2700      int size;
 2701      char *end;
 2702      char **sets, **sets_pos;
 2703      memset(ipsets, 0, sizeof(struct ipsets));
 2704      unhide_metas(arg);
 2705      if (arg && *arg == '/') 
 2706        {
 2707          arg++;
 2708          while ((end = split_chr(arg, '/'))) 
 2709            {
 2710          char *domain = NULL;
 2711          /* elide leading dots - they are implied in the search algorithm */
 2712          while (*arg == '.')
 2713            arg++;
 2714          /* # matches everything and becomes a zero length domain string */
 2715          if (strcmp(arg, "#") == 0 || !*arg)
 2716            domain = "";
 2717          else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
 2718            ret_err(gen_err);
 2719          ipsets->next = opt_malloc(sizeof(struct ipsets));
 2720          ipsets = ipsets->next;
 2721          memset(ipsets, 0, sizeof(struct ipsets));
 2722          ipsets->domain = domain;
 2723          arg = end;
 2724            }
 2725        } 
 2726      else 
 2727        {
 2728          ipsets->next = opt_malloc(sizeof(struct ipsets));
 2729          ipsets = ipsets->next;
 2730          memset(ipsets, 0, sizeof(struct ipsets));
 2731          ipsets->domain = "";
 2732        }
 2733      
 2734      if (!arg || !*arg)
 2735        ret_err(gen_err);
 2736      
 2737      for (size = 2, end = arg; *end; ++end) 
 2738        if (*end == ',')
 2739            ++size;
 2740      
 2741      sets = sets_pos = opt_malloc(sizeof(char *) * size);
 2742      
 2743      do {
 2744        end = split(arg);
 2745        *sets_pos++ = opt_string_alloc(arg);
 2746        arg = end;
 2747      } while (end);
 2748      *sets_pos = 0;
 2749      for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
 2750        ipsets->next->sets = sets;
 2751      ipsets->next = daemon->ipsets;
 2752      daemon->ipsets = ipsets_head.next;
 2753      
 2754      break;
 2755       }
 2756 #endif
 2757       
 2758     case 'c':  /* --cache-size */
 2759       {
 2760     int size;
 2761     
 2762     if (!atoi_check(arg, &size))
 2763       ret_err(gen_err);
 2764     else
 2765       {
 2766         /* zero is OK, and means no caching. */
 2767         
 2768         if (size < 0)
 2769           size = 0;
 2770 
 2771         /* Note that for very large cache sizes, the malloc()
 2772            will overflow. For the size of the cache record
 2773            at the time this was noted, the value of "very large"
 2774                was 46684428. Limit to an order of magnitude less than
 2775            that to be safe from changes to the cache record. */
 2776         if (size > 5000000)
 2777           size = 5000000;
 2778         
 2779         daemon->cachesize = size;
 2780       }
 2781     break;
 2782       }
 2783       
 2784     case 'p':  /* --port */
 2785       if (!atoi_check16(arg, &daemon->port))
 2786     ret_err(gen_err);
 2787       break;
 2788     
 2789     case LOPT_MINPORT:  /* --min-port */
 2790       if (!atoi_check16(arg, &daemon->min_port))
 2791     ret_err(gen_err);
 2792       break;
 2793 
 2794     case LOPT_MAXPORT:  /* --max-port */
 2795       if (!atoi_check16(arg, &daemon->max_port))
 2796     ret_err(gen_err);
 2797       break;
 2798 
 2799     case '0':  /* --dns-forward-max */
 2800       if (!atoi_check(arg, &daemon->ftabsize))
 2801     ret_err(gen_err);
 2802       break;  
 2803     
 2804     case 'q': /* --log-queries */
 2805       set_option_bool(OPT_LOG);
 2806       if (arg && strcmp(arg, "extra") == 0)
 2807     set_option_bool(OPT_EXTRALOG);
 2808       break;
 2809 
 2810     case LOPT_MAX_LOGS:  /* --log-async */
 2811       daemon->max_logs = LOG_MAX; /* default */
 2812       if (arg && !atoi_check(arg, &daemon->max_logs))
 2813     ret_err(gen_err);
 2814       else if (daemon->max_logs > 100)
 2815     daemon->max_logs = 100;
 2816       break;  
 2817 
 2818     case 'P': /* --edns-packet-max */
 2819       {
 2820     int i;
 2821     if (!atoi_check(arg, &i))
 2822       ret_err(gen_err);
 2823     daemon->edns_pktsz = (unsigned short)i; 
 2824     break;
 2825       }
 2826       
 2827     case 'Q':  /* --query-port */
 2828       if (!atoi_check16(arg, &daemon->query_port))
 2829     ret_err(gen_err);
 2830       /* if explicitly set to zero, use single OS ephemeral port
 2831      and disable random ports */
 2832       if (daemon->query_port == 0)
 2833     daemon->osport = 1;
 2834       break;
 2835       
 2836     case 'T':         /* --local-ttl */
 2837     case LOPT_NEGTTL: /* --neg-ttl */
 2838     case LOPT_MAXTTL: /* --max-ttl */
 2839     case LOPT_MINCTTL: /* --min-cache-ttl */
 2840     case LOPT_MAXCTTL: /* --max-cache-ttl */
 2841     case LOPT_AUTHTTL: /* --auth-ttl */
 2842     case LOPT_DHCPTTL: /* --dhcp-ttl */
 2843       {
 2844     int ttl;
 2845     if (!atoi_check(arg, &ttl))
 2846       ret_err(gen_err);
 2847     else if (option == LOPT_NEGTTL)
 2848       daemon->neg_ttl = (unsigned long)ttl;
 2849     else if (option == LOPT_MAXTTL)
 2850       daemon->max_ttl = (unsigned long)ttl;
 2851     else if (option == LOPT_MINCTTL)
 2852       {
 2853         if (ttl > TTL_FLOOR_LIMIT)
 2854           ttl = TTL_FLOOR_LIMIT;
 2855         daemon->min_cache_ttl = (unsigned long)ttl;
 2856       }
 2857     else if (option == LOPT_MAXCTTL)
 2858       daemon->max_cache_ttl = (unsigned long)ttl;
 2859     else if (option == LOPT_AUTHTTL)
 2860       daemon->auth_ttl = (unsigned long)ttl;
 2861     else if (option == LOPT_DHCPTTL)
 2862       {
 2863         daemon->dhcp_ttl = (unsigned long)ttl;
 2864         daemon->use_dhcp_ttl = 1;
 2865       }
 2866     else
 2867       daemon->local_ttl = (unsigned long)ttl;
 2868     break;
 2869       }
 2870       
 2871 #ifdef HAVE_DHCP
 2872     case 'X': /* --dhcp-lease-max */
 2873       if (!atoi_check(arg, &daemon->dhcp_max))
 2874     ret_err(gen_err);
 2875       break;
 2876 #endif
 2877       
 2878 #ifdef HAVE_TFTP
 2879     case LOPT_TFTP_MAX:  /*  --tftp-max */
 2880       if (!atoi_check(arg, &daemon->tftp_max))
 2881     ret_err(gen_err);
 2882       break;  
 2883 
 2884     case LOPT_TFTP_MTU:  /*  --tftp-mtu */
 2885       if (!atoi_check(arg, &daemon->tftp_mtu))
 2886     ret_err(gen_err);
 2887       break;
 2888 
 2889     case LOPT_PREFIX: /* --tftp-prefix */
 2890       comma = split(arg);
 2891       if (comma)
 2892     {
 2893       struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
 2894       new->interface = opt_string_alloc(comma);
 2895       new->prefix = opt_string_alloc(arg);
 2896       new->next = daemon->if_prefix;
 2897       daemon->if_prefix = new;
 2898     }
 2899       else
 2900     daemon->tftp_prefix = opt_string_alloc(arg);
 2901       break;
 2902 
 2903     case LOPT_TFTPPORTS: /* --tftp-port-range */
 2904       if (!(comma = split(arg)) || 
 2905       !atoi_check16(arg, &daemon->start_tftp_port) ||
 2906       !atoi_check16(comma, &daemon->end_tftp_port))
 2907     ret_err(_("bad port range"));
 2908       
 2909       if (daemon->start_tftp_port > daemon->end_tftp_port)
 2910     {
 2911       int tmp = daemon->start_tftp_port;
 2912       daemon->start_tftp_port = daemon->end_tftp_port;
 2913       daemon->end_tftp_port = tmp;
 2914     } 
 2915       
 2916       break;
 2917 
 2918     case LOPT_APREF: /* --tftp-unique-root */
 2919       if (!arg || strcasecmp(arg, "ip") == 0)
 2920         set_option_bool(OPT_TFTP_APREF_IP);
 2921       else if (strcasecmp(arg, "mac") == 0)
 2922         set_option_bool(OPT_TFTP_APREF_MAC);
 2923       else
 2924         ret_err(gen_err);
 2925       break;
 2926 #endif
 2927           
 2928     case LOPT_BRIDGE:   /* --bridge-interface */
 2929       {
 2930     struct dhcp_bridge *new;
 2931 
 2932     if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
 2933       ret_err(_("bad bridge-interface"));
 2934 
 2935     for (new = daemon->bridges; new; new = new->next)
 2936       if (strcmp(new->iface, arg) == 0)
 2937         break;
 2938 
 2939     if (!new)
 2940       {
 2941          new = opt_malloc(sizeof(struct dhcp_bridge));
 2942          strcpy(new->iface, arg);
 2943          new->alias = NULL;
 2944          new->next = daemon->bridges;
 2945          daemon->bridges = new;
 2946       }
 2947     
 2948     do {
 2949       arg = comma;
 2950       comma = split(arg);
 2951       if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
 2952         {
 2953           struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge)); 
 2954           b->next = new->alias;
 2955           new->alias = b;
 2956           strcpy(b->iface, arg);
 2957         }
 2958     } while (comma);
 2959     
 2960     break;
 2961       }
 2962 
 2963 #ifdef HAVE_DHCP
 2964     case LOPT_SHARED_NET: /* --shared-network */
 2965       {
 2966     struct shared_network *new = opt_malloc(sizeof(struct shared_network));
 2967 
 2968 #ifdef HAVE_DHCP6
 2969     new->shared_addr.s_addr = 0;
 2970 #endif
 2971     new->if_index = 0;
 2972     
 2973     if (!(comma = split(arg)))
 2974       {
 2975       snerr:
 2976         free(new);
 2977         ret_err(_("bad shared-network"));
 2978       }
 2979     
 2980     if (inet_pton(AF_INET, comma, &new->shared_addr))
 2981       {
 2982         if (!inet_pton(AF_INET, arg, &new->match_addr) &&
 2983         !(new->if_index = if_nametoindex(arg)))
 2984           goto snerr;
 2985       }
 2986 #ifdef HAVE_DHCP6
 2987     else if (inet_pton(AF_INET6, comma, &new->shared_addr6))
 2988       {
 2989         if (!inet_pton(AF_INET6, arg, &new->match_addr6) &&
 2990         !(new->if_index = if_nametoindex(arg)))
 2991           goto snerr;
 2992       }
 2993 #endif
 2994     else
 2995       goto snerr;
 2996 
 2997     new->next = daemon->shared_networks;
 2998     daemon->shared_networks = new;
 2999     break;
 3000       }
 3001       
 3002     case 'F':  /* --dhcp-range */
 3003       {
 3004     int k, leasepos = 2;
 3005     char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
 3006     struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
 3007     
 3008     memset (new, 0, sizeof(*new));
 3009     
 3010     while(1)
 3011       {
 3012         for (cp = arg; *cp; cp++)
 3013           if (!(*cp == ' ' || *cp == '.' || *cp == ':' || 
 3014             (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
 3015             (*cp >='0' && *cp <= '9')))
 3016         break;
 3017         
 3018         if (*cp != ',' && (comma = split(arg)))
 3019           {
 3020         if (is_tag_prefix(arg))
 3021           {
 3022             /* ignore empty tag */
 3023             if (arg[4])
 3024               new->filter = dhcp_netid_create(arg+4, new->filter);
 3025           }
 3026         else
 3027           {
 3028             if (new->netid.net)
 3029               {
 3030             dhcp_context_free(new);
 3031             ret_err(_("only one tag allowed"));
 3032               }
 3033             else
 3034               new->netid.net = opt_string_alloc(set_prefix(arg));
 3035           }
 3036         arg = comma;
 3037           }
 3038         else
 3039           {
 3040         a[0] = arg;
 3041         break;
 3042           }
 3043       }
 3044     
 3045     for (k = 1; k < 8; k++)
 3046       if (!(a[k] = split(a[k-1])))
 3047         break;
 3048     
 3049     if (k < 2)
 3050       {
 3051         dhcp_context_free(new);
 3052         ret_err(_("bad dhcp-range"));
 3053       }
 3054     
 3055     if (inet_pton(AF_INET, a[0], &new->start))
 3056       {
 3057         new->next = daemon->dhcp;
 3058         new->lease_time = DEFLEASE;
 3059         daemon->dhcp = new;
 3060         new->end = new->start;
 3061         if (strcmp(a[1], "static") == 0)
 3062           new->flags |= CONTEXT_STATIC;
 3063         else if (strcmp(a[1], "proxy") == 0)
 3064           new->flags |= CONTEXT_PROXY;
 3065         else if (!inet_pton(AF_INET, a[1], &new->end))
 3066           {
 3067         dhcp_context_free(new);
 3068         ret_err(_("bad dhcp-range"));
 3069           }
 3070         
 3071         if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
 3072           {
 3073         struct in_addr tmp = new->start;
 3074         new->start = new->end;
 3075         new->end = tmp;
 3076           }
 3077         
 3078         if (k >= 3 && strchr(a[2], '.') &&  
 3079         (inet_pton(AF_INET, a[2], &new->netmask) > 0))
 3080           {
 3081         new->flags |= CONTEXT_NETMASK;
 3082         leasepos = 3;
 3083         if (!is_same_net(new->start, new->end, new->netmask))
 3084           {
 3085             dhcp_context_free(new);
 3086             ret_err(_("inconsistent DHCP range"));
 3087           }
 3088         
 3089         
 3090         if (k >= 4 && strchr(a[3], '.') &&  
 3091             (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
 3092           {
 3093             new->flags |= CONTEXT_BRDCAST;
 3094             leasepos = 4;
 3095           }
 3096           }
 3097       }
 3098 #ifdef HAVE_DHCP6
 3099     else if (inet_pton(AF_INET6, a[0], &new->start6))
 3100       {
 3101         const char *err = NULL;
 3102 
 3103         new->flags |= CONTEXT_V6; 
 3104         new->prefix = 64; /* default */
 3105         new->end6 = new->start6;
 3106         new->lease_time = DEFLEASE6;
 3107         new->next = daemon->dhcp6;
 3108         daemon->dhcp6 = new;
 3109 
 3110         for (leasepos = 1; leasepos < k; leasepos++)
 3111           {
 3112         if (strcmp(a[leasepos], "static") == 0)
 3113           new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
 3114         else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
 3115           new->flags |= CONTEXT_RA;
 3116         else if (strcmp(a[leasepos], "ra-names") == 0)
 3117           new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
 3118         else if (strcmp(a[leasepos], "ra-advrouter") == 0)
 3119           new->flags |= CONTEXT_RA_ROUTER | CONTEXT_RA;
 3120         else if (strcmp(a[leasepos], "ra-stateless") == 0)
 3121           new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
 3122         else if (strcmp(a[leasepos], "off-link") == 0)
 3123           new->flags |= CONTEXT_RA_OFF_LINK;
 3124         else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
 3125           new->flags |= CONTEXT_DHCP; 
 3126         else if (strstr(a[leasepos], "constructor:") == a[leasepos])
 3127           {
 3128             new->template_interface = opt_string_alloc(a[leasepos] + 12);
 3129             new->flags |= CONTEXT_TEMPLATE;
 3130           }
 3131         else  
 3132           break;
 3133           }
 3134                      
 3135         /* bare integer < 128 is prefix value */
 3136         if (leasepos < k)
 3137           {
 3138         int pref;
 3139         for (cp = a[leasepos]; *cp; cp++)
 3140           if (!(*cp >= '0' && *cp <= '9'))
 3141             break;
 3142         if (!*cp && (pref = atoi(a[leasepos])) <= 128)
 3143           {
 3144             new->prefix = pref;
 3145             leasepos++;
 3146           }
 3147           }
 3148         
 3149         if (new->prefix > 64)
 3150           {
 3151         if (new->flags & CONTEXT_RA)
 3152           err=(_("prefix length must be exactly 64 for RA subnets"));
 3153         else if (new->flags & CONTEXT_TEMPLATE)
 3154           err=(_("prefix length must be exactly 64 for subnet constructors"));
 3155           }
 3156         else if (new->prefix < 64)
 3157           err=(_("prefix length must be at least 64"));
 3158         
 3159         if (!err && !is_same_net6(&new->start6, &new->end6, new->prefix))
 3160           err=(_("inconsistent DHCPv6 range"));
 3161 
 3162         if (err)
 3163           {
 3164         dhcp_context_free(new);
 3165         ret_err(err);
 3166           }
 3167 
 3168         /* dhcp-range=:: enables DHCP stateless on any interface */
 3169         if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
 3170           new->prefix = 0;
 3171         
 3172         if (new->flags & CONTEXT_TEMPLATE)
 3173           {
 3174         struct in6_addr zero;
 3175         memset(&zero, 0, sizeof(zero));
 3176         if (!is_same_net6(&zero, &new->start6, new->prefix))
 3177           {
 3178             dhcp_context_free(new);
 3179             ret_err(_("prefix must be zero with \"constructor:\" argument"));
 3180           }
 3181           }
 3182         
 3183         if (addr6part(&new->start6) > addr6part(&new->end6))
 3184           {
 3185         struct in6_addr tmp = new->start6;
 3186         new->start6 = new->end6;
 3187         new->end6 = tmp;
 3188           }
 3189       }
 3190 #endif
 3191     else
 3192       {
 3193         dhcp_context_free(new);
 3194         ret_err(_("bad dhcp-range"));
 3195       }
 3196     
 3197     if (leasepos < k)
 3198       {
 3199         if (leasepos != k-1)
 3200           {
 3201         dhcp_context_free(new);
 3202         ret_err(_("bad dhcp-range"));
 3203           }
 3204         
 3205         if (strcmp(a[leasepos], "infinite") == 0)
 3206           {
 3207         new->lease_time = 0xffffffff;
 3208         new->flags |= CONTEXT_SETLEASE;
 3209           }
 3210         else if (strcmp(a[leasepos], "deprecated") == 0)
 3211           new->flags |= CONTEXT_DEPRECATE;
 3212         else
 3213           {
 3214         int fac = 1;
 3215         if (strlen(a[leasepos]) > 0)
 3216           {
 3217             switch (a[leasepos][strlen(a[leasepos]) - 1])
 3218               {
 3219               case 'w':
 3220               case 'W':
 3221             fac *= 7;
 3222             /* fall through */
 3223               case 'd':
 3224               case 'D':
 3225             fac *= 24;
 3226             /* fall through */
 3227               case 'h':
 3228               case 'H':
 3229             fac *= 60;
 3230             /* fall through */
 3231               case 'm':
 3232               case 'M':
 3233             fac *= 60;
 3234             /* fall through */
 3235               case 's':
 3236               case 'S':
 3237             a[leasepos][strlen(a[leasepos]) - 1] = 0;
 3238               }
 3239             
 3240             for (cp = a[leasepos]; *cp; cp++)
 3241               if (!(*cp >= '0' && *cp <= '9'))
 3242             break;
 3243 
 3244             if (*cp || (leasepos+1 < k))
 3245               ret_err_free(_("bad dhcp-range"), new);
 3246             
 3247             new->lease_time = atoi(a[leasepos]) * fac;
 3248             new->flags |= CONTEXT_SETLEASE;
 3249             /* Leases of a minute or less confuse
 3250                some clients, notably Apple's */
 3251             if (new->lease_time < 120)
 3252               new->lease_time = 120;
 3253           }
 3254           }
 3255       }
 3256 
 3257     break;
 3258       }
 3259 
 3260     case LOPT_BANK:
 3261     case 'G':  /* --dhcp-host */
 3262       {
 3263     struct dhcp_config *new;
 3264     struct in_addr in;
 3265     
 3266     new = opt_malloc(sizeof(struct dhcp_config));
 3267     
 3268     new->next = daemon->dhcp_conf;
 3269     new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
 3270     new->hwaddr = NULL;
 3271     new->netid = NULL;
 3272     new->filter = NULL;
 3273     new->clid = NULL;
 3274 #ifdef HAVE_DHCP6
 3275     new->addr6 = NULL;
 3276 #endif
 3277 
 3278     while (arg)
 3279       {
 3280         comma = split(arg);
 3281         if (strchr(arg, ':')) /* ethernet address, netid or binary CLID */
 3282           {
 3283         if ((arg[0] == 'i' || arg[0] == 'I') &&
 3284             (arg[1] == 'd' || arg[1] == 'D') &&
 3285             arg[2] == ':')
 3286           {
 3287             if (arg[3] == '*')
 3288               new->flags |= CONFIG_NOCLID;
 3289             else
 3290               {
 3291             int len;
 3292             arg += 3; /* dump id: */
 3293             if (strchr(arg, ':'))
 3294               len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
 3295             else
 3296               {
 3297                 unhide_metas(arg);
 3298                 len = (int) strlen(arg);
 3299               }
 3300             
 3301             if (len == -1)
 3302               {
 3303                 dhcp_config_free(new);
 3304                 ret_err(_("bad hex constant"));
 3305               }
 3306             else if ((new->clid = opt_malloc(len)))
 3307               {
 3308                 new->flags |= CONFIG_CLID;
 3309                 new->clid_len = len;
 3310                 memcpy(new->clid, arg, len);
 3311               }
 3312               }
 3313           }
 3314         /* dhcp-host has strange backwards-compat needs. */
 3315         else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
 3316           {
 3317             struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
 3318             newlist->next = new->netid;
 3319             new->netid = newlist;
 3320             newlist->list = dhcp_netid_create(arg+4, NULL);
 3321           }
 3322         else if (strstr(arg, "tag:") == arg)
 3323           new->filter = dhcp_netid_create(arg+4, new->filter);
 3324           
 3325 #ifdef HAVE_DHCP6
 3326         else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
 3327           {
 3328             char *pref;
 3329             struct in6_addr in6;
 3330             struct addrlist *new_addr;
 3331             
 3332             arg[strlen(arg)-1] = 0;
 3333             arg++;
 3334             pref = split_chr(arg, '/');
 3335             
 3336             if (!inet_pton(AF_INET6, arg, &in6))
 3337               {
 3338             dhcp_config_free(new);
 3339             ret_err(_("bad IPv6 address"));
 3340               }
 3341 
 3342             new_addr = opt_malloc(sizeof(struct addrlist));
 3343             new_addr->next = new->addr6;
 3344             new_addr->flags = 0;
 3345             new_addr->addr.addr6 = in6;
 3346             new->addr6 = new_addr;
 3347             
 3348             if (pref)
 3349               {
 3350             u64 addrpart = addr6part(&in6);
 3351             
 3352             if (!atoi_check(pref, &new_addr->prefixlen) ||
 3353                 new_addr->prefixlen > 128 ||
 3354                 ((((u64)1<<(128-new_addr->prefixlen))-1) & addrpart) != 0)
 3355               {
 3356                 dhcp_config_free(new);
 3357                 ret_err(_("bad IPv6 prefix"));
 3358               }
 3359             
 3360             new_addr->flags |= ADDRLIST_PREFIX;
 3361               }
 3362           
 3363             for (i= 0; i < 8; i++)
 3364               if (in6.s6_addr[i] != 0)
 3365             break;
 3366             
 3367             /* set WILDCARD if network part all zeros */
 3368             if (i == 8)
 3369               new_addr->flags |= ADDRLIST_WILDCARD;
 3370             
 3371             new->flags |= CONFIG_ADDR6;
 3372           }
 3373 #endif
 3374         else
 3375           {
 3376             struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
 3377             if ((newhw->hwaddr_len = parse_hex(arg, newhw->hwaddr, DHCP_CHADDR_MAX, 
 3378                                &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
 3379               {
 3380             free(newhw);
 3381             dhcp_config_free(new);
 3382             ret_err(_("bad hex constant"));
 3383               }
 3384             else
 3385               {
 3386             newhw->next = new->hwaddr;
 3387             new->hwaddr = newhw;
 3388               }         
 3389           }
 3390           }
 3391         else if (strchr(arg, '.') && (inet_pton(AF_INET, arg, &in) > 0))
 3392           {
 3393         struct dhcp_config *configs;
 3394         
 3395         new->addr = in;
 3396         new->flags |= CONFIG_ADDR;
 3397         
 3398         /* If the same IP appears in more than one host config, then DISCOVER
 3399            for one of the hosts will get the address, but REQUEST will be NAKed,
 3400            since the address is reserved by the other one -> protocol loop. */
 3401         for (configs = daemon->dhcp_conf; configs; configs = configs->next) 
 3402           if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
 3403             {
 3404               sprintf(errstr, _("duplicate dhcp-host IP address %s"),  inet_ntoa(in));
 3405               return 0;
 3406             }         
 3407           }
 3408         else
 3409           {
 3410         char *cp, *lastp = NULL, last = 0;
 3411         int fac = 1, isdig = 0;
 3412         
 3413         if (strlen(arg) > 1)
 3414           {
 3415             lastp = arg + strlen(arg) - 1;
 3416             last = *lastp;
 3417             switch (last)
 3418               {
 3419               case 'w':
 3420               case 'W':
 3421             fac *= 7;
 3422             /* fall through */
 3423               case 'd':
 3424               case 'D':
 3425             fac *= 24;
 3426             /* fall through */
 3427               case 'h':
 3428               case 'H':
 3429             fac *= 60;
 3430             /* fall through */
 3431               case 'm':
 3432               case 'M':
 3433             fac *= 60;
 3434             /* fall through */
 3435               case 's':
 3436               case 'S':
 3437             *lastp = 0;
 3438               }
 3439           }
 3440         
 3441         for (cp = arg; *cp; cp++)
 3442           if (isdigit((unsigned char)*cp))
 3443             isdig = 1;
 3444           else if (*cp != ' ')
 3445             break;
 3446 
 3447         if (*cp)
 3448           {
 3449             if (lastp)
 3450               *lastp = last;
 3451             if (strcmp(arg, "infinite") == 0)
 3452               {
 3453             new->lease_time = 0xffffffff;
 3454             new->flags |= CONFIG_TIME;
 3455               }
 3456             else if (strcmp(arg, "ignore") == 0)
 3457               new->flags |= CONFIG_DISABLE;
 3458             else
 3459               {
 3460             if (!(new->hostname = canonicalise_opt(arg)) ||
 3461                 !legal_hostname(new->hostname))
 3462               {
 3463                 dhcp_config_free(new);
 3464                 ret_err(_("bad DHCP host name"));
 3465               }
 3466             
 3467             new->flags |= CONFIG_NAME;
 3468             new->domain = strip_hostname(new->hostname);            
 3469               }
 3470           }
 3471         else if (isdig)
 3472           {
 3473             new->lease_time = atoi(arg) * fac; 
 3474             /* Leases of a minute or less confuse
 3475                some clients, notably Apple's */
 3476             if (new->lease_time < 120)
 3477               new->lease_time = 120;
 3478             new->flags |= CONFIG_TIME;
 3479           }
 3480           }
 3481 
 3482         arg = comma;
 3483       }
 3484 
 3485     daemon->dhcp_conf = new;
 3486     break;
 3487       }
 3488       
 3489     case LOPT_TAG_IF:  /* --tag-if */
 3490       {
 3491     struct tag_if *new = opt_malloc(sizeof(struct tag_if));
 3492         
 3493     new->tag = NULL;
 3494     new->set = NULL;
 3495     new->next = NULL;
 3496     
 3497     /* preserve order */
 3498     if (!daemon->tag_if)
 3499       daemon->tag_if = new;
 3500     else
 3501       {
 3502         struct tag_if *tmp;
 3503         for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
 3504         tmp->next = new;
 3505       }
 3506 
 3507     while (arg)
 3508       {
 3509         size_t len;
 3510 
 3511         comma = split(arg);
 3512         len = strlen(arg);
 3513 
 3514         if (len < 5)
 3515           {
 3516         new->set = NULL;
 3517         break;
 3518           }
 3519         else
 3520           {
 3521         struct dhcp_netid *newtag = dhcp_netid_create(arg+4, NULL);
 3522 
 3523         if (strstr(arg, "set:") == arg)
 3524           {
 3525             struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
 3526             newlist->next = new->set;
 3527             new->set = newlist;
 3528             newlist->list = newtag;
 3529           }
 3530         else if (strstr(arg, "tag:") == arg)
 3531           {
 3532             newtag->next = new->tag;
 3533             new->tag = newtag;
 3534           }
 3535         else 
 3536           {
 3537             new->set = NULL;
 3538             dhcp_netid_free(newtag);
 3539             break;
 3540           }
 3541           }
 3542         
 3543         arg = comma;
 3544       }
 3545 
 3546     if (!new->set)
 3547       {
 3548         dhcp_netid_free(new->tag);
 3549         dhcp_netid_list_free(new->set);
 3550         ret_err_free(_("bad tag-if"), new);
 3551       }
 3552       
 3553     break;
 3554       }
 3555 
 3556       
 3557     case 'O':           /* --dhcp-option */
 3558     case LOPT_FORCE:    /* --dhcp-option-force */
 3559     case LOPT_OPTS:
 3560     case LOPT_MATCH:    /* --dhcp-match */
 3561       return parse_dhcp_opt(errstr, arg, 
 3562                 option == LOPT_FORCE ? DHOPT_FORCE : 
 3563                 (option == LOPT_MATCH ? DHOPT_MATCH :
 3564                  (option == LOPT_OPTS ? DHOPT_BANK : 0)));
 3565 
 3566     case LOPT_NAME_MATCH: /* --dhcp-name-match */
 3567       {
 3568     struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name));
 3569     struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid));
 3570     ssize_t len;
 3571     
 3572     if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
 3573       ret_err(gen_err);
 3574 
 3575     new->wildcard = 0;
 3576     new->netid = id;
 3577     id->net = opt_string_alloc(set_prefix(arg));
 3578 
 3579     if (comma[len-1] == '*')
 3580       {
 3581         comma[len-1] = 0;
 3582         new->wildcard = 1;
 3583       }
 3584     new->name = opt_string_alloc(comma);
 3585 
 3586     new->next = daemon->dhcp_name_match;
 3587     daemon->dhcp_name_match = new;
 3588 
 3589     break;
 3590       }
 3591       
 3592     case 'M': /* --dhcp-boot */
 3593       {
 3594     struct dhcp_netid *id = dhcp_tags(&arg);
 3595     
 3596     if (!arg)
 3597       {
 3598         ret_err(gen_err);
 3599       }
 3600     else 
 3601       {
 3602         char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
 3603         struct in_addr dhcp_next_server;
 3604         struct dhcp_boot *new;
 3605         comma = split(arg);
 3606         dhcp_file = opt_string_alloc(arg);
 3607         dhcp_next_server.s_addr = 0;
 3608         if (comma)
 3609           {
 3610         arg = comma;
 3611         comma = split(arg);
 3612         dhcp_sname = opt_string_alloc(arg);
 3613         if (comma)
 3614           {
 3615             unhide_metas(comma);
 3616             if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
 3617               {
 3618             /*
 3619              * The user may have specified the tftp hostname here.
 3620              * save it so that it can be resolved/looked up during
 3621              * actual dhcp_reply().
 3622              */ 
 3623             
 3624             tftp_sname = opt_string_alloc(comma);
 3625             dhcp_next_server.s_addr = 0;
 3626               }
 3627           }
 3628           }
 3629         
 3630         new = opt_malloc(sizeof(struct dhcp_boot));
 3631         new->file = dhcp_file;
 3632         new->sname = dhcp_sname;
 3633         new->tftp_sname = tftp_sname;
 3634         new->next_server = dhcp_next_server;
 3635         new->netid = id;
 3636         new->next = daemon->boot_config;
 3637         daemon->boot_config = new;
 3638       }
 3639       
 3640     break;
 3641       }
 3642 
 3643     case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */
 3644       {
 3645     struct dhcp_netid *id = dhcp_tags(&arg);
 3646     
 3647     if (!arg)
 3648       {
 3649         ret_err(gen_err);
 3650       }
 3651     else
 3652       {
 3653         struct delay_config *new;
 3654         int delay;
 3655         if (!atoi_check(arg, &delay))
 3656               ret_err(gen_err);
 3657         
 3658         new = opt_malloc(sizeof(struct delay_config));
 3659         new->delay = delay;
 3660         new->netid = id;
 3661             new->next = daemon->delay_conf;
 3662             daemon->delay_conf = new;
 3663       }
 3664     
 3665     break;
 3666       }
 3667       
 3668     case LOPT_PXE_PROMT:  /* --pxe-prompt */
 3669        {
 3670      struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
 3671      int timeout;
 3672      
 3673      new->netid = NULL;
 3674      new->opt = 10; /* PXE_MENU_PROMPT */
 3675      new->netid = dhcp_tags(&arg);
 3676      
 3677      if (!arg)
 3678        {
 3679          dhcp_opt_free(new);
 3680          ret_err(gen_err);
 3681        }
 3682      else
 3683        {
 3684          comma = split(arg);
 3685          unhide_metas(arg);
 3686          new->len = strlen(arg) + 1;
 3687          new->val = opt_malloc(new->len);
 3688          memcpy(new->val + 1, arg, new->len - 1);
 3689          
 3690          new->u.vendor_class = NULL;
 3691          new->flags = DHOPT_VENDOR | DHOPT_VENDOR_PXE;
 3692          
 3693          if (comma && atoi_check(comma, &timeout))
 3694            *(new->val) = timeout;
 3695          else
 3696            *(new->val) = 255;
 3697 
 3698          new->next = daemon->dhcp_opts;
 3699          daemon->dhcp_opts = new;
 3700          daemon->enable_pxe = 1;
 3701        }
 3702      
 3703      break;
 3704        }
 3705        
 3706     case LOPT_PXE_SERV:  /* --pxe-service */
 3707        {
 3708      struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
 3709      char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
 3710              "IA32_EFI", "x86-64_EFI", "Xscale_EFI", "BC_EFI",
 3711              "ARM32_EFI", "ARM64_EFI", NULL };  
 3712      static int boottype = 32768;
 3713      
 3714      new->netid = NULL;
 3715      new->sname = NULL;
 3716      new->server.s_addr = 0;
 3717      new->netid = dhcp_tags(&arg);
 3718 
 3719      if (arg && (comma = split(arg)))
 3720        {
 3721          for (i = 0; CSA[i]; i++)
 3722            if (strcasecmp(CSA[i], arg) == 0)
 3723          break;
 3724          
 3725          if (CSA[i] || atoi_check(arg, &i))
 3726            {
 3727          arg = comma;
 3728          comma = split(arg);
 3729          
 3730          new->CSA = i;
 3731          new->menu = opt_string_alloc(arg);
 3732          
 3733          if (!comma)
 3734            {
 3735              new->type = 0; /* local boot */
 3736              new->basename = NULL;
 3737            }
 3738          else
 3739            {
 3740              arg = comma;
 3741              comma = split(arg);
 3742              if (atoi_check(arg, &i))
 3743                {
 3744              new->type = i;
 3745              new->basename = NULL;
 3746                }
 3747              else
 3748                {
 3749              new->type = boottype++;
 3750              new->basename = opt_string_alloc(arg);
 3751                }
 3752              
 3753              if (comma)
 3754                {
 3755              if (!inet_pton(AF_INET, comma, &new->server))
 3756                {
 3757                  new->server.s_addr = 0;
 3758                  new->sname = opt_string_alloc(comma);
 3759                }
 3760                
 3761                }
 3762            }
 3763          
 3764          /* Order matters */
 3765          new->next = NULL;
 3766          if (!daemon->pxe_services)
 3767            daemon->pxe_services = new; 
 3768          else
 3769            {
 3770              struct pxe_service *s;
 3771              for (s = daemon->pxe_services; s->next; s = s->next);
 3772              s->next = new;
 3773            }
 3774          
 3775          daemon->enable_pxe = 1;
 3776          break;
 3777         
 3778            }
 3779        }
 3780      
 3781      ret_err(gen_err);
 3782        }
 3783      
 3784     case '4':  /* --dhcp-mac */
 3785       {
 3786     if (!(comma = split(arg)))
 3787       ret_err(gen_err);
 3788     else
 3789       {
 3790         struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
 3791         new->netid.net = opt_string_alloc(set_prefix(arg));
 3792         unhide_metas(comma);
 3793         new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
 3794         if (new->hwaddr_len == -1)
 3795           {
 3796         free(new->netid.net);
 3797         ret_err_free(gen_err, new);
 3798           }
 3799         else
 3800           {
 3801         new->next = daemon->dhcp_macs;
 3802         daemon->dhcp_macs = new;
 3803           }
 3804       }
 3805       }
 3806       break;
 3807 
 3808     case 'U':           /* --dhcp-vendorclass */
 3809     case 'j':           /* --dhcp-userclass */
 3810     case LOPT_CIRCUIT:  /* --dhcp-circuitid */
 3811     case LOPT_REMOTE:   /* --dhcp-remoteid */
 3812     case LOPT_SUBSCR:   /* --dhcp-subscrid */
 3813       {
 3814      unsigned char *p;
 3815      int dig = 0;
 3816      struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
 3817      
 3818      if (!(comma = split(arg)))
 3819        ret_err_free(gen_err, new);
 3820     
 3821      new->netid.net = opt_string_alloc(set_prefix(arg));
 3822      /* check for hex string - must digits may include : must not have nothing else, 
 3823         only allowed for agent-options. */
 3824      
 3825      arg = comma;
 3826      if ((comma = split(arg)))
 3827        {
 3828          if (option  != 'U' || strstr(arg, "enterprise:") != arg)
 3829            {
 3830              free(new->netid.net);
 3831              ret_err_free(gen_err, new);
 3832            }
 3833          else
 3834            new->enterprise = atoi(arg+11);
 3835        }
 3836      else
 3837        comma = arg;
 3838      
 3839      for (p = (unsigned char *)comma; *p; p++)
 3840        if (isxdigit(*p))
 3841          dig = 1;
 3842        else if (*p != ':')
 3843          break;
 3844      unhide_metas(comma);
 3845      if (option == 'U' || option == 'j' || *p || !dig)
 3846        {
 3847          new->len = strlen(comma);  
 3848          new->data = opt_malloc(new->len);
 3849          memcpy(new->data, comma, new->len);
 3850        }
 3851      else
 3852        {
 3853          new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
 3854          new->data = opt_malloc(new->len);
 3855          memcpy(new->data, comma, new->len);
 3856        }
 3857      
 3858      switch (option)
 3859        {
 3860        case 'j':
 3861          new->match_type = MATCH_USER;
 3862          break;
 3863        case 'U':
 3864          new->match_type = MATCH_VENDOR;
 3865          break; 
 3866        case LOPT_CIRCUIT:
 3867          new->match_type = MATCH_CIRCUIT;
 3868          break;
 3869        case LOPT_REMOTE:
 3870          new->match_type = MATCH_REMOTE;
 3871          break;
 3872        case LOPT_SUBSCR:
 3873          new->match_type = MATCH_SUBSCRIBER;
 3874          break;
 3875        }
 3876      new->next = daemon->dhcp_vendors;
 3877      daemon->dhcp_vendors = new;
 3878 
 3879      break;
 3880       }
 3881       
 3882     case LOPT_ALTPORT:   /* --dhcp-alternate-port */
 3883       if (!arg)
 3884     {
 3885       daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
 3886       daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
 3887     }
 3888       else
 3889     {
 3890       comma = split(arg);
 3891       if (!atoi_check16(arg, &daemon->dhcp_server_port) || 
 3892           (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
 3893         ret_err(_("invalid port number"));
 3894       if (!comma)
 3895         daemon->dhcp_client_port = daemon->dhcp_server_port+1; 
 3896     }
 3897       break;
 3898 
 3899     case 'J':            /* --dhcp-ignore */
 3900     case LOPT_NO_NAMES:  /* --dhcp-ignore-names */
 3901     case LOPT_BROADCAST: /* --dhcp-broadcast */
 3902     case '3':            /* --bootp-dynamic */
 3903     case LOPT_GEN_NAMES: /* --dhcp-generate-names */
 3904       {
 3905     struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
 3906     struct dhcp_netid *list = NULL;
 3907     if (option == 'J')
 3908       {
 3909         new->next = daemon->dhcp_ignore;
 3910         daemon->dhcp_ignore = new;
 3911       }
 3912     else if (option == LOPT_BROADCAST)
 3913       {
 3914         new->next = daemon->force_broadcast;
 3915         daemon->force_broadcast = new;
 3916       }
 3917     else if (option == '3')
 3918       {
 3919         new->next = daemon->bootp_dynamic;
 3920         daemon->bootp_dynamic = new;
 3921       }
 3922     else if (option == LOPT_GEN_NAMES)
 3923       {
 3924         new->next = daemon->dhcp_gen_names;
 3925         daemon->dhcp_gen_names = new;
 3926       }
 3927     else
 3928       {
 3929         new->next = daemon->dhcp_ignore_names;
 3930         daemon->dhcp_ignore_names = new;
 3931       }
 3932     
 3933     while (arg) {
 3934       comma = split(arg);
 3935       list = dhcp_netid_create(is_tag_prefix(arg) ? arg+4 :arg, list);
 3936       arg = comma;
 3937     }
 3938     
 3939     new->list = list;
 3940     break;
 3941       }
 3942 
 3943     case LOPT_PROXY: /* --dhcp-proxy */
 3944       daemon->override = 1;
 3945       while (arg) {
 3946     struct addr_list *new = opt_malloc(sizeof(struct addr_list));
 3947     comma = split(arg);
 3948     if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
 3949       ret_err_free(_("bad dhcp-proxy address"), new);
 3950     new->next = daemon->override_relays;
 3951     daemon->override_relays = new;
 3952     arg = comma;
 3953     }
 3954       break;
 3955 
 3956     case LOPT_PXE_VENDOR: /* --dhcp-pxe-vendor */
 3957       {
 3958         while (arg) {
 3959       struct dhcp_pxe_vendor *new = opt_malloc(sizeof(struct dhcp_pxe_vendor));
 3960       comma = split(arg);
 3961           new->data = opt_string_alloc(arg);
 3962       new->next = daemon->dhcp_pxe_vendors;
 3963       daemon->dhcp_pxe_vendors = new;
 3964       arg = comma;
 3965     }
 3966       }
 3967       break;
 3968 
 3969     case LOPT_RELAY: /* --dhcp-relay */
 3970       {
 3971     struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
 3972     comma = split(arg);
 3973     new->interface = opt_string_alloc(split(comma));
 3974     new->iface_index = 0;
 3975     if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
 3976       {
 3977         new->next = daemon->relay4;
 3978         daemon->relay4 = new;
 3979       }
 3980 #ifdef HAVE_DHCP6
 3981     else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
 3982       {
 3983         new->next = daemon->relay6;
 3984         daemon->relay6 = new;
 3985       }
 3986 #endif
 3987     else
 3988       {
 3989         free(new->interface);
 3990         ret_err_free(_("Bad dhcp-relay"), new);
 3991       }
 3992     
 3993     break;
 3994       }
 3995 
 3996 #endif
 3997       
 3998 #ifdef HAVE_DHCP6
 3999     case LOPT_RA_PARAM: /* --ra-param */
 4000       if ((comma = split(arg)))
 4001     {
 4002       struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
 4003       new->lifetime = -1;
 4004       new->prio = 0;
 4005       new->mtu = 0;
 4006       new->mtu_name = NULL;
 4007       new->name = opt_string_alloc(arg);
 4008       if (strcasestr(comma, "mtu:") == comma)
 4009         {
 4010           arg = comma + 4;
 4011           if (!(comma = split(comma)))
 4012             goto err;
 4013           if (!strcasecmp(arg, "off"))
 4014             new->mtu = -1;
 4015           else if (!atoi_check(arg, &new->mtu))
 4016             new->mtu_name = opt_string_alloc(arg);
 4017           else if (new->mtu < 1280)
 4018             goto err;
 4019         }
 4020       if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
 4021         {
 4022           if (*comma == 'l' || *comma == 'L')
 4023         new->prio = 0x18;
 4024           else
 4025         new->prio = 0x08;
 4026           comma = split(comma);
 4027         }
 4028        arg = split(comma);
 4029        if (!atoi_check(comma, &new->interval) || 
 4030           (arg && !atoi_check(arg, &new->lifetime)))
 4031              {
 4032 err:
 4033            free(new->name);
 4034            ret_err_free(_("bad RA-params"), new);
 4035              }
 4036       
 4037       new->next = daemon->ra_interfaces;
 4038       daemon->ra_interfaces = new;
 4039     }
 4040       break;
 4041       
 4042     case LOPT_DUID: /* --dhcp-duid */
 4043       if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
 4044     ret_err(_("bad DUID"));
 4045       else
 4046     {
 4047       daemon->duid_config_len = parse_hex(comma,(unsigned char *)comma, strlen(comma), NULL, NULL);
 4048       daemon->duid_config = opt_malloc(daemon->duid_config_len);
 4049       memcpy(daemon->duid_config, comma, daemon->duid_config_len);
 4050     }
 4051       break;
 4052 #endif
 4053 
 4054     case 'V':  /* --alias */
 4055       {
 4056     char *dash, *a[3] = { NULL, NULL, NULL };
 4057     int k = 0;
 4058     struct doctor *new = opt_malloc(sizeof(struct doctor));
 4059     new->next = daemon->doctors;
 4060     daemon->doctors = new;
 4061     new->mask.s_addr = 0xffffffff;
 4062     new->end.s_addr = 0;
 4063 
 4064     if ((a[0] = arg))
 4065       for (k = 1; k < 3; k++)
 4066         {
 4067           if (!(a[k] = split(a[k-1])))
 4068         break;
 4069           unhide_metas(a[k]);
 4070         }
 4071     
 4072     dash = split_chr(a[0], '-');
 4073 
 4074     if ((k < 2) || 
 4075         (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
 4076         (!(inet_pton(AF_INET, a[1], &new->out) > 0)) ||
 4077         (k == 3 && !inet_pton(AF_INET, a[2], &new->mask)))
 4078       ret_err(_("missing address in alias"));
 4079     
 4080     if (dash && 
 4081         (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
 4082          !is_same_net(new->in, new->end, new->mask) ||
 4083          ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
 4084       ret_err_free(_("invalid alias range"), new);
 4085     
 4086     break;
 4087       }
 4088       
 4089     case LOPT_INTNAME:  /* --interface-name */
 4090     case LOPT_DYNHOST:  /* --dynamic-host */
 4091       {
 4092     struct interface_name *new, **up;
 4093     char *domain = arg;
 4094     
 4095     arg = split(arg);
 4096     
 4097     new = opt_malloc(sizeof(struct interface_name));
 4098     memset(new, 0, sizeof(struct interface_name));
 4099     new->flags = IN4 | IN6;
 4100     
 4101     /* Add to the end of the list, so that first name
 4102        of an interface is used for PTR lookups. */
 4103     for (up = &daemon->int_names; *up; up = &((*up)->next));
 4104     *up = new;
 4105     
 4106     while ((comma = split(arg)))
 4107       {
 4108         if (inet_pton(AF_INET, arg, &new->proto4))
 4109           new->flags |= INP4;
 4110         else if (inet_pton(AF_INET6, arg, &new->proto6))
 4111           new->flags |= INP6;
 4112         else
 4113           break;
 4114         
 4115         arg = comma;
 4116       }
 4117 
 4118     if ((comma = split_chr(arg, '/')))
 4119       {
 4120         if (strcmp(comma, "4") == 0)
 4121           new->flags &= ~IN6;
 4122         else if (strcmp(comma, "6") == 0)
 4123           new->flags &= ~IN4;
 4124         else
 4125           ret_err_free(gen_err, new);
 4126       }
 4127 
 4128     new->intr = opt_string_alloc(arg);
 4129 
 4130     if (option == LOPT_DYNHOST)
 4131       {
 4132         if (!(new->flags & (INP4 | INP6)))
 4133           ret_err(_("missing address in dynamic host"));
 4134 
 4135         if (!(new->flags & IN4) || !(new->flags & IN6))
 4136           arg = NULL; /* provoke error below */
 4137 
 4138         new->flags &= ~(IN4 | IN6);
 4139       }
 4140     else
 4141       {
 4142         if (new->flags & (INP4 | INP6))
 4143           arg = NULL; /* provoke error below */
 4144       }
 4145     
 4146     if (!domain || !arg || !(new->name = canonicalise_opt(domain)))
 4147       ret_err(option == LOPT_DYNHOST ?
 4148           _("bad dynamic host") : _("bad interface name"));
 4149     
 4150     break;
 4151       }
 4152       
 4153     case LOPT_CNAME: /* --cname */
 4154       {
 4155     struct cname *new;
 4156     char *alias, *target, *last, *pen;
 4157     int ttl = -1;
 4158 
 4159     for (last = pen = NULL, comma = arg; comma; comma = split(comma))
 4160       {
 4161         pen = last;
 4162         last = comma;
 4163       }
 4164 
 4165     if (!pen)
 4166       ret_err(_("bad CNAME"));
 4167     
 4168     if (pen != arg && atoi_check(last, &ttl))
 4169       last = pen;
 4170         
 4171         target = canonicalise_opt(last);
 4172 
 4173     while (arg != last)
 4174       {
 4175         int arglen = strlen(arg);
 4176         alias = canonicalise_opt(arg);
 4177 
 4178         if (!alias || !target)
 4179           {
 4180         free(target);
 4181         free(alias);
 4182         ret_err(_("bad CNAME"));
 4183           }
 4184         
 4185         for (new = daemon->cnames; new; new = new->next)
 4186           if (hostname_isequal(new->alias, alias))
 4187         {
 4188           free(target);
 4189           free(alias);
 4190           ret_err(_("duplicate CNAME"));
 4191         }
 4192         new = opt_malloc(sizeof(struct cname));
 4193         new->next = daemon->cnames;
 4194         daemon->cnames = new;
 4195         new->alias = alias;
 4196         new->target = target;
 4197         new->ttl = ttl;
 4198 
 4199         for (arg += arglen+1; *arg && isspace(*arg); arg++);
 4200       }
 4201       
 4202     break;
 4203       }
 4204 
 4205     case LOPT_PTR:  /* --ptr-record */
 4206       {
 4207     struct ptr_record *new;
 4208     char *dom, *target = NULL;
 4209 
 4210     comma = split(arg);
 4211     
 4212     if (!(dom = canonicalise_opt(arg)) ||
 4213         (comma && !(target = canonicalise_opt(comma))))
 4214       {
 4215         free(dom);
 4216         free(target);
 4217         ret_err(_("bad PTR record"));
 4218       }
 4219     else
 4220       {
 4221         new = opt_malloc(sizeof(struct ptr_record));
 4222         new->next = daemon->ptr;
 4223         daemon->ptr = new;
 4224         new->name = dom;
 4225         new->ptr = target;
 4226       }
 4227     break;
 4228       }
 4229 
 4230     case LOPT_NAPTR: /* --naptr-record */
 4231       {
 4232     char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
 4233     int k = 0;
 4234     struct naptr *new;
 4235     int order, pref;
 4236     char *name=NULL, *replace = NULL;
 4237 
 4238     if ((a[0] = arg))
 4239       for (k = 1; k < 7; k++)
 4240         if (!(a[k] = split(a[k-1])))
 4241           break;
 4242     
 4243     
 4244     if (k < 6 || 
 4245         !(name = canonicalise_opt(a[0])) ||
 4246         !atoi_check16(a[1], &order) || 
 4247         !atoi_check16(a[2], &pref) ||
 4248         (k == 7 && !(replace = canonicalise_opt(a[6]))))
 4249           {
 4250         free(name);
 4251         free(replace);
 4252         ret_err(_("bad NAPTR record"));
 4253           }
 4254     else
 4255       {
 4256         new = opt_malloc(sizeof(struct naptr));
 4257         new->next = daemon->naptr;
 4258         daemon->naptr = new;
 4259         new->name = name;
 4260         new->flags = opt_string_alloc(a[3]);
 4261         new->services = opt_string_alloc(a[4]);
 4262         new->regexp = opt_string_alloc(a[5]);
 4263         new->replace = replace;
 4264         new->order = order;
 4265         new->pref = pref;
 4266       }
 4267     break;
 4268       }
 4269 
 4270     case LOPT_RR: /* dns-rr */
 4271       {
 4272         struct txt_record *new;
 4273     size_t len = 0;
 4274     char *data;
 4275     int class;
 4276 
 4277     comma = split(arg);
 4278     data = split(comma);
 4279         
 4280     new = opt_malloc(sizeof(struct txt_record));
 4281     new->name = NULL;
 4282     
 4283     if (!atoi_check(comma, &class) || 
 4284         !(new->name = canonicalise_opt(arg)) ||
 4285         (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
 4286           {
 4287             free(new->name);
 4288         ret_err_free(_("bad RR record"), new);
 4289           }
 4290 
 4291     new->len = 0;
 4292     new->class = class;
 4293     new->next = daemon->rr;
 4294     daemon->rr = new;
 4295     
 4296     if (data)
 4297       {
 4298         new->txt = opt_malloc(len);
 4299         new->len = len;
 4300         memcpy(new->txt, data, len);
 4301       }
 4302     
 4303     break;
 4304       }
 4305 
 4306     case LOPT_CAA: /* --caa-record */
 4307       {
 4308         struct txt_record *new;
 4309     char *tag, *value;
 4310     int flags;
 4311     
 4312     comma = split(arg);
 4313     tag = split(comma);
 4314     value = split(tag);
 4315     
 4316     new = opt_malloc(sizeof(struct txt_record));
 4317     new->next = daemon->rr;
 4318     daemon->rr = new;
 4319 
 4320     if (!atoi_check(comma, &flags) || !tag || !value || !(new->name = canonicalise_opt(arg)))
 4321       ret_err(_("bad CAA record"));
 4322     
 4323     unhide_metas(tag);
 4324     unhide_metas(value);
 4325 
 4326     new->len = strlen(tag) + strlen(value) + 2;
 4327     new->txt = opt_malloc(new->len);
 4328     new->txt[0] = flags;
 4329     new->txt[1] = strlen(tag);
 4330     memcpy(&new->txt[2], tag, strlen(tag));
 4331     memcpy(&new->txt[2 + strlen(tag)], value, strlen(value));
 4332     new->class = T_CAA;
 4333     
 4334     break;
 4335       }
 4336     
 4337     case 'Y':  /* --txt-record */
 4338       {
 4339     struct txt_record *new;
 4340     unsigned char *p, *cnt;
 4341     size_t len;
 4342 
 4343     comma = split(arg);
 4344         
 4345     new = opt_malloc(sizeof(struct txt_record));
 4346     new->class = C_IN;
 4347     new->stat = 0;
 4348 
 4349     if (!(new->name = canonicalise_opt(arg)))
 4350       ret_err_free(_("bad TXT record"), new);
 4351     
 4352     new->next = daemon->txt;
 4353     daemon->txt = new;
 4354     len = comma ? strlen(comma) : 0;
 4355     len += (len/255) + 1; /* room for extra counts */
 4356     new->txt = p = opt_malloc(len);
 4357 
 4358     cnt = p++;
 4359     *cnt = 0;
 4360     
 4361     while (comma && *comma)
 4362       {
 4363         unsigned char c = (unsigned char)*comma++;
 4364 
 4365         if (c == ',' || *cnt == 255)
 4366           {
 4367         if (c != ',')
 4368           comma--;
 4369         cnt = p++;
 4370         *cnt = 0;
 4371           }
 4372         else
 4373           {
 4374         *p++ = unhide_meta(c);
 4375         (*cnt)++;
 4376           }
 4377       }
 4378 
 4379     new->len = p - new->txt;
 4380 
 4381     break;
 4382       }
 4383       
 4384     case 'W':  /* --srv-host */
 4385       {
 4386     int port = 1, priority = 0, weight = 0;
 4387     char *name, *target = NULL;
 4388     struct mx_srv_record *new;
 4389     
 4390     comma = split(arg);
 4391     
 4392     if (!(name = canonicalise_opt(arg)))
 4393       ret_err(_("bad SRV record"));
 4394     
 4395     if (comma)
 4396       {
 4397         arg = comma;
 4398         comma = split(arg);
 4399         if (!(target = canonicalise_opt(arg)))
 4400           ret_err_free(_("bad SRV target"), name);
 4401         
 4402         if (comma)
 4403           {
 4404         arg = comma;
 4405         comma = split(arg);
 4406         if (!atoi_check16(arg, &port))
 4407                   {
 4408                     free(name);
 4409             ret_err_free(_("invalid port number"), target);
 4410                   }
 4411         
 4412         if (comma)
 4413           {
 4414             arg = comma;
 4415             comma = split(arg);
 4416             if (!atoi_check16(arg, &priority))
 4417                       {
 4418                         free(name);
 4419                 ret_err_free(_("invalid priority"), target);
 4420               }
 4421             if (comma && !atoi_check16(comma, &weight))
 4422                       {
 4423                         free(name);
 4424                 ret_err_free(_("invalid weight"), target);
 4425                       }
 4426           }
 4427           }
 4428       }
 4429     
 4430     new = opt_malloc(sizeof(struct mx_srv_record));
 4431     new->next = daemon->mxnames;
 4432     daemon->mxnames = new;
 4433     new->issrv = 1;
 4434     new->name = name;
 4435     new->target = target;
 4436     new->srvport = port;
 4437     new->priority = priority;
 4438     new->weight = weight;
 4439     break;
 4440       }
 4441       
 4442     case LOPT_HOST_REC: /* --host-record */
 4443       {
 4444     struct host_record *new;
 4445 
 4446     if (!arg || !(comma = split(arg)))
 4447       ret_err(_("Bad host-record"));
 4448     
 4449     new = opt_malloc(sizeof(struct host_record));
 4450     memset(new, 0, sizeof(struct host_record));
 4451     new->ttl = -1;
 4452     new->flags = 0;
 4453 
 4454     while (arg)
 4455       {
 4456         union all_addr addr;
 4457         char *dig;
 4458 
 4459         for (dig = arg; *dig != 0; dig++)
 4460           if (*dig < '0' || *dig > '9')
 4461         break;
 4462         if (*dig == 0)
 4463           new->ttl = atoi(arg);
 4464         else if (inet_pton(AF_INET, arg, &addr.addr4))
 4465           {
 4466         new->addr = addr.addr4;
 4467         new->flags |= HR_4;
 4468           }
 4469         else if (inet_pton(AF_INET6, arg, &addr.addr6))
 4470           {
 4471         new->addr6 = addr.addr6;
 4472         new->flags |= HR_6;
 4473           }
 4474         else
 4475           {
 4476         int nomem;
 4477         char *canon = canonicalise(arg, &nomem);
 4478         struct name_list *nl;
 4479         if (!canon)
 4480                   {
 4481             struct name_list *tmp = new->names, *next;
 4482             for (tmp = new->names; tmp; tmp = next)
 4483               {
 4484             next = tmp->next;
 4485             free(tmp);
 4486               }
 4487             ret_err_free(_("Bad name in host-record"), new);
 4488                   }
 4489 
 4490         nl = opt_malloc(sizeof(struct name_list));
 4491         nl->name = canon;
 4492         /* keep order, so that PTR record goes to first name */
 4493         nl->next = NULL;
 4494         if (!new->names)
 4495           new->names = nl;
 4496         else
 4497           { 
 4498             struct name_list *tmp;
 4499             for (tmp = new->names; tmp->next; tmp = tmp->next);
 4500             tmp->next = nl;
 4501           }
 4502           }
 4503         
 4504         arg = comma;
 4505         comma = split(arg);
 4506       }
 4507 
 4508     /* Keep list order */
 4509     if (!daemon->host_records_tail)
 4510       daemon->host_records = new;
 4511     else
 4512       daemon->host_records_tail->next = new;
 4513     new->next = NULL;
 4514     daemon->host_records_tail = new;
 4515     break;
 4516       }
 4517 
 4518 #ifdef HAVE_DNSSEC
 4519     case LOPT_DNSSEC_STAMP: /* --dnssec-timestamp */
 4520       daemon->timestamp_file = opt_string_alloc(arg); 
 4521       break;
 4522 
 4523     case LOPT_DNSSEC_CHECK: /* --dnssec-check-unsigned */
 4524       if (arg)
 4525     {
 4526       if (strcmp(arg, "no") == 0)
 4527         set_option_bool(OPT_DNSSEC_IGN_NS);
 4528       else
 4529         ret_err(_("bad value for dnssec-check-unsigned"));
 4530     }
 4531       break;
 4532       
 4533     case LOPT_TRUST_ANCHOR: /* --trust-anchor */
 4534       {
 4535     struct ds_config *new = opt_malloc(sizeof(struct ds_config));
 4536         char *cp, *cp1, *keyhex, *digest, *algo = NULL;
 4537     int len;
 4538     
 4539     new->class = C_IN;
 4540     new->name = NULL;
 4541 
 4542     if ((comma = split(arg)) && (algo = split(comma)))
 4543       {
 4544         int class = 0;
 4545         if (strcmp(comma, "IN") == 0)
 4546           class = C_IN;
 4547         else if (strcmp(comma, "CH") == 0)
 4548           class = C_CHAOS;
 4549         else if (strcmp(comma, "HS") == 0)
 4550           class = C_HESIOD;
 4551         
 4552         if (class != 0)
 4553           {
 4554         new->class = class;
 4555         comma = algo;
 4556         algo = split(comma);
 4557           }
 4558       }
 4559           
 4560         if (!comma || !algo || !(digest = split(algo)) || !(keyhex = split(digest)) ||
 4561         !atoi_check16(comma, &new->keytag) || 
 4562         !atoi_check8(algo, &new->algo) ||
 4563         !atoi_check8(digest, &new->digest_type) ||
 4564         !(new->name = canonicalise_opt(arg)))
 4565       ret_err_free(_("bad trust anchor"), new);
 4566         
 4567     /* Upper bound on length */
 4568     len = (2*strlen(keyhex))+1;
 4569     new->digest = opt_malloc(len);
 4570     unhide_metas(keyhex);
 4571     /* 4034: "Whitespace is allowed within digits" */
 4572     for (cp = keyhex; *cp; )
 4573       if (isspace(*cp))
 4574         for (cp1 = cp; *cp1; cp1++)
 4575           *cp1 = *(cp1+1);
 4576       else
 4577         cp++;
 4578     if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1)
 4579       {
 4580         free(new->name);
 4581         ret_err_free(_("bad HEX in trust anchor"), new);
 4582       }
 4583     
 4584     new->next = daemon->ds;
 4585     daemon->ds = new;
 4586     
 4587     break;
 4588       }
 4589 #endif
 4590         
 4591     default:
 4592       ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
 4593       
 4594     }
 4595   
 4596   return 1;
 4597 }
 4598 
 4599 static void read_file(char *file, FILE *f, int hard_opt)    
 4600 {
 4601   volatile int lineno = 0;
 4602   char *buff = daemon->namebuff;
 4603   
 4604   while (fgets(buff, MAXDNAME, f))
 4605     {
 4606       int white, i;
 4607       volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
 4608       char *errmess, *p, *arg, *start;
 4609       size_t len;
 4610 
 4611       /* Memory allocation failure longjmps here if mem_recover == 1 */ 
 4612       if (option != 0 || hard_opt == LOPT_REV_SERV)
 4613     {
 4614       if (setjmp(mem_jmp))
 4615         continue;
 4616       mem_recover = 1;
 4617     }
 4618       
 4619       arg = NULL;
 4620       lineno++;
 4621       errmess = NULL;
 4622       
 4623       /* Implement quotes, inside quotes we allow \\ \" \n and \t 
 4624      metacharacters get hidden also strip comments */
 4625       for (white = 1, p = buff; *p; p++)
 4626     {
 4627       if (*p == '"')
 4628         {
 4629           memmove(p, p+1, strlen(p+1)+1);
 4630 
 4631           for(; *p && *p != '"'; p++)
 4632         {
 4633           if (*p == '\\' && strchr("\"tnebr\\", p[1]))
 4634             {
 4635               if (p[1] == 't')
 4636             p[1] = '\t';
 4637               else if (p[1] == 'n')
 4638             p[1] = '\n';
 4639               else if (p[1] == 'b')
 4640             p[1] = '\b';
 4641               else if (p[1] == 'r')
 4642             p[1] = '\r';
 4643               else if (p[1] == 'e') /* escape */
 4644             p[1] = '\033';
 4645               memmove(p, p+1, strlen(p+1)+1);
 4646             }
 4647           *p = hide_meta(*p);
 4648         }
 4649 
 4650           if (*p == 0) 
 4651         {
 4652           errmess = _("missing \"");
 4653           goto oops; 
 4654         }
 4655 
 4656           memmove(p, p+1, strlen(p+1)+1);
 4657         }
 4658 
 4659       if (isspace(*p))
 4660         {
 4661           *p = ' ';
 4662           white = 1;
 4663         }
 4664       else 
 4665         {
 4666           if (white && *p == '#')
 4667         { 
 4668           *p = 0;
 4669           break;
 4670         }
 4671           white = 0;
 4672         } 
 4673     }
 4674 
 4675       
 4676       /* strip leading spaces */
 4677       for (start = buff; *start && *start == ' '; start++);
 4678       
 4679       /* strip trailing spaces */
 4680       for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
 4681       
 4682       if (len == 0)
 4683     continue; 
 4684       else
 4685     start[len] = 0;
 4686       
 4687       if (option != 0)
 4688     arg = start;
 4689       else if ((p=strchr(start, '=')))
 4690     {
 4691       /* allow spaces around "=" */
 4692       for (arg = p+1; *arg == ' '; arg++);
 4693       for (; p >= start && (*p == ' ' || *p == '='); p--)
 4694         *p = 0;
 4695     }
 4696       else
 4697     arg =