Diff for /embedaddon/dnsmasq/src/option.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2013/07/29 19:37:40 version 1.1.1.3, 2016/11/02 09:57:01
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
Line 64  struct myoption { Line 64  struct myoption {
 #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:"  #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:"
   
 /* options which don't have a one-char version */  /* options which don't have a one-char version */
#define LOPT_RELOAD    256#define LOPT_RELOAD        256
#define LOPT_NO_NAMES  257#define LOPT_NO_NAMES      257
#define LOPT_TFTP      258#define LOPT_TFTP          258
#define LOPT_SECURE    259#define LOPT_SECURE        259
#define LOPT_PREFIX    260#define LOPT_PREFIX        260
#define LOPT_PTR       261#define LOPT_PTR           261
#define LOPT_BRIDGE    262#define LOPT_BRIDGE        262
#define LOPT_TFTP_MAX  263#define LOPT_TFTP_MAX      263
#define LOPT_FORCE     264#define LOPT_FORCE         264
#define LOPT_NOBLOCK   265#define LOPT_NOBLOCK       265
#define LOPT_LOG_OPTS  266#define LOPT_LOG_OPTS      266
#define LOPT_MAX_LOGS  267#define LOPT_MAX_LOGS      267
#define LOPT_CIRCUIT   268#define LOPT_CIRCUIT       268
#define LOPT_REMOTE    269#define LOPT_REMOTE        269
#define LOPT_SUBSCR    270#define LOPT_SUBSCR        270
#define LOPT_INTNAME   271#define LOPT_INTNAME       271
#define LOPT_BANK      272#define LOPT_BANK          272
#define LOPT_DHCP_HOST 273#define LOPT_DHCP_HOST     273
#define LOPT_APREF     274#define LOPT_APREF         274
#define LOPT_OVERRIDE  275#define LOPT_OVERRIDE      275
#define LOPT_TFTPPORTS 276#define LOPT_TFTPPORTS     276
#define LOPT_REBIND    277#define LOPT_REBIND        277
#define LOPT_NOLAST    278#define LOPT_NOLAST        278
#define LOPT_OPTS      279#define LOPT_OPTS          279
#define LOPT_DHCP_OPTS 280#define LOPT_DHCP_OPTS     280
#define LOPT_MATCH     281#define LOPT_MATCH         281
#define LOPT_BROADCAST 282#define LOPT_BROADCAST     282
#define LOPT_NEGTTL    283#define LOPT_NEGTTL        283
#define LOPT_ALTPORT   284#define LOPT_ALTPORT       284
#define LOPT_SCRIPTUSR 285#define LOPT_SCRIPTUSR     285
#define LOPT_LOCAL     286#define LOPT_LOCAL         286
#define LOPT_NAPTR     287#define LOPT_NAPTR         287
#define LOPT_MINPORT   288#define LOPT_MINPORT       288
#define LOPT_DHCP_FQDN 289#define LOPT_DHCP_FQDN     289
#define LOPT_CNAME     290#define LOPT_CNAME         290
#define LOPT_PXE_PROMT 291#define LOPT_PXE_PROMT     291
#define LOPT_PXE_SERV  292#define LOPT_PXE_SERV      292
#define LOPT_TEST      293#define LOPT_TEST          293
#define LOPT_TAG_IF    294#define LOPT_TAG_IF        294
#define LOPT_PROXY     295#define LOPT_PROXY         295
#define LOPT_GEN_NAMES 296#define LOPT_GEN_NAMES     296
#define LOPT_MAXTTL    297#define LOPT_MAXTTL        297
#define LOPT_NO_REBIND 298#define LOPT_NO_REBIND     298
#define LOPT_LOC_REBND 299#define LOPT_LOC_REBND     299
#define LOPT_ADD_MAC   300#define LOPT_ADD_MAC       300
#define LOPT_DNSSEC    301#define LOPT_DNSSEC        301
#define LOPT_INCR_ADDR 302#define LOPT_INCR_ADDR     302
#define LOPT_CONNTRACK 303#define LOPT_CONNTRACK     303
#define LOPT_FQDN      304#define LOPT_FQDN          304
#define LOPT_LUASCRIPT 305#define LOPT_LUASCRIPT     305
#define LOPT_RA        306#define LOPT_RA            306
#define LOPT_DUID      307#define LOPT_DUID          307
#define LOPT_HOST_REC  308#define LOPT_HOST_REC      308
#define LOPT_TFTP_LC   309#define LOPT_TFTP_LC       309
#define LOPT_RR        310#define LOPT_RR            310
#define LOPT_CLVERBIND 311#define LOPT_CLVERBIND     311
#define LOPT_MAXCTTL   312#define LOPT_MAXCTTL       312
#define LOPT_AUTHZONE  313#define LOPT_AUTHZONE      313
#define LOPT_AUTHSERV  314#define LOPT_AUTHSERV      314
#define LOPT_AUTHTTL   315#define LOPT_AUTHTTL       315
#define LOPT_AUTHSOA   316#define LOPT_AUTHSOA       316
#define LOPT_AUTHSFS   317#define LOPT_AUTHSFS       317
#define LOPT_AUTHPEER  318#define LOPT_AUTHPEER      318
#define LOPT_IPSET     319#define LOPT_IPSET         319
 #define LOPT_SYNTH         320
 #ifdef OPTION6_PREFIX_CLASS   #ifdef OPTION6_PREFIX_CLASS 
#define LOPT_PREF_CLSS 320#define LOPT_PREF_CLSS     321
 #endif  #endif
#define LOPT_RELAY         323
 #define LOPT_RA_PARAM      324
 #define LOPT_ADD_SBNET     325
 #define LOPT_QUIET_DHCP    326
 #define LOPT_QUIET_DHCP6   327
 #define LOPT_QUIET_RA      328
 #define LOPT_SEC_VALID     329
 #define LOPT_TRUST_ANCHOR  330
 #define LOPT_DNSSEC_DEBUG  331
 #define LOPT_REV_SERV      332
 #define LOPT_SERVERS_FILE  333
 #define LOPT_DNSSEC_CHECK  334
 #define LOPT_LOCAL_SERVICE 335
 #define LOPT_DNSSEC_TIME   336
 #define LOPT_LOOP_DETECT   337
 #define LOPT_IGNORE_ADDR   338
 #define LOPT_MINCTTL       339
 #define LOPT_DHCP_INOTIFY  340
 #define LOPT_DHOPT_INOTIFY 341
 #define LOPT_HOST_INOTIFY  342
 #define LOPT_DNSSEC_STAMP  343
 #define LOPT_TFTP_NO_FAIL  344
 #define LOPT_MAXPORT       345
 #define LOPT_CPE_ID        346
 #define LOPT_SCRIPT_ARP    347
 #define LOPT_DHCPTTL       348
 #define LOPT_TFTP_MTU      349
  
 #ifdef HAVE_GETOPT_LONG  #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =    static const struct option opts[] =  
 #else  #else
Line 143  static const struct myoption opts[] =  Line 171  static const struct myoption opts[] = 
     { "no-poll", 0, 0, 'n' },      { "no-poll", 0, 0, 'n' },
     { "help", 0, 0, 'w' },      { "help", 0, 0, 'w' },
     { "no-daemon", 0, 0, 'd' },      { "no-daemon", 0, 0, 'd' },
    { "log-queries", 0, 0, 'q' },    { "log-queries", 2, 0, 'q' },
     { "user", 2, 0, 'u' },      { "user", 2, 0, 'u' },
     { "group", 2, 0, 'g' },      { "group", 2, 0, 'g' },
     { "resolv-file", 2, 0, 'r' },      { "resolv-file", 2, 0, 'r' },
       { "servers-file", 1, 0, LOPT_SERVERS_FILE },
     { "mx-host", 1, 0, 'm' },      { "mx-host", 1, 0, 'm' },
     { "mx-target", 1, 0, 't' },      { "mx-target", 1, 0, 't' },
     { "cache-size", 2, 0, 'c' },      { "cache-size", 2, 0, 'c' },
Line 161  static const struct myoption opts[] =  Line 190  static const struct myoption opts[] = 
     { "domain-suffix", 1, 0, 's' },      { "domain-suffix", 1, 0, 's' },
     { "interface", 1, 0, 'i' },      { "interface", 1, 0, 'i' },
     { "listen-address", 1, 0, 'a' },      { "listen-address", 1, 0, 'a' },
       { "local-service", 0, 0, LOPT_LOCAL_SERVICE },
     { "bogus-priv", 0, 0, 'b' },      { "bogus-priv", 0, 0, 'b' },
     { "bogus-nxdomain", 1, 0, 'B' },      { "bogus-nxdomain", 1, 0, 'B' },
       { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
     { "selfmx", 0, 0, 'e' },      { "selfmx", 0, 0, 'e' },
     { "filterwin2k", 0, 0, 'f' },      { "filterwin2k", 0, 0, 'f' },
     { "pid-file", 2, 0, 'x' },      { "pid-file", 2, 0, 'x' },
     { "strict-order", 0, 0, 'o' },      { "strict-order", 0, 0, 'o' },
     { "server", 1, 0, 'S' },      { "server", 1, 0, 'S' },
       { "rev-server", 1, 0, LOPT_REV_SERV },
     { "local", 1, 0, LOPT_LOCAL },      { "local", 1, 0, LOPT_LOCAL },
     { "address", 1, 0, 'A' },      { "address", 1, 0, 'A' },
     { "conf-file", 2, 0, 'C' },      { "conf-file", 2, 0, 'C' },
Line 177  static const struct myoption opts[] =  Line 209  static const struct myoption opts[] = 
     { "local-ttl", 1, 0, 'T' },      { "local-ttl", 1, 0, 'T' },
     { "no-negcache", 0, 0, 'N' },      { "no-negcache", 0, 0, 'N' },
     { "addn-hosts", 1, 0, 'H' },      { "addn-hosts", 1, 0, 'H' },
       { "hostsdir", 1, 0, LOPT_HOST_INOTIFY },
     { "query-port", 1, 0, 'Q' },      { "query-port", 1, 0, 'Q' },
     { "except-interface", 1, 0, 'I' },      { "except-interface", 1, 0, 'I' },
     { "no-dhcp-interface", 1, 0, '2' },      { "no-dhcp-interface", 1, 0, '2' },
Line 206  static const struct myoption opts[] =  Line 239  static const struct myoption opts[] = 
     { "dns-forward-max", 1, 0, '0' },      { "dns-forward-max", 1, 0, '0' },
     { "clear-on-reload", 0, 0, LOPT_RELOAD },      { "clear-on-reload", 0, 0, LOPT_RELOAD },
     { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },      { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
    { "enable-tftp", 0, 0, LOPT_TFTP },    { "enable-tftp", 2, 0, LOPT_TFTP },
     { "tftp-secure", 0, 0, LOPT_SECURE },      { "tftp-secure", 0, 0, LOPT_SECURE },
       { "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL },
     { "tftp-unique-root", 0, 0, LOPT_APREF },      { "tftp-unique-root", 0, 0, LOPT_APREF },
     { "tftp-root", 1, 0, LOPT_PREFIX },      { "tftp-root", 1, 0, LOPT_PREFIX },
     { "tftp-max", 1, 0, LOPT_TFTP_MAX },      { "tftp-max", 1, 0, LOPT_TFTP_MAX },
       { "tftp-mtu", 1, 0, LOPT_TFTP_MTU },
     { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },      { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
     { "ptr-record", 1, 0, LOPT_PTR },      { "ptr-record", 1, 0, LOPT_PTR },
     { "naptr-record", 1, 0, LOPT_NAPTR },      { "naptr-record", 1, 0, LOPT_NAPTR },
Line 225  static const struct myoption opts[] =  Line 260  static const struct myoption opts[] = 
     { "interface-name", 1, 0, LOPT_INTNAME },      { "interface-name", 1, 0, LOPT_INTNAME },
     { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },      { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
     { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },      { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
       { "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY },
       { "dhcp-optsdir", 1, 0, LOPT_DHOPT_INOTIFY },
     { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },      { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
     { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },      { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
     { "stop-dns-rebind", 0, 0, LOPT_REBIND },      { "stop-dns-rebind", 0, 0, LOPT_REBIND },
Line 234  static const struct myoption opts[] =  Line 271  static const struct myoption opts[] = 
     { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },      { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
     { "neg-ttl", 1, 0, LOPT_NEGTTL },      { "neg-ttl", 1, 0, LOPT_NEGTTL },
     { "max-ttl", 1, 0, LOPT_MAXTTL },      { "max-ttl", 1, 0, LOPT_MAXTTL },
       { "min-cache-ttl", 1, 0, LOPT_MINCTTL },
     { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },      { "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
     { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },      { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
     { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },      { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
     { "min-port", 1, 0, LOPT_MINPORT },      { "min-port", 1, 0, LOPT_MINPORT },
       { "max-port", 1, 0, LOPT_MAXPORT },
     { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },      { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
     { "cname", 1, 0, LOPT_CNAME },      { "cname", 1, 0, LOPT_CNAME },
     { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },      { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
Line 247  static const struct myoption opts[] =  Line 286  static const struct myoption opts[] = 
     { "dhcp-proxy", 2, 0, LOPT_PROXY },      { "dhcp-proxy", 2, 0, LOPT_PROXY },
     { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },      { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
     { "rebind-localhost-ok", 0, 0,  LOPT_LOC_REBND },      { "rebind-localhost-ok", 0, 0,  LOPT_LOC_REBND },
    { "add-mac", 0, 0, LOPT_ADD_MAC },    { "add-mac", 2, 0, LOPT_ADD_MAC },
     { "add-subnet", 2, 0, LOPT_ADD_SBNET },
     { "add-cpe-id", 1, 0 , LOPT_CPE_ID },
     { "proxy-dnssec", 0, 0, LOPT_DNSSEC },      { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
     { "dhcp-sequential-ip", 0, 0,  LOPT_INCR_ADDR },      { "dhcp-sequential-ip", 0, 0,  LOPT_INCR_ADDR },
     { "conntrack", 0, 0, LOPT_CONNTRACK },      { "conntrack", 0, 0, LOPT_CONNTRACK },
Line 264  static const struct myoption opts[] =  Line 305  static const struct myoption opts[] = 
     { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },      { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
     { "auth-peer", 1, 0, LOPT_AUTHPEER },       { "auth-peer", 1, 0, LOPT_AUTHPEER }, 
     { "ipset", 1, 0, LOPT_IPSET },      { "ipset", 1, 0, LOPT_IPSET },
       { "synth-domain", 1, 0, LOPT_SYNTH },
       { "dnssec", 0, 0, LOPT_SEC_VALID },
       { "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
       { "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
       { "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
       { "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
       { "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP },
 #ifdef OPTION6_PREFIX_CLASS   #ifdef OPTION6_PREFIX_CLASS 
     { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },      { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
 #endif  #endif
       { "dhcp-relay", 1, 0, LOPT_RELAY },
       { "ra-param", 1, 0, LOPT_RA_PARAM },
       { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
       { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
       { "quiet-ra", 0, 0, LOPT_QUIET_RA },
       { "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT },
       { "script-arp", 0, 0, LOPT_SCRIPT_ARP },
       { "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
     { NULL, 0, 0, 0 }      { NULL, 0, 0, 0 }
   };    };
   
Line 299  static struct { Line 355  static struct {
   { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },    { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
   { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },    { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
   { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },    { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
     { LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL }, 
     { LOPT_DHOPT_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP options from a directory."), NULL }, 
   { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },    { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
   { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },    { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
   { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },    { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
     { LOPT_HOST_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read hosts files from a directory."), NULL },
   { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },    { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
   { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },    { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
   { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },    { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
Line 323  static struct { Line 382  static struct {
   { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},    { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
   { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },    { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
   { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },    { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
  { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },  { 'q', ARG_DUP, NULL, gettext_noop("Log DNS queries."), NULL },
   { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },    { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
   { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },    { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
   { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },     { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, 
     { LOPT_SERVERS_FILE, ARG_ONE, "<path>", gettext_noop("Specify path to file with server= options"), NULL },
   { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },    { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
     { LOPT_REV_SERV, ARG_DUP, "<addr>/<prefix>,<ipaddr>", gettext_noop("Specify address of upstream servers for reverse address queries"), NULL },
   { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },    { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
   { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },    { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
   { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },    { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
   { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },    { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
   { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },    { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
   { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },    { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
     { LOPT_MAXCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live ceiling for cache."), NULL },
     { LOPT_MINCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live floor for cache."), NULL },
   { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },     { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER }, 
   { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },    { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
   { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },    { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
   { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },    { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
   { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },    { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL },
   { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },    { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
   { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },    { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
   { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },    { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
Line 357  static struct { Line 420  static struct {
   { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },    { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
   { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },    { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
   { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },    { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
     { LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL },
   { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },    { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
   { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },    { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
   { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },    { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
Line 364  static struct { Line 428  static struct {
   { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },    { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
   { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },    { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
   { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },    { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
  { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },  { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
   { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },    { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
   { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },    { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
   { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },    { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
     { LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate the service if TFTP directories are inaccessible."), NULL },
   { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },    { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
     { LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum MTU to use for TFTP transfers."), NULL },
   { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },    { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
   { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },    { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
   { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },    { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
Line 382  static struct { Line 448  static struct {
   { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },    { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
   { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },    { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
   { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },    { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
     { LOPT_MAXPORT, ARG_ONE, "<port>", gettext_noop("Specify highest port available for DNS query transmission."), NULL },
   { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },    { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
   { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},    { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
   { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },    { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
  { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },  { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
   { LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
   { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },    { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
   { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },    { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
   { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },    { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
  { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },  { LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
  { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },  { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL },
   { LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client identification to forwarded DNS queries."), NULL },
   { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
   { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },    { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
   { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },    { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
   { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },    { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
   { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },    { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
   { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },    { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
  { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },  { LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
   { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },    { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
   { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },    { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
   { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },    { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
Line 406  static struct { Line 476  static struct {
   { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },    { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
   { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },    { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
   { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },    { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
     { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
     { LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
     { LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
     { LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
     { LOPT_DNSSEC_CHECK, OPT_DNSSEC_NO_SIGN, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
     { LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
     { LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL },
 #ifdef OPTION6_PREFIX_CLASS   #ifdef OPTION6_PREFIX_CLASS 
   { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },    { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
 #endif  #endif
     { LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
     { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
     { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
     { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
     { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks."), NULL },
     { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops."), NULL },
     { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL }, 
     { LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL }, 
   { 0, 0, NULL, NULL, NULL }    { 0, 0, NULL, NULL, NULL }
 };   }; 
   
Line 560  static int atoi_check16(char *a, int *res) Line 645  static int atoi_check16(char *a, int *res)
   
   return 1;    return 1;
 }  }
   
   #ifdef HAVE_DNSSEC
   static int atoi_check8(char *a, int *res)
   {
     if (!(atoi_check(a, res)) ||
         *res < 0 ||
         *res > 0xff)
       return 0;
   
     return 1;
   }
   #endif
                   
static void add_txt(char *name, char *txt)static void add_txt(char *name, char *txt, int stat)
 {  {
   size_t len = strlen(txt);  
   struct txt_record *r = opt_malloc(sizeof(struct txt_record));    struct txt_record *r = opt_malloc(sizeof(struct txt_record));
   
     if (txt)
       {
         size_t len = strlen(txt);
         r->txt = opt_malloc(len+1);
         r->len = len+1;
         *(r->txt) = len;
         memcpy((r->txt)+1, txt, len);
       }
       
     r->stat = stat;
   r->name = opt_string_alloc(name);    r->name = opt_string_alloc(name);
   r->next = daemon->txt;    r->next = daemon->txt;
   daemon->txt = r;    daemon->txt = r;
   r->class = C_CHAOS;    r->class = C_CHAOS;
   r->txt = opt_malloc(len+1);  
   r->len = len+1;  
   *(r->txt) = len;  
   memcpy((r->txt)+1, txt, len);  
 }  }
   
 static void do_usage(void)  static void do_usage(void)
Line 635  static void do_usage(void) Line 737  static void do_usage(void)
   
 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)  #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
   
   static char *parse_mysockaddr(char *arg, union mysockaddr *addr) 
   {
     if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
       addr->sa.sa_family = AF_INET;
   #ifdef HAVE_IPV6
     else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
       addr->sa.sa_family = AF_INET6;
   #endif
     else
       return _("bad address");
      
     return NULL;
   }
   
 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)  char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
 {  {
   int source_port = 0, serv_port = NAMESERVER_PORT;    int source_port = 0, serv_port = NAMESERVER_PORT;
Line 644  char *parse_server(char *arg, union mysockaddr *addr,  Line 760  char *parse_server(char *arg, union mysockaddr *addr, 
   char *scope_id;    char *scope_id;
 #endif  #endif
       
     if (!arg || strlen(arg) == 0)
       {
         *flags |= SERV_NO_ADDR;
         *interface = 0;
         return NULL;
       }
   
   if ((source = split_chr(arg, '@')) && /* is there a source. */    if ((source = split_chr(arg, '@')) && /* is there a source. */
       (portno = split_chr(source, '#')) &&        (portno = split_chr(source, '#')) &&
       !atoi_check16(portno, &source_port))        !atoi_check16(portno, &source_port))
Line 657  char *parse_server(char *arg, union mysockaddr *addr,  Line 780  char *parse_server(char *arg, union mysockaddr *addr, 
   scope_id = split_chr(arg, '%');    scope_id = split_chr(arg, '%');
 #endif  #endif
       
  if ((addr->in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)  if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
     {      {
       addr->in.sin_port = htons(serv_port);             addr->in.sin_port = htons(serv_port);     
       addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;        addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
Line 672  char *parse_server(char *arg, union mysockaddr *addr,  Line 795  char *parse_server(char *arg, union mysockaddr *addr, 
           if (flags)            if (flags)
             *flags |= SERV_HAS_SOURCE;              *flags |= SERV_HAS_SOURCE;
           source_addr->in.sin_port = htons(source_port);            source_addr->in.sin_port = htons(source_port);
          if ((source_addr->in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)          if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
             {              {
 #if defined(SO_BINDTODEVICE)  #if defined(SO_BINDTODEVICE)
               source_addr->in.sin_addr.s_addr = INADDR_ANY;                source_addr->in.sin_addr.s_addr = INADDR_ANY;
Line 722  char *parse_server(char *arg, union mysockaddr *addr,  Line 845  char *parse_server(char *arg, union mysockaddr *addr, 
   return NULL;    return NULL;
 }  }
   
   static struct server *add_rev4(struct in_addr addr, int msize)
   {
     struct server *serv = opt_malloc(sizeof(struct server));
     in_addr_t  a = ntohl(addr.s_addr) >> 8;
     char *p;
   
     memset(serv, 0, sizeof(struct server));
     p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
     
     if (msize == 24)
       p += sprintf(p, "%d.", a & 0xff);
     a = a >> 8;
     if (msize != 8)
       p += sprintf(p, "%d.", a & 0xff);
     a = a >> 8;
     p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
     
     serv->flags = SERV_HAS_DOMAIN;
     serv->next = daemon->servers;
     daemon->servers = serv;
   
     return serv;
   
   }
   
   static struct server *add_rev6(struct in6_addr *addr, int msize)
   {
     struct server *serv = opt_malloc(sizeof(struct server));
     char *p;
     int i;
                                     
     memset(serv, 0, sizeof(struct server));
     p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
     
     for (i = msize-1; i >= 0; i -= 4)
       { 
         int dig = ((unsigned char *)addr)[i>>3];
         p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
       }
     p += sprintf(p, "ip6.arpa");
     
     serv->flags = SERV_HAS_DOMAIN;
     serv->next = daemon->servers;
     daemon->servers = serv;
     
     return serv;
   }
   
 #ifdef HAVE_DHCP  #ifdef HAVE_DHCP
   
 static int is_tag_prefix(char *arg)  static int is_tag_prefix(char *arg)
Line 750  static int parse_dhcp_opt(char *errstr, char *arg, int Line 921  static int parse_dhcp_opt(char *errstr, char *arg, int
   struct dhcp_netid *np = NULL;    struct dhcp_netid *np = NULL;
   u16 opt_len = 0;    u16 opt_len = 0;
   int is6 = 0;    int is6 = 0;
     int option_ok = 0;
   
   new->len = 0;    new->len = 0;
   new->flags = flags;    new->flags = flags;
Line 769  static int parse_dhcp_opt(char *errstr, char *arg, int Line 941  static int parse_dhcp_opt(char *errstr, char *arg, int
         {          {
           new->opt = atoi(arg);            new->opt = atoi(arg);
           opt_len = 0;            opt_len = 0;
             option_ok = 1;
           break;            break;
         }          }
               
       if (strstr(arg, "option:") == arg)        if (strstr(arg, "option:") == arg)
         {          {
          new->opt = lookup_dhcp_opt(AF_INET, arg+7);          if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
          opt_len = lookup_dhcp_len(AF_INET, new->opt);            {
          /* option:<optname> must follow tag and vendor string. */              opt_len = lookup_dhcp_len(AF_INET, new->opt);
          if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH)              /* option:<optname> must follow tag and vendor string. */
            new->opt = 0;              if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
                 option_ok = 1;
             }
           break;            break;
         }          }
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
Line 792  static int parse_dhcp_opt(char *errstr, char *arg, int Line 967  static int parse_dhcp_opt(char *errstr, char *arg, int
             {              {
               new->opt = atoi(arg+8);                new->opt = atoi(arg+8);
               opt_len = 0;                opt_len = 0;
                 option_ok = 1;
             }              }
           else            else
             {              {
              new->opt = lookup_dhcp_opt(AF_INET6, arg+8);              if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
              opt_len = lookup_dhcp_len(AF_INET6, new->opt);                {
              if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH)                  opt_len = lookup_dhcp_len(AF_INET6, new->opt);
                new->opt = 0;                  if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
                     option_ok = 1;
                 }
             }              }
           /* option6:<opt>|<optname> must follow tag and vendor string. */            /* option6:<opt>|<optname> must follow tag and vendor string. */
           is6 = 1;            is6 = 1;
Line 821  static int parse_dhcp_opt(char *errstr, char *arg, int Line 999  static int parse_dhcp_opt(char *errstr, char *arg, int
           new->flags |= DHOPT_RFC3925;            new->flags |= DHOPT_RFC3925;
           if (flags == DHOPT_MATCH)            if (flags == DHOPT_MATCH)
             {              {
              new->opt = 1; /* avoid error below */              option_ok = 1;
               break;                break;
             }              }
         }          }
Line 848  static int parse_dhcp_opt(char *errstr, char *arg, int Line 1026  static int parse_dhcp_opt(char *errstr, char *arg, int
               
       if (opt_len == 0 &&        if (opt_len == 0 &&
           !(new->flags & DHOPT_RFC3925))            !(new->flags & DHOPT_RFC3925))
        opt_len = lookup_dhcp_len(AF_INET6 ,new->opt);        opt_len = lookup_dhcp_len(AF_INET6, new->opt);
     }      }
   else    else
 #endif  #endif
     if (opt_len == 0 &&      if (opt_len == 0 &&
         !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))          !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
      opt_len = lookup_dhcp_len(AF_INET ,new->opt);      opt_len = lookup_dhcp_len(AF_INET, new->opt);
       
   /* option may be missing with rfc3925 match */    /* option may be missing with rfc3925 match */
  if (new->opt == 0)  if (!option_ok)
     ret_err(_("bad dhcp-option"));      ret_err(_("bad dhcp-option"));
       
   if (comma)    if (comma)
Line 1021  static int parse_dhcp_opt(char *errstr, char *arg, int Line 1199  static int parse_dhcp_opt(char *errstr, char *arg, int
               cp = comma;                cp = comma;
               comma = split(cp);                comma = split(cp);
               slash = split_chr(cp, '/');                slash = split_chr(cp, '/');
              in.s_addr = inet_addr(cp);              if (!inet_pton(AF_INET, cp, &in))
                 ret_err(_("bad IPv4 address"));
               if (!slash)                if (!slash)
                 {                  {
                   memcpy(op, &in, INADDRSZ);                    memcpy(op, &in, INADDRSZ);
Line 1278  void reset_option_bool(unsigned int opt) Line 1457  void reset_option_bool(unsigned int opt)
     daemon->options2 &= ~(1u << (opt - 32));      daemon->options2 &= ~(1u << (opt - 32));
 }  }
   
static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only)
 {        {      
   int i;    int i;
   char *comma;    char *comma;
Line 1338  static int one_opt(int option, char *arg, char *errstr Line 1517  static int one_opt(int option, char *arg, char *errstr
         struct list {          struct list {
           char *suffix;            char *suffix;
           struct list *next;            struct list *next;
        } *ignore_suffix = NULL, *li;        } *ignore_suffix = NULL, *match_suffix = NULL, *li;
                   
         comma = split(arg);          comma = split(arg);
         if (!(directory = opt_string_alloc(arg)))          if (!(directory = opt_string_alloc(arg)))
Line 1347  static int one_opt(int option, char *arg, char *errstr Line 1526  static int one_opt(int option, char *arg, char *errstr
         for (arg = comma; arg; arg = comma)           for (arg = comma; arg; arg = comma) 
           {            {
             comma = split(arg);              comma = split(arg);
            li = opt_malloc(sizeof(struct list));            if (strlen(arg) != 0)
            li->next = ignore_suffix;              {
            ignore_suffix = li;                li = opt_malloc(sizeof(struct list));
            /* Have to copy: buffer is overwritten */                if (*arg == '*')
            li->suffix = opt_string_alloc(arg);                  {
          };                    /* "*" with no suffix is a no-op */
                     if (arg[1] == 0)
                       free(li);
                     else
                       {
                         li->next = match_suffix;
                         match_suffix = li;
                         /* Have to copy: buffer is overwritten */
                         li->suffix = opt_string_alloc(arg+1);
                       }
                   }
                 else
                   {
                     li->next = ignore_suffix;
                     ignore_suffix = li;
                     /* Have to copy: buffer is overwritten */
                     li->suffix = opt_string_alloc(arg);
                   }
               }
           }
                   
         if (!(dir_stream = opendir(directory)))          if (!(dir_stream = opendir(directory)))
           die(_("cannot access directory %s: %s"), directory, EC_FILE);            die(_("cannot access directory %s: %s"), directory, EC_FILE);
Line 1369  static int one_opt(int option, char *arg, char *errstr Line 1567  static int one_opt(int option, char *arg, char *errstr
                 ent->d_name[0] == '.')                  ent->d_name[0] == '.')
               continue;                continue;
   
               if (match_suffix)
                 {
                   for (li = match_suffix; li; li = li->next)
                     {
                       /* check for required suffices */
                       size_t ls = strlen(li->suffix);
                       if (len > ls &&
                           strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
                         break;
                     }
                   if (!li)
                     continue;
                 }
               
             for (li = ignore_suffix; li; li = li->next)              for (li = ignore_suffix; li; li = li->next)
               {                {
                 /* check for proscribed suffices */                  /* check for proscribed suffices */
Line 1404  static int one_opt(int option, char *arg, char *errstr Line 1616  static int one_opt(int option, char *arg, char *errstr
             free(ignore_suffix->suffix);              free(ignore_suffix->suffix);
             free(ignore_suffix);              free(ignore_suffix);
           }            }
                      for(; match_suffix; match_suffix = li)
           {
             li = match_suffix->next;
             free(match_suffix->suffix);
             free(match_suffix);
           }
         break;          break;
       }        }
   
       case LOPT_ADD_SBNET: /* --add-subnet */
         set_option_bool(OPT_CLIENT_SUBNET);
         if (arg)
           {
             char *err, *end;
             comma = split(arg);
   
             struct mysubnet* new = opt_malloc(sizeof(struct mysubnet));
             if ((end = split_chr(arg, '/')))
               {
                 /* has subnet+len */
                 err = parse_mysockaddr(arg, &new->addr);
                 if (err)
                   ret_err(err);
                 if (!atoi_check(end, &new->mask))
                   ret_err(gen_err);
                 new->addr_used = 1;
               } 
             else if (!atoi_check(arg, &new->mask))
               ret_err(gen_err);
               
             daemon->add_subnet4 = new;
   
             if (comma)
               {
                 new = opt_malloc(sizeof(struct mysubnet));
                 if ((end = split_chr(comma, '/')))
                   {
                     /* has subnet+len */
                     err = parse_mysockaddr(comma, &new->addr);
                     if (err)
                       ret_err(err);
                     if (!atoi_check(end, &new->mask))
                       ret_err(gen_err);
                     new->addr_used = 1;
                   }
                 else
                   {
                     if (!atoi_check(comma, &new->mask))
                       ret_err(gen_err);
                   }
             
                 daemon->add_subnet6 = new;
               }
           }
         break;
   
     case '1': /* --enable-dbus */      case '1': /* --enable-dbus */
       set_option_bool(OPT_DBUS);        set_option_bool(OPT_DBUS);
       if (arg)        if (arg)
Line 1470  static int one_opt(int option, char *arg, char *errstr Line 1734  static int one_opt(int option, char *arg, char *errstr
         daemon->resolv_files = list;          daemon->resolv_files = list;
         break;          break;
       }        }
   
       case LOPT_SERVERS_FILE:
         daemon->servers_file = opt_string_alloc(arg);
         break;
               
     case 'm':  /* --mx-host */      case 'm':  /* --mx-host */
       {        {
Line 1528  static int one_opt(int option, char *arg, char *errstr Line 1796  static int one_opt(int option, char *arg, char *errstr
       break;        break;
 #endif /* HAVE_DHCP */  #endif /* HAVE_DHCP */
   
    case LOPT_DHCP_HOST: /* --dhcp-hostfile */    case LOPT_DHCP_HOST:     /* --dhcp-hostsfile */
    case LOPT_DHCP_OPTS: /* --dhcp-optsfile */    case LOPT_DHCP_OPTS:     /* --dhcp-optsfile */
    case 'H': /* --addn-hosts */    case LOPT_DHCP_INOTIFY:  /* --dhcp-hostsdir */
     case LOPT_DHOPT_INOTIFY: /* --dhcp-optsdir */
     case LOPT_HOST_INOTIFY:  /* --hostsdir */
     case 'H':                /* --addn-hosts */
       {        {
         struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));          struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
        static int hosts_index = 1;        static unsigned int hosts_index = SRC_AH;
         new->fname = opt_string_alloc(arg);          new->fname = opt_string_alloc(arg);
         new->index = hosts_index++;          new->index = hosts_index++;
         new->flags = 0;          new->flags = 0;
Line 1552  static int one_opt(int option, char *arg, char *errstr Line 1823  static int one_opt(int option, char *arg, char *errstr
             new->next = daemon->dhcp_opts_file;              new->next = daemon->dhcp_opts_file;
             daemon->dhcp_opts_file = new;              daemon->dhcp_opts_file = new;
           }                   }       
           else 
             {
               new->next = daemon->dynamic_dirs;
               daemon->dynamic_dirs = new; 
               if (option == LOPT_DHCP_INOTIFY)
                 new->flags |= AH_DHCP_HST;
               else if (option == LOPT_DHOPT_INOTIFY)
                 new->flags |= AH_DHCP_OPT;
               else if (option == LOPT_HOST_INOTIFY)
                 new->flags |= AH_HOSTS;
             }
           
         break;          break;
       }        }
               
   
   #ifdef HAVE_AUTH
     case LOPT_AUTHSERV: /* --auth-server */      case LOPT_AUTHSERV: /* --auth-server */
       if (!(comma = split(arg)))        if (!(comma = split(arg)))
         ret_err(gen_err);          ret_err(gen_err);
Line 1566  static int one_opt(int option, char *arg, char *errstr Line 1851  static int one_opt(int option, char *arg, char *errstr
         comma = split(arg);          comma = split(arg);
         new->name = NULL;          new->name = NULL;
         unhide_metas(arg);          unhide_metas(arg);
        if ((new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)        if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
           new->addr.sa.sa_family = AF_INET;            new->addr.sa.sa_family = AF_INET;
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
         else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)          else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
           new->addr.sa.sa_family = AF_INET6;            new->addr.sa.sa_family = AF_INET6;
 #endif  #endif
         else          else
          new->name = opt_string_alloc(arg);          {
                    char *fam = split_chr(arg, '/');
             new->name = opt_string_alloc(arg);
             new->addr.sa.sa_family = 0;
             if (fam)
               {
                 if (strcmp(fam, "4") == 0)
                   new->addr.sa.sa_family = AF_INET;
 #ifdef HAVE_IPV6
                 else if (strcmp(fam, "6") == 0)
                   new->addr.sa.sa_family = AF_INET6;
 #endif
                 else
                   ret_err(gen_err);
               } 
           }
         new->next = daemon->authinterface;          new->next = daemon->authinterface;
         daemon->authinterface = new;          daemon->authinterface = new;
                   
Line 1607  static int one_opt(int option, char *arg, char *errstr Line 1906  static int one_opt(int option, char *arg, char *errstr
         new = opt_malloc(sizeof(struct auth_zone));          new = opt_malloc(sizeof(struct auth_zone));
         new->domain = opt_string_alloc(arg);          new->domain = opt_string_alloc(arg);
         new->subnet = NULL;          new->subnet = NULL;
           new->interface_names = NULL;
         new->next = daemon->auth_zones;          new->next = daemon->auth_zones;
         daemon->auth_zones = new;          daemon->auth_zones = new;
   
Line 1614  static int one_opt(int option, char *arg, char *errstr Line 1914  static int one_opt(int option, char *arg, char *errstr
           {            {
             int prefixlen = 0;              int prefixlen = 0;
             char *prefix;              char *prefix;
            struct subnet *subnet =  opt_malloc(sizeof(struct subnet));            struct addrlist *subnet =  NULL;
                        struct all_addr addr;
            subnet->next = new->subnet; 
            new->subnet = subnet; 
   
             comma = split(arg);              comma = split(arg);
             prefix = split_chr(arg, '/');              prefix = split_chr(arg, '/');
Line 1625  static int one_opt(int option, char *arg, char *errstr Line 1923  static int one_opt(int option, char *arg, char *errstr
             if (prefix && !atoi_check(prefix, &prefixlen))              if (prefix && !atoi_check(prefix, &prefixlen))
               ret_err(gen_err);                ret_err(gen_err);
                           
            if (inet_pton(AF_INET, arg, &subnet->addr4))            if (inet_pton(AF_INET, arg, &addr.addr.addr4))
               {                {
                if ((prefixlen & 0x07) != 0 || prefixlen > 24)                subnet = opt_malloc(sizeof(struct addrlist));
                  ret_err(_("bad prefix")); 
                 subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;                  subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
                subnet->is6 = 0;                subnet->flags = ADDRLIST_LITERAL;
               }                }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
            else if (inet_pton(AF_INET6, arg, &subnet->addr6))            else if (inet_pton(AF_INET6, arg, &addr.addr.addr6))
               {                {
                   subnet = opt_malloc(sizeof(struct addrlist));
                 subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;                  subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
                subnet->is6 = 1;                subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
               }                }
 #endif  #endif
            else            else 
                ret_err(gen_err);              {
                 struct auth_name_list *name =  opt_malloc(sizeof(struct auth_name_list));
                 name->name = opt_string_alloc(arg);
                 name->flags = AUTH4 | AUTH6;
                 name->next = new->interface_names;
                 new->interface_names = name;
                 if (prefix)
                   {
                     if (prefixlen == 4)
                       name->flags &= ~AUTH6;
 #ifdef HAVE_IPV6
                     else if (prefixlen == 6)
                       name->flags &= ~AUTH4;
 #endif
                     else
                       ret_err(gen_err);
                   }
               }
             
             if (subnet)
               {
                 subnet->addr = addr;
                 subnet->next = new->subnet;
                 new->subnet = subnet;
               }
           }            }
         break;          break;
       }        }
      
     case  LOPT_AUTHSOA: /* --auth-soa */      case  LOPT_AUTHSOA: /* --auth-soa */
       comma = split(arg);        comma = split(arg);
      atoi_check(arg, (int *)&daemon->soa_sn);      daemon->soa_sn = (u32)atoi(arg);
       if (comma)        if (comma)
         {          {
           char *cp;            char *cp;
Line 1662  static int one_opt(int option, char *arg, char *errstr Line 1984  static int one_opt(int option, char *arg, char *errstr
             {              {
               arg = comma;                arg = comma;
               comma = split(arg);                 comma = split(arg); 
              atoi_check(arg, (int *)&daemon->soa_refresh);              daemon->soa_refresh = (u32)atoi(arg);
               if (comma)                if (comma)
                 {                  {
                   arg = comma;                    arg = comma;
                   comma = split(arg);                     comma = split(arg); 
                  atoi_check(arg, (int *)&daemon->soa_retry);                  daemon->soa_retry = (u32)atoi(arg);
                   if (comma)                    if (comma)
                    {                    daemon->soa_expiry = (u32)atoi(comma);
                      arg = comma; 
                      comma = split(arg);  
                      atoi_check(arg, (int *)&daemon->soa_expiry); 
                    } 
                 }                  }
             }              }
         }          }
   
       break;        break;
   #endif
   
    case 's': /* --domain */    case 's':         /* --domain */
     case LOPT_SYNTH:  /* --synth-domain */
       if (strcmp (arg, "#") == 0)        if (strcmp (arg, "#") == 0)
         set_option_bool(OPT_RESOLV_DOMAIN);          set_option_bool(OPT_RESOLV_DOMAIN);
       else        else
Line 1695  static int one_opt(int option, char *arg, char *errstr Line 2015  static int one_opt(int option, char *arg, char *errstr
                 {                  {
                   struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));                    struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
                   char *netpart;                    char *netpart;
                     
                     new->prefix = NULL;
   
                   unhide_metas(comma);                    unhide_metas(comma);
                   if ((netpart = split_chr(comma, '/')))                    if ((netpart = split_chr(comma, '/')))
Line 1712  static int one_opt(int option, char *arg, char *errstr Line 2034  static int one_opt(int option, char *arg, char *errstr
                           new->end.s_addr = new->start.s_addr | htonl(mask);                            new->end.s_addr = new->start.s_addr | htonl(mask);
                           if (arg)                            if (arg)
                             {                              {
                              /* generate the equivalent of                              if (option != 's')
                                 local=/<domain>/                                {
                                 local=/xxx.yyy.zzz.in-addr.arpa/ */                                  if (!(new->prefix = canonicalise_opt(arg)) ||
                                      strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
                              if (strcmp(arg, "local") != 0 ||                                     ret_err(_("bad prefix"));
                                  (msize != 8 && msize != 16 && msize != 24))                                }
                               else if (strcmp(arg, "local") != 0 ||
                                        (msize != 8 && msize != 16 && msize != 24))
                                 ret_err(gen_err);                                  ret_err(gen_err);
                               else                                else
                                 {                                  {
                                  struct server *serv = opt_malloc(sizeof(struct server));                                   /* generate the equivalent of
                                  in_addr_t a = ntohl(new->start.s_addr) >> 8;                                      local=/xxx.yyy.zzz.in-addr.arpa/ */
                                  char *p;                                  struct server *serv = add_rev4(new->start, msize);
                                   serv->flags |= SERV_NO_ADDR;
   
                                     /* local=/<domain>/ */
                                     serv = opt_malloc(sizeof(struct server));
                                   memset(serv, 0, sizeof(struct server));                                    memset(serv, 0, sizeof(struct server));
                                   serv->domain = d;                                    serv->domain = d;
                                   serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;                                    serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
                                   serv->next = daemon->servers;                                    serv->next = daemon->servers;
                                   daemon->servers = serv;                                    daemon->servers = serv;
   
                                   serv = opt_malloc(sizeof(struct server));  
                                   memset(serv, 0, sizeof(struct server));  
                                   p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */  
                                     
                                   if (msize == 24)  
                                     p += sprintf(p, "%d.", a & 0xff);  
                                   a = a >> 8;  
                                   if (msize != 8)  
                                     p += sprintf(p, "%d.", a & 0xff);  
                                   a = a >> 8;  
                                   p += sprintf(p, "%d.in-addr.arpa", a & 0xff);  
   
                                   serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;  
                                   serv->next = daemon->servers;  
                                   daemon->servers = serv;  
                                 }                                  }
                             }                              }
                         }                          }
Line 1755  static int one_opt(int option, char *arg, char *errstr Line 2066  static int one_opt(int option, char *arg, char *errstr
                           u64 mask = (1LLU << (128 - msize)) - 1LLU;                            u64 mask = (1LLU << (128 - msize)) - 1LLU;
                           u64 addrpart = addr6part(&new->start6);                            u64 addrpart = addr6part(&new->start6);
                           new->is6 = 1;                            new->is6 = 1;
                          
                           /* prefix==64 overflows the mask calculation above */                            /* prefix==64 overflows the mask calculation above */
                           if (msize == 64)                            if (msize == 64)
                             mask = (u64)-1LL;                              mask = (u64)-1LL;
                          
                           new->end6 = new->start6;                            new->end6 = new->start6;
                           setaddr6part(&new->start6, addrpart & ~mask);                            setaddr6part(&new->start6, addrpart & ~mask);
                           setaddr6part(&new->end6, addrpart | mask);                            setaddr6part(&new->end6, addrpart | mask);
Line 1768  static int one_opt(int option, char *arg, char *errstr Line 2079  static int one_opt(int option, char *arg, char *errstr
                             ret_err(gen_err);                              ret_err(gen_err);
                           else if (arg)                            else if (arg)
                             {                              {
                              /* generate the equivalent of                              if (option != 's')
                                 local=/<domain>/                                {
                                 local=/xxx.yyy.zzz.ip6.arpa/ */                                  if (!(new->prefix = canonicalise_opt(arg)) ||
                                      strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
                              if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))                                    ret_err(_("bad prefix"));
                                 }       
                               else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
                                 ret_err(gen_err);                                  ret_err(gen_err);
                               else                                 else 
                                 {                                  {
                                  struct server *serv = opt_malloc(sizeof(struct server));                                  /* generate the equivalent of
                                  char *p;                                     local=/xxx.yyy.zzz.ip6.arpa/ */
                                   struct server *serv = add_rev6(&new->start6, msize);
                                   serv->flags |= SERV_NO_ADDR;
                                                                       
                                     /* local=/<domain>/ */
                                     serv = opt_malloc(sizeof(struct server));
                                   memset(serv, 0, sizeof(struct server));                                    memset(serv, 0, sizeof(struct server));
                                   serv->domain = d;                                    serv->domain = d;
                                   serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;                                    serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
                                   serv->next = daemon->servers;                                    serv->next = daemon->servers;
                                   daemon->servers = serv;                                    daemon->servers = serv;
   
                                   serv = opt_malloc(sizeof(struct server));  
                                   memset(serv, 0, sizeof(struct server));  
                                   p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */  
                                     
                                   for (i = msize-1; i >= 0; i -= 4)  
                                     {   
                                       int dig = ((unsigned char *)&new->start6)[i>>3];  
                                       p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);  
                                     }  
                                   p += sprintf(p, "ip6.arpa");  
                                     
                                   serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;  
                                   serv->next = daemon->servers;  
                                   daemon->servers = serv;  
                                 }                                  }
                             }                              }
                         }                          }
Line 1806  static int one_opt(int option, char *arg, char *errstr Line 2108  static int one_opt(int option, char *arg, char *errstr
                       else                        else
                         ret_err(gen_err);                          ret_err(gen_err);
                     }                      }
                  else                   else
                     {                      {
                         char *prefstr;
                       arg = split(comma);                        arg = split(comma);
                         prefstr = split(arg);
   
                       if (inet_pton(AF_INET, comma, &new->start))                        if (inet_pton(AF_INET, comma, &new->start))
                         {                          {
                           new->is6 = 0;                            new->is6 = 0;
Line 1829  static int one_opt(int option, char *arg, char *errstr Line 2134  static int one_opt(int option, char *arg, char *errstr
 #endif  #endif
                       else                         else 
                         ret_err(gen_err);                          ret_err(gen_err);
   
                         if (option != 's' && prefstr)
                           {
                             if (!(new->prefix = canonicalise_opt(prefstr)) ||
                                 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
                               ret_err(_("bad prefix"));
                           }
                     }                      }
   
                   new->domain = d;                    new->domain = d;
                  new->next = daemon->cond_domain;                  if (option  == 's')
                  daemon->cond_domain = new;                                     {
                       new->next = daemon->cond_domain;
                       daemon->cond_domain = new;
                     }
                   else
                     {
                       new->next = daemon->synth_domains;
                       daemon->synth_domains = new;
                     }
                 }                  }
              else              else if (option == 's')
                 daemon->domain_suffix = d;                  daemon->domain_suffix = d;
                 else 
                   ret_err(gen_err);
             }              }
         }          }
       break;        break;
               
       case LOPT_CPE_ID: /* --add-dns-client */
         if (arg)
           daemon->dns_client_id = opt_string_alloc(arg);
         break;
   
       case LOPT_ADD_MAC: /* --add-mac */
         if (!arg)
           set_option_bool(OPT_ADD_MAC);
         else
           {
             unhide_metas(arg);
             if (strcmp(arg, "base64") == 0)
               set_option_bool(OPT_MAC_B64);
             else if (strcmp(arg, "text") == 0)
               set_option_bool(OPT_MAC_HEX);
             else
               ret_err(gen_err);
           }
         break;
   
     case 'u':  /* --user */      case 'u':  /* --user */
       daemon->username = opt_string_alloc(arg);        daemon->username = opt_string_alloc(arg);
       break;        break;
Line 1870  static int one_opt(int option, char *arg, char *errstr Line 2212  static int one_opt(int option, char *arg, char *errstr
       } while (arg);        } while (arg);
       break;        break;
               
       case LOPT_TFTP: /* --enable-tftp */
         set_option_bool(OPT_TFTP);
         if (!arg)
           break;
         /* fall through */
   
     case 'I':  /* --except-interface */      case 'I':  /* --except-interface */
     case '2':  /* --no-dhcp-interface */      case '2':  /* --no-dhcp-interface */
       do {        do {
Line 1881  static int one_opt(int option, char *arg, char *errstr Line 2229  static int one_opt(int option, char *arg, char *errstr
             new->next = daemon->if_except;              new->next = daemon->if_except;
             daemon->if_except = new;              daemon->if_except = new;
           }            }
           else if (option == LOPT_TFTP)
              {
               new->next = daemon->tftp_interfaces;
               daemon->tftp_interfaces = new;
             }
         else          else
           {            {
             new->next = daemon->dhcp_except;              new->next = daemon->dhcp_except;
Line 1891  static int one_opt(int option, char *arg, char *errstr Line 2244  static int one_opt(int option, char *arg, char *errstr
       break;        break;
               
     case 'B':  /* --bogus-nxdomain */      case 'B':  /* --bogus-nxdomain */
      {    case LOPT_IGNORE_ADDR: /* --ignore-address */
      {
         struct in_addr addr;          struct in_addr addr;
         unhide_metas(arg);          unhide_metas(arg);
        if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)        if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
           {            {
             struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));              struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
            baddr->next = daemon->bogus_addr;            if (option == 'B')
            daemon->bogus_addr = baddr;              {
                 baddr->next = daemon->bogus_addr;
                 daemon->bogus_addr = baddr;
               }
             else
               {
                 baddr->next = daemon->ignore_addr;
                 daemon->ignore_addr = baddr;
               }
             baddr->addr = addr;              baddr->addr = addr;
           }            }
         else          else
Line 1912  static int one_opt(int option, char *arg, char *errstr Line 2274  static int one_opt(int option, char *arg, char *errstr
         struct iname *new = opt_malloc(sizeof(struct iname));          struct iname *new = opt_malloc(sizeof(struct iname));
         comma = split(arg);          comma = split(arg);
         unhide_metas(arg);          unhide_metas(arg);
        if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)        if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
           {            {
             new->addr.sa.sa_family = AF_INET;              new->addr.sa.sa_family = AF_INET;
             new->addr.in.sin_port = 0;              new->addr.in.sin_port = 0;
Line 1992  static int one_opt(int option, char *arg, char *errstr Line 2354  static int one_opt(int option, char *arg, char *errstr
           {            {
             newlist = opt_malloc(sizeof(struct server));              newlist = opt_malloc(sizeof(struct server));
             memset(newlist, 0, sizeof(struct server));              memset(newlist, 0, sizeof(struct server));
   #ifdef HAVE_LOOP
               newlist->uid = rand32();
   #endif
           }            }
                   
           if (servers_only && option == 'S')
             newlist->flags |= SERV_FROM_FILE;
           
         if (option == 'A')          if (option == 'A')
           {            {
             newlist->flags |= SERV_LITERAL_ADDRESS;              newlist->flags |= SERV_LITERAL_ADDRESS;
Line 2007  static int one_opt(int option, char *arg, char *errstr Line 2375  static int one_opt(int option, char *arg, char *errstr
           {            {
             if (!(newlist->flags & SERV_NO_REBIND))              if (!(newlist->flags & SERV_NO_REBIND))
               newlist->flags |= SERV_NO_ADDR; /* no server */                newlist->flags |= SERV_NO_ADDR; /* no server */
             if (newlist->flags & SERV_LITERAL_ADDRESS)  
               ret_err(gen_err);  
           }            }
   
         else if (strcmp(arg, "#") == 0)          else if (strcmp(arg, "#") == 0)
Line 2038  static int one_opt(int option, char *arg, char *errstr Line 2404  static int one_opt(int option, char *arg, char *errstr
         break;          break;
       }        }
   
       case LOPT_REV_SERV: /* --rev-server */
         {
           char *string;
           int size;
           struct server *serv;
           struct in_addr addr4;
   #ifdef HAVE_IPV6
           struct in6_addr addr6;
   #endif
    
           unhide_metas(arg);
           if (!arg || !(comma=split(arg)) || !(string = split_chr(arg, '/')) || !atoi_check(string, &size))
             ret_err(gen_err);
   
           if (inet_pton(AF_INET, arg, &addr4))
             serv = add_rev4(addr4, size);
   #ifdef HAVE_IPV6
           else if (inet_pton(AF_INET6, arg, &addr6))
             serv = add_rev6(&addr6, size);
   #endif
           else
             ret_err(gen_err);
    
           string = parse_server(comma, &serv->addr, &serv->source_addr, serv->interface, &serv->flags);
           
           if (string)
             ret_err(string);
           
           if (servers_only)
             serv->flags |= SERV_FROM_FILE;
           
           break;
         }
   
     case LOPT_IPSET: /* --ipset */      case LOPT_IPSET: /* --ipset */
 #ifndef HAVE_IPSET  #ifndef HAVE_IPSET
       ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));        ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
Line 2136  static int one_opt(int option, char *arg, char *errstr Line 2536  static int one_opt(int option, char *arg, char *errstr
         ret_err(gen_err);          ret_err(gen_err);
       break;        break;
   
       case LOPT_MAXPORT:  /* --max-port */
         if (!atoi_check16(arg, &daemon->max_port))
           ret_err(gen_err);
         break;
   
     case '0':  /* --dns-forward-max */      case '0':  /* --dns-forward-max */
       if (!atoi_check(arg, &daemon->ftabsize))        if (!atoi_check(arg, &daemon->ftabsize))
         ret_err(gen_err);          ret_err(gen_err);
       break;          break;  
           
       case 'q': /* --log-queries */
         set_option_bool(OPT_LOG);
         if (arg && strcmp(arg, "extra") == 0)
           set_option_bool(OPT_EXTRALOG);
         break;
   
     case LOPT_MAX_LOGS:  /* --log-async */      case LOPT_MAX_LOGS:  /* --log-async */
       daemon->max_logs = LOG_MAX; /* default */        daemon->max_logs = LOG_MAX; /* default */
       if (arg && !atoi_check(arg, &daemon->max_logs))        if (arg && !atoi_check(arg, &daemon->max_logs))
Line 2170  static int one_opt(int option, char *arg, char *errstr Line 2581  static int one_opt(int option, char *arg, char *errstr
     case 'T':         /* --local-ttl */      case 'T':         /* --local-ttl */
     case LOPT_NEGTTL: /* --neg-ttl */      case LOPT_NEGTTL: /* --neg-ttl */
     case LOPT_MAXTTL: /* --max-ttl */      case LOPT_MAXTTL: /* --max-ttl */
       case LOPT_MINCTTL: /* --min-cache-ttl */
     case LOPT_MAXCTTL: /* --max-cache-ttl */      case LOPT_MAXCTTL: /* --max-cache-ttl */
     case LOPT_AUTHTTL: /* --auth-ttl */      case LOPT_AUTHTTL: /* --auth-ttl */
       case LOPT_DHCPTTL: /* --dhcp-ttl */
       {        {
         int ttl;          int ttl;
         if (!atoi_check(arg, &ttl))          if (!atoi_check(arg, &ttl))
Line 2180  static int one_opt(int option, char *arg, char *errstr Line 2593  static int one_opt(int option, char *arg, char *errstr
           daemon->neg_ttl = (unsigned long)ttl;            daemon->neg_ttl = (unsigned long)ttl;
         else if (option == LOPT_MAXTTL)          else if (option == LOPT_MAXTTL)
           daemon->max_ttl = (unsigned long)ttl;            daemon->max_ttl = (unsigned long)ttl;
           else if (option == LOPT_MINCTTL)
             {
               if (ttl > TTL_FLOOR_LIMIT)
                 ttl = TTL_FLOOR_LIMIT;
               daemon->min_cache_ttl = (unsigned long)ttl;
             }
         else if (option == LOPT_MAXCTTL)          else if (option == LOPT_MAXCTTL)
           daemon->max_cache_ttl = (unsigned long)ttl;            daemon->max_cache_ttl = (unsigned long)ttl;
         else if (option == LOPT_AUTHTTL)          else if (option == LOPT_AUTHTTL)
           daemon->auth_ttl = (unsigned long)ttl;            daemon->auth_ttl = (unsigned long)ttl;
           else if (option == LOPT_DHCPTTL)
             {
               daemon->dhcp_ttl = (unsigned long)ttl;
               daemon->use_dhcp_ttl = 1;
             }
         else          else
           daemon->local_ttl = (unsigned long)ttl;            daemon->local_ttl = (unsigned long)ttl;
         break;          break;
Line 2202  static int one_opt(int option, char *arg, char *errstr Line 2626  static int one_opt(int option, char *arg, char *errstr
         ret_err(gen_err);          ret_err(gen_err);
       break;          break;  
   
       case LOPT_TFTP_MTU:  /*  --tftp-mtu */
         if (!atoi_check(arg, &daemon->tftp_mtu))
           ret_err(gen_err);
         break;
   
     case LOPT_PREFIX: /* --tftp-prefix */      case LOPT_PREFIX: /* --tftp-prefix */
       comma = split(arg);        comma = split(arg);
       if (comma)        if (comma)
Line 2289  static int one_opt(int option, char *arg, char *errstr Line 2718  static int one_opt(int option, char *arg, char *errstr
                     struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));                      struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
                     tt->net = opt_string_alloc(arg+4);                      tt->net = opt_string_alloc(arg+4);
                     tt->next = new->filter;                      tt->next = new->filter;
                    new->filter = tt;                    /* ignore empty tag */
                     if (tt->net)
                       new->filter = tt;
                   }                    }
                 else                  else
                   {                    {
Line 2336  static int one_opt(int option, char *arg, char *errstr Line 2767  static int one_opt(int option, char *arg, char *errstr
               }                }
                           
             if (k >= 3 && strchr(a[2], '.') &&                if (k >= 3 && strchr(a[2], '.') &&  
                ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))                (inet_pton(AF_INET, a[2], &new->netmask) > 0))
               {                {
                 new->flags |= CONTEXT_NETMASK;                  new->flags |= CONTEXT_NETMASK;
                 leasepos = 3;                  leasepos = 3;
                 if (!is_same_net(new->start, new->end, new->netmask))                  if (!is_same_net(new->start, new->end, new->netmask))
                   ret_err(_("inconsistent DHCP range"));                    ret_err(_("inconsistent DHCP range"));
              }                
                           
            if (k >= 4 && strchr(a[3], '.') &&                  if (k >= 4 && strchr(a[3], '.') &&  
                ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))                    (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
              {                  {
                new->flags |= CONTEXT_BRDCAST;                    new->flags |= CONTEXT_BRDCAST;
                leasepos = 4;                    leasepos = 4;
                   }
               }                }
           }            }
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
         else if (inet_pton(AF_INET6, a[0], &new->start6))          else if (inet_pton(AF_INET6, a[0], &new->start6))
           {            {
               new->flags |= CONTEXT_V6; 
             new->prefix = 64; /* default */              new->prefix = 64; /* default */
             new->end6 = new->start6;              new->end6 = new->start6;
                        new->next = daemon->dhcp6;
            /* dhcp-range=:: enables DHCP stateless on any interface */            daemon->dhcp6 = new;
            if (IN6_IS_ADDR_UNSPECIFIED(&new->start6))
              new->prefix = 0; 
             
             for (leasepos = 1; leasepos < k; leasepos++)              for (leasepos = 1; leasepos < k; leasepos++)
               {                {
                 if (strcmp(a[leasepos], "static") == 0)                  if (strcmp(a[leasepos], "static") == 0)
                   new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;                    new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
                 else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )                  else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
                  new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;                  new->flags |= CONTEXT_RA;
                 else if (strcmp(a[leasepos], "ra-names") == 0)                  else if (strcmp(a[leasepos], "ra-names") == 0)
                   new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;                    new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
                   else if (strcmp(a[leasepos], "ra-advrouter") == 0)
                     new->flags |= CONTEXT_RA_ROUTER | CONTEXT_RA;
                 else if (strcmp(a[leasepos], "ra-stateless") == 0)                  else if (strcmp(a[leasepos], "ra-stateless") == 0)
                   new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;                    new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
                   else if (strcmp(a[leasepos], "off-link") == 0)
                     new->flags |= CONTEXT_RA_OFF_LINK;
                 else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))                  else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
                   new->flags |= CONTEXT_DHCP;                     new->flags |= CONTEXT_DHCP; 
                 else if (strstr(a[leasepos], "constructor:") == a[leasepos])                  else if (strstr(a[leasepos], "constructor:") == a[leasepos])
Line 2381  static int one_opt(int option, char *arg, char *errstr Line 2816  static int one_opt(int option, char *arg, char *errstr
                 else                    else  
                   break;                    break;
               }                }
                                         
            new->next = daemon->dhcp6; 
            daemon->dhcp6 = new; 
                      
             /* bare integer < 128 is prefix value */              /* bare integer < 128 is prefix value */
             if (leasepos < k)              if (leasepos < k)
               {                {
Line 2396  static int one_opt(int option, char *arg, char *errstr Line 2828  static int one_opt(int option, char *arg, char *errstr
                   {                    {
                     new->prefix = pref;                      new->prefix = pref;
                     leasepos++;                      leasepos++;
                     if (new->prefix != 64)  
                       {  
                         if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))  
                           ret_err(_("prefix must be exactly 64 for RA subnets"));  
                         else if (new->template_interface)  
                           ret_err(_("prefix must be exactly 64 for subnet constructors"));  
                       }  
                     if (new->prefix < 64)  
                       ret_err(_("prefix must be at least 64"));  
                   }                    }
               }                }
                           
               if (new->prefix != 64)
                 {
                   if (new->flags & CONTEXT_RA)
                     ret_err(_("prefix length must be exactly 64 for RA subnets"));
                   else if (new->flags & CONTEXT_TEMPLATE)
                     ret_err(_("prefix length must be exactly 64 for subnet constructors"));
                 }
   
               if (new->prefix < 64)
                 ret_err(_("prefix length must be at least 64"));
               
             if (!is_same_net6(&new->start6, &new->end6, new->prefix))              if (!is_same_net6(&new->start6, &new->end6, new->prefix))
               ret_err(_("inconsistent DHCPv6 range"));                ret_err(_("inconsistent DHCPv6 range"));
   
               /* dhcp-range=:: enables DHCP stateless on any interface */
               if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
                 new->prefix = 0;
               
               if (new->flags & CONTEXT_TEMPLATE)
                 {
                   struct in6_addr zero;
                   memset(&zero, 0, sizeof(zero));
                   if (!is_same_net6(&zero, &new->start6, new->prefix))
                     ret_err(_("prefix must be zero with \"constructor:\" argument"));
                 }
               
             if (addr6part(&new->start6) > addr6part(&new->end6))              if (addr6part(&new->start6) > addr6part(&new->end6))
               {                {
                 struct in6_addr tmp = new->start6;                  struct in6_addr tmp = new->start6;
Line 2423  static int one_opt(int option, char *arg, char *errstr Line 2870  static int one_opt(int option, char *arg, char *errstr
                   
         if (leasepos < k)          if (leasepos < k)
           {            {
               if (leasepos != k-1)
                 ret_err(_("bad dhcp-range"));
               
             if (strcmp(a[leasepos], "infinite") == 0)              if (strcmp(a[leasepos], "infinite") == 0)
               new->lease_time = 0xffffffff;                new->lease_time = 0xffffffff;
             else if (strcmp(a[leasepos], "deprecated") == 0)              else if (strcmp(a[leasepos], "deprecated") == 0)
Line 2477  static int one_opt(int option, char *arg, char *errstr Line 2927  static int one_opt(int option, char *arg, char *errstr
     case 'G':  /* --dhcp-host */      case 'G':  /* --dhcp-host */
       {        {
         int j, k = 0;          int j, k = 0;
        char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };        char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
         struct dhcp_config *new;          struct dhcp_config *new;
         struct in_addr in;          struct in_addr in;
                   
Line 2489  static int one_opt(int option, char *arg, char *errstr Line 2939  static int one_opt(int option, char *arg, char *errstr
         new->netid = NULL;          new->netid = NULL;
   
         if ((a[0] = arg))          if ((a[0] = arg))
          for (k = 1; k < 6; k++)          for (k = 1; k < 7; k++)
             if (!(a[k] = split(a[k-1])))              if (!(a[k] = split(a[k-1])))
               break;                break;
                   
Line 2517  static int one_opt(int option, char *arg, char *errstr Line 2967  static int one_opt(int option, char *arg, char *errstr
                         }                          }
   
                       if (len == -1)                        if (len == -1)
   
                         ret_err(_("bad hex constant"));                          ret_err(_("bad hex constant"));
                       else if ((new->clid = opt_malloc(len)))                        else if ((new->clid = opt_malloc(len)))
                         {                          {
Line 2575  static int one_opt(int option, char *arg, char *errstr Line 3024  static int one_opt(int option, char *arg, char *errstr
                     }                                     }               
                 }                  }
             }              }
          else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)          else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
             {              {
               struct dhcp_config *configs;                struct dhcp_config *configs;
                               
Line 2595  static int one_opt(int option, char *arg, char *errstr Line 3044  static int one_opt(int option, char *arg, char *errstr
           else            else
             {              {
               char *cp, *lastp = NULL, last = 0;                char *cp, *lastp = NULL, last = 0;
              int fac = 1;              int fac = 1, isdig = 0;
                               
               if (strlen(a[j]) > 1)                if (strlen(a[j]) > 1)
                 {                  {
Line 2626  static int one_opt(int option, char *arg, char *errstr Line 3075  static int one_opt(int option, char *arg, char *errstr
                 }                  }
                               
               for (cp = a[j]; *cp; cp++)                for (cp = a[j]; *cp; cp++)
                if (!isdigit((unsigned char)*cp) && *cp != ' ')                if (isdigit((unsigned char)*cp))
                   isdig = 1;
                 else if (*cp != ' ')
                   break;                    break;
              
               if (*cp)                if (*cp)
                 {                  {
                   if (lastp)                    if (lastp)
Line 2650  static int one_opt(int option, char *arg, char *errstr Line 3101  static int one_opt(int option, char *arg, char *errstr
                       new->domain = strip_hostname(new->hostname);                                              new->domain = strip_hostname(new->hostname);                      
                     }                      }
                 }                  }
              else              else if (isdig)
                 {                  {
                   new->lease_time = atoi(a[j]) * fac;                     new->lease_time = atoi(a[j]) * fac; 
                   /* Leases of a minute or less confuse                    /* Leases of a minute or less confuse
Line 2772  static int one_opt(int option, char *arg, char *errstr Line 3223  static int one_opt(int option, char *arg, char *errstr
                 if (comma)                  if (comma)
                   {                    {
                     unhide_metas(comma);                      unhide_metas(comma);
                    if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) {                    if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
                      {
                      /*                        /*
                       * The user may have specified the tftp hostname here.                         * The user may have specified the tftp hostname here.
                       * save it so that it can be resolved/looked up during                         * save it so that it can be resolved/looked up during
                       * actual dhcp_reply().                         * actual dhcp_reply().
                       */                                */     
                        
                      tftp_sname = opt_string_alloc(comma);                        tftp_sname = opt_string_alloc(comma);
                      dhcp_next_server.s_addr = 0;                        dhcp_next_server.s_addr = 0;
                    }                      }
                   }                    }
               }                }
                           
Line 2795  static int one_opt(int option, char *arg, char *errstr Line 3246  static int one_opt(int option, char *arg, char *errstr
             new->next = daemon->boot_config;              new->next = daemon->boot_config;
             daemon->boot_config = new;              daemon->boot_config = new;
           }            }
              
         break;          break;
       }        }
   
Line 2847  static int one_opt(int option, char *arg, char *errstr Line 3298  static int one_opt(int option, char *arg, char *errstr
        {         {
          struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));           struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
          char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",           char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
                         "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };                           "IA32_EFI", "x86-64_EFI", "Xscale_EFI", "BC_EFI",
                          "ARM32_EFI", "ARM64_EFI", NULL };  
          static int boottype = 32768;           static int boottype = 32768;
                     
          new->netid = NULL;           new->netid = NULL;
Line 3111  static int one_opt(int option, char *arg, char *errstr Line 3563  static int one_opt(int option, char *arg, char *errstr
       while (arg) {        while (arg) {
         struct addr_list *new = opt_malloc(sizeof(struct addr_list));          struct addr_list *new = opt_malloc(sizeof(struct addr_list));
         comma = split(arg);          comma = split(arg);
        if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)        if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
           ret_err(_("bad dhcp-proxy address"));            ret_err(_("bad dhcp-proxy address"));
         new->next = daemon->override_relays;          new->next = daemon->override_relays;
         daemon->override_relays = new;          daemon->override_relays = new;
         arg = comma;          arg = comma;
       }        }
       break;        break;
   
       case LOPT_RELAY: /* --dhcp-relay */
         {
           struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
           comma = split(arg);
           new->interface = opt_string_alloc(split(comma));
           new->iface_index = 0;
           if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
             {
               new->next = daemon->relay4;
               daemon->relay4 = new;
             }
   #ifdef HAVE_DHCP6
           else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
             {
               new->next = daemon->relay6;
               daemon->relay6 = new;
             }
 #endif  #endif
           else
             ret_err(_("Bad dhcp-relay"));
           
           break;
         }
   
   #endif
               
 #ifdef HAVE_DHCP6  #ifdef HAVE_DHCP6
       case LOPT_RA_PARAM: /* --ra-param */
         if ((comma = split(arg)))
           {
             struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
             new->lifetime = -1;
             new->prio = 0;
             new->name = opt_string_alloc(arg);
             if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
               {
                 if (*comma == 'l' || *comma == 'L')
                   new->prio = 0x18;
                 else
                   new->prio = 0x08;
                 comma = split(comma);
               }
              arg = split(comma);
              if (!atoi_check(comma, &new->interval) || 
                 (arg && !atoi_check(arg, &new->lifetime)))
               ret_err(_("bad RA-params"));
             
             new->next = daemon->ra_interfaces;
             daemon->ra_interfaces = new;
           }
         break;
         
     case LOPT_DUID: /* --dhcp-duid */      case LOPT_DUID: /* --dhcp-duid */
       if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))        if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
         ret_err(_("bad DUID"));          ret_err(_("bad DUID"));
Line 3154  static int one_opt(int option, char *arg, char *errstr Line 3656  static int one_opt(int option, char *arg, char *errstr
         dash = split_chr(a[0], '-');          dash = split_chr(a[0], '-');
   
         if ((k < 2) ||           if ((k < 2) || 
            ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||            (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
            ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))            (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
           option = '?';            option = '?';
                   
        if (k == 3)        if (k == 3 && !inet_pton(AF_INET, a[2], &new->mask))
          new->mask.s_addr = inet_addr(a[2]);          option = '?';
                   
         if (dash &&           if (dash && 
            ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||            (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
              !is_same_net(new->in, new->end, new->mask) ||               !is_same_net(new->in, new->end, new->mask) ||
              ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))               ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
           ret_err(_("invalid alias range"));            ret_err(_("invalid alias range"));
Line 3182  static int one_opt(int option, char *arg, char *errstr Line 3684  static int one_opt(int option, char *arg, char *errstr
                   
         new = opt_malloc(sizeof(struct interface_name));          new = opt_malloc(sizeof(struct interface_name));
         new->next = NULL;          new->next = NULL;
           new->addr = NULL;
           
         /* Add to the end of the list, so that first name          /* Add to the end of the list, so that first name
            of an interface is used for PTR lookups. */             of an interface is used for PTR lookups. */
         for (up = &daemon->int_names; *up; up = &((*up)->next));          for (up = &daemon->int_names; *up; up = &((*up)->next));
         *up = new;          *up = new;
         new->name = domain;          new->name = domain;
           new->family = 0;
           arg = split_chr(comma, '/');
           if (arg)
             {
               if (strcmp(arg, "4") == 0)
                 new->family = AF_INET;
   #ifdef HAVE_IPV6
               else if (strcmp(arg, "6") == 0)
                 new->family = AF_INET6;
   #endif
               else
                 ret_err(gen_err);
             } 
         new->intr = opt_string_alloc(comma);          new->intr = opt_string_alloc(comma);
         break;          break;
       }        }
Line 3194  static int one_opt(int option, char *arg, char *errstr Line 3711  static int one_opt(int option, char *arg, char *errstr
     case LOPT_CNAME: /* --cname */      case LOPT_CNAME: /* --cname */
       {        {
         struct cname *new;          struct cname *new;
        char *alias;        char *alias, *target, *ttls;
        char *target;        int ttl = -1;
   
         if (!(comma = split(arg)))          if (!(comma = split(arg)))
           ret_err(gen_err);            ret_err(gen_err);
                   
           if ((ttls = split(comma)) && !atoi_check(ttls, &ttl))
             ret_err(_("bad TTL"));
           
         alias = canonicalise_opt(arg);          alias = canonicalise_opt(arg);
         target = canonicalise_opt(comma);          target = canonicalise_opt(comma);
                           
Line 3215  static int one_opt(int option, char *arg, char *errstr Line 3735  static int one_opt(int option, char *arg, char *errstr
             daemon->cnames = new;              daemon->cnames = new;
             new->alias = alias;              new->alias = alias;
             new->target = target;              new->target = target;
               new->ttl = ttl;
           }            }
               
         break;          break;
Line 3280  static int one_opt(int option, char *arg, char *errstr Line 3801  static int one_opt(int option, char *arg, char *errstr
     case LOPT_RR: /* dns-rr */      case LOPT_RR: /* dns-rr */
       {        {
         struct txt_record *new;          struct txt_record *new;
        size_t len;        size_t len = 0;
         char *data;          char *data;
         int val;          int val;
   
Line 3321  static int one_opt(int option, char *arg, char *errstr Line 3842  static int one_opt(int option, char *arg, char *errstr
         new->next = daemon->txt;          new->next = daemon->txt;
         daemon->txt = new;          daemon->txt = new;
         new->class = C_IN;          new->class = C_IN;
                new->stat = 0;
 
         if (!(new->name = canonicalise_opt(arg)))          if (!(new->name = canonicalise_opt(arg)))
           ret_err(_("bad TXT record"));            ret_err(_("bad TXT record"));
                   
Line 3387  static int one_opt(int option, char *arg, char *errstr Line 3909  static int one_opt(int option, char *arg, char *errstr
                     if (!atoi_check16(arg, &priority))                      if (!atoi_check16(arg, &priority))
                       ret_err(_("invalid priority"));                        ret_err(_("invalid priority"));
                                                   
                    if (comma)                    if (comma && !atoi_check16(comma, &weight))
                      {                      ret_err(_("invalid weight"));
                        arg = comma; 
                        comma = split(arg); 
                        if (!atoi_check16(arg, &weight)) 
                          ret_err(_("invalid weight")); 
                      } 
                   }                    }
               }                }
           }            }
Line 3414  static int one_opt(int option, char *arg, char *errstr Line 3931  static int one_opt(int option, char *arg, char *errstr
       {        {
         struct host_record *new = opt_malloc(sizeof(struct host_record));          struct host_record *new = opt_malloc(sizeof(struct host_record));
         memset(new, 0, sizeof(struct host_record));          memset(new, 0, sizeof(struct host_record));
                new->ttl = -1;
 
         if (!arg || !(comma = split(arg)))          if (!arg || !(comma = split(arg)))
           ret_err(_("Bad host-record"));            ret_err(_("Bad host-record"));
                   
         while (arg)          while (arg)
           {            {
             struct all_addr addr;              struct all_addr addr;
            if (inet_pton(AF_INET, arg, &addr))            char *dig;
 
             for (dig = arg; *dig != 0; dig++)
               if (*dig < '0' || *dig > '9')
                 break;
             if (*dig == 0)
               new->ttl = atoi(arg);
             else if (inet_pton(AF_INET, arg, &addr))
               new->addr = addr.addr.addr4;                new->addr = addr.addr.addr4;
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
             else if (inet_pton(AF_INET6, arg, &addr))              else if (inet_pton(AF_INET6, arg, &addr))
Line 3461  static int one_opt(int option, char *arg, char *errstr Line 3986  static int one_opt(int option, char *arg, char *errstr
         daemon->host_records_tail = new;          daemon->host_records_tail = new;
         break;          break;
       }        }
      
 #ifdef HAVE_DNSSEC
     case LOPT_DNSSEC_STAMP:
       daemon->timestamp_file = opt_string_alloc(arg); 
       break;
 
     case LOPT_TRUST_ANCHOR:
       {
         struct ds_config *new = opt_malloc(sizeof(struct ds_config));
         char *cp, *cp1, *keyhex, *digest, *algo = NULL;
         int len;
         
         new->class = C_IN;
 
         if ((comma = split(arg)) && (algo = split(comma)))
           {
             int class = 0;
             if (strcmp(comma, "IN") == 0)
               class = C_IN;
             else if (strcmp(comma, "CH") == 0)
               class = C_CHAOS;
             else if (strcmp(comma, "HS") == 0)
               class = C_HESIOD;
             
             if (class != 0)
               {
                 new->class = class;
                 comma = algo;
                 algo = split(comma);
               }
           }
                   
         if (!comma || !algo || !(digest = split(algo)) || !(keyhex = split(digest)) ||
             !atoi_check16(comma, &new->keytag) || 
             !atoi_check8(algo, &new->algo) ||
             !atoi_check8(digest, &new->digest_type) ||
             !(new->name = canonicalise_opt(arg)))
           ret_err(_("bad trust anchor"));
             
         /* Upper bound on length */
         len = (2*strlen(keyhex))+1;
         new->digest = opt_malloc(len);
         unhide_metas(keyhex);
         /* 4034: "Whitespace is allowed within digits" */
         for (cp = keyhex; *cp; )
           if (isspace(*cp))
             for (cp1 = cp; *cp1; cp1++)
               *cp1 = *(cp1+1);
           else
             cp++;
         if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1)
           ret_err(_("bad HEX in trust anchor"));
         
         new->next = daemon->ds;
         daemon->ds = new;
         
         break;
       }
 #endif
                 
     default:      default:
      ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"));      ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
               
     }      }
       
Line 3477  static void read_file(char *file, FILE *f, int hard_op Line 4061  static void read_file(char *file, FILE *f, int hard_op
       
   while (fgets(buff, MAXDNAME, f))    while (fgets(buff, MAXDNAME, f))
     {      {
      int white, i, option = hard_opt;      int white, i;
       volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
       char *errmess, *p, *arg = NULL, *start;        char *errmess, *p, *arg = NULL, *start;
       size_t len;        size_t len;
   
       /* Memory allocation failure longjmps here if mem_recover == 1 */         /* Memory allocation failure longjmps here if mem_recover == 1 */ 
      if (option != 0)      if (option != 0 || hard_opt == LOPT_REV_SERV)
         {          {
           if (setjmp(mem_jmp))            if (setjmp(mem_jmp))
             continue;              continue;
Line 3583  static void read_file(char *file, FILE *f, int hard_op Line 4168  static void read_file(char *file, FILE *f, int hard_op
             errmess = _("extraneous parameter");              errmess = _("extraneous parameter");
           else if (opts[i].has_arg == 1 && !arg)            else if (opts[i].has_arg == 1 && !arg)
             errmess = _("missing parameter");              errmess = _("missing parameter");
             else if (hard_opt == LOPT_REV_SERV && option != 'S' && option != LOPT_REV_SERV)
               errmess = _("illegal option");
         }          }
   
     oops:      oops:
       if (errmess)        if (errmess)
         strcpy(daemon->namebuff, errmess);          strcpy(daemon->namebuff, errmess);
                       
      if (errmess || !one_opt(option, arg, buff, _("error"), 0))      if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
         {          {
           sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);            sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
           if (hard_opt != 0)            if (hard_opt != 0)
Line 3603  static void read_file(char *file, FILE *f, int hard_op Line 4190  static void read_file(char *file, FILE *f, int hard_op
   fclose(f);    fclose(f);
 }  }
   
   #ifdef HAVE_DHCP
   int option_read_dynfile(char *file, int flags)
   {
     my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file);
     
     if (flags & AH_DHCP_HST)
       return one_file(file, LOPT_BANK);
     else if (flags & AH_DHCP_OPT)
       return one_file(file, LOPT_OPTS);
     
     return 0;
   }
   #endif
   
 static int one_file(char *file, int hard_opt)  static int one_file(char *file, int hard_opt)
 {  {
   FILE *f;    FILE *f;
Line 3674  static int one_file(char *file, int hard_opt) Line 4275  static int one_file(char *file, int hard_opt)
 /* expand any name which is a directory */  /* expand any name which is a directory */
 struct hostsfile *expand_filelist(struct hostsfile *list)  struct hostsfile *expand_filelist(struct hostsfile *list)
 {  {
  int i;  unsigned int i;
   struct hostsfile *ah;    struct hostsfile *ah;
   
  for (i = 0, ah = list; ah; ah = ah->next)  /* find largest used index */
   for (i = SRC_AH, ah = list; ah; ah = ah->next)
     {      {
       if (i <= ah->index)        if (i <= ah->index)
         i = ah->index + 1;          i = ah->index + 1;
Line 3699  struct hostsfile *expand_filelist(struct hostsfile *li Line 4301  struct hostsfile *expand_filelist(struct hostsfile *li
                           
             /* don't read this as a file */              /* don't read this as a file */
             ah->flags |= AH_INACTIVE;              ah->flags |= AH_INACTIVE;
            
             if (!(dir_stream = opendir(ah->fname)))              if (!(dir_stream = opendir(ah->fname)))
               my_syslog(LOG_ERR, _("cannot access directory %s: %s"),                 my_syslog(LOG_ERR, _("cannot access directory %s: %s"), 
                         ah->fname, strerror(errno));                          ah->fname, strerror(errno));
Line 3771  struct hostsfile *expand_filelist(struct hostsfile *li Line 4373  struct hostsfile *expand_filelist(struct hostsfile *li
   return list;    return list;
 }  }
   
   void read_servers_file(void)
   {
     FILE *f;
   
     if (!(f = fopen(daemon->servers_file, "r")))
       {
          my_syslog(LOG_ERR, _("cannot read %s: %s"), daemon->servers_file, strerror(errno));
          return;
       }
     
     mark_servers(SERV_FROM_FILE);
     cleanup_servers();
     
     read_file(daemon->servers_file, f, LOPT_REV_SERV);
   }
    
   
 #ifdef HAVE_DHCP  #ifdef HAVE_DHCP
 void reread_dhcp(void)  void reread_dhcp(void)
 {  {
Line 3895  void read_opts(int argc, char **argv, char *compile_op Line 4513  void read_opts(int argc, char **argv, char *compile_op
   daemon->soa_refresh = SOA_REFRESH;    daemon->soa_refresh = SOA_REFRESH;
   daemon->soa_retry = SOA_RETRY;    daemon->soa_retry = SOA_RETRY;
   daemon->soa_expiry = SOA_EXPIRY;    daemon->soa_expiry = SOA_EXPIRY;
  add_txt("version.bind", "dnsmasq-" VERSION );  daemon->max_port = MAX_PORT;
  add_txt("authors.bind", "Simon Kelley"); 
  add_txt("copyright.bind", COPYRIGHT); 
   
     add_txt("version.bind", "dnsmasq-" VERSION, 0 );
     add_txt("authors.bind", "Simon Kelley", 0);
     add_txt("copyright.bind", COPYRIGHT, 0);
     add_txt("cachesize.bind", NULL, TXT_STAT_CACHESIZE);
     add_txt("insertions.bind", NULL, TXT_STAT_INSERTS);
     add_txt("evictions.bind", NULL, TXT_STAT_EVICTIONS);
     add_txt("misses.bind", NULL, TXT_STAT_MISSES);
     add_txt("hits.bind", NULL, TXT_STAT_HITS);
   #ifdef HAVE_AUTH
     add_txt("auth.bind", NULL, TXT_STAT_AUTH);
   #endif
     add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
   
   while (1)     while (1) 
     {      {
 #ifdef HAVE_GETOPT_LONG  #ifdef HAVE_GETOPT_LONG
Line 3964  void read_opts(int argc, char **argv, char *compile_op Line 4593  void read_opts(int argc, char **argv, char *compile_op
       else        else
         {          {
 #ifdef HAVE_GETOPT_LONG  #ifdef HAVE_GETOPT_LONG
          if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))          if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1, 0))
 #else   #else 
          if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))             if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0)) 
 #endif    #endif  
             die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);              die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
         }          }
     }      }
   
   if (conffile)    if (conffile)
    one_file(conffile, conffile_opt);    {
       one_file(conffile, conffile_opt);
       if (conffile_opt == 0)
         free(conffile);
     }
   
   /* port might not be known when the address is parsed - fill in here */    /* port might not be known when the address is parsed - fill in here */
   if (daemon->servers)    if (daemon->servers)
Line 3988  void read_opts(int argc, char **argv, char *compile_op Line 4621  void read_opts(int argc, char **argv, char *compile_op
             else if (tmp->source_addr.sa.sa_family == AF_INET6)              else if (tmp->source_addr.sa.sa_family == AF_INET6)
               tmp->source_addr.in6.sin6_port = htons(daemon->query_port);                tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
 #endif   #endif 
          }           }
    }    } 
       
     if (daemon->host_records)
       {
         struct host_record *hr;
         
         for (hr = daemon->host_records; hr; hr = hr->next)
           if (hr->ttl == -1)
             hr->ttl = daemon->local_ttl;
       }
   
     if (daemon->cnames)
       {
         struct cname *cn;
         
         for (cn = daemon->cnames; cn; cn = cn->next)
           if (cn->ttl == -1)
             cn->ttl = daemon->local_ttl;
       }
   
   if (daemon->if_addrs)    if (daemon->if_addrs)
     {        {  
       struct iname *tmp;        struct iname *tmp;
Line 4097  void read_opts(int argc, char **argv, char *compile_op Line 4748  void read_opts(int argc, char **argv, char *compile_op
     }      }
   else if (option_bool(OPT_DHCP_FQDN))    else if (option_bool(OPT_DHCP_FQDN))
     die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);      die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
   
     /* If there's access-control config, then ignore --local-service, it's intended
        as a system default to keep otherwise unconfigured installations safe. */
     if (daemon->if_names || daemon->if_except || daemon->if_addrs || daemon->authserver)
       reset_option_bool(OPT_LOCAL_SERVICE); 
   
   if (testmode)    if (testmode)
     {      {

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>