"Fossies" - the Fresh Open Source Software Archive

Member "nsd-4.3.6/options.c" (6 Apr 2021, 62370 Bytes) of package /linux/misc/dns/nsd-4.3.6.tar.gz:


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

    1 /*
    2  * options.c -- options functions.
    3  *
    4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
    5  *
    6  * See LICENSE for the license.
    7  *
    8  */
    9 #include "config.h"
   10 #include <string.h>
   11 #include <stdio.h>
   12 #include <sys/stat.h>
   13 #include <errno.h>
   14 #ifdef HAVE_IFADDRS_H
   15 #include <ifaddrs.h>
   16 #endif
   17 #include "options.h"
   18 #include "query.h"
   19 #include "tsig.h"
   20 #include "difffile.h"
   21 #include "rrl.h"
   22 #include "bitset.h"
   23 
   24 #include "configparser.h"
   25 config_parser_state_type* cfg_parser = 0;
   26 extern FILE* c_in, *c_out;
   27 int c_parse(void);
   28 int c_lex(void);
   29 int c_wrap(void);
   30 int c_lex_destroy(void);
   31 extern char* c_text;
   32 
   33 static int
   34 rbtree_strcmp(const void* p1, const void* p2)
   35 {
   36     if(p1 == NULL && p2 == NULL) return 0;
   37     if(p1 == NULL) return -1;
   38     if(p2 == NULL) return 1;
   39     return strcmp((const char*)p1, (const char*)p2);
   40 }
   41 
   42 struct nsd_options*
   43 nsd_options_create(region_type* region)
   44 {
   45     struct nsd_options* opt;
   46     opt = (struct nsd_options*)region_alloc(region, sizeof(
   47         struct nsd_options));
   48     opt->region = region;
   49     opt->zone_options = rbtree_create(region,
   50         (int (*)(const void *, const void *)) dname_compare);
   51     opt->configfile = NULL;
   52     opt->zonestatnames = rbtree_create(opt->region, rbtree_strcmp);
   53     opt->patterns = rbtree_create(region, rbtree_strcmp);
   54     opt->keys = rbtree_create(region, rbtree_strcmp);
   55     opt->ip_addresses = NULL;
   56     opt->ip_transparent = 0;
   57     opt->ip_freebind = 0;
   58     opt->send_buffer_size = 0;
   59     opt->receive_buffer_size = 0;
   60     opt->debug_mode = 0;
   61     opt->verbosity = 0;
   62     opt->hide_version = 0;
   63     opt->hide_identity = 0;
   64     opt->drop_updates = 0;
   65     opt->do_ip4 = 1;
   66     opt->do_ip6 = 1;
   67     opt->database = DBFILE;
   68     opt->identity = 0;
   69     opt->version = 0;
   70     opt->nsid = 0;
   71     opt->logfile = 0;
   72     opt->log_only_syslog = 0;
   73     opt->log_time_ascii = 1;
   74     opt->round_robin = 0; /* also packet.h::round_robin */
   75     opt->minimal_responses = 0; /* also packet.h::minimal_responses */
   76     opt->confine_to_zone = 0;
   77     opt->refuse_any = 0;
   78     opt->server_count = 1;
   79     opt->cpu_affinity = NULL;
   80     opt->service_cpu_affinity = NULL;
   81     opt->tcp_count = 100;
   82     opt->tcp_reject_overflow = 0;
   83     opt->tcp_query_count = 0;
   84     opt->tcp_timeout = TCP_TIMEOUT;
   85     opt->tcp_mss = 0;
   86     opt->outgoing_tcp_mss = 0;
   87     opt->ipv4_edns_size = EDNS_MAX_MESSAGE_LEN;
   88     opt->ipv6_edns_size = EDNS_MAX_MESSAGE_LEN;
   89     opt->pidfile = PIDFILE;
   90     opt->port = UDP_PORT;
   91 /* deprecated?  opt->port = TCP_PORT; */
   92     opt->reuseport = 0;
   93     opt->statistics = 0;
   94     opt->chroot = 0;
   95     opt->username = USER;
   96     opt->zonesdir = ZONESDIR;
   97     opt->xfrdfile = XFRDFILE;
   98     opt->xfrdir = XFRDIR;
   99     opt->zonelistfile = ZONELISTFILE;
  100 #ifdef RATELIMIT
  101     opt->rrl_size = RRL_BUCKETS;
  102     opt->rrl_slip = RRL_SLIP;
  103     opt->rrl_ipv4_prefix_length = RRL_IPV4_PREFIX_LENGTH;
  104     opt->rrl_ipv6_prefix_length = RRL_IPV6_PREFIX_LENGTH;
  105 #  ifdef RATELIMIT_DEFAULT_OFF
  106     opt->rrl_ratelimit = 0;
  107     opt->rrl_whitelist_ratelimit = 0;
  108 #  else
  109     opt->rrl_ratelimit = RRL_LIMIT/2;
  110     opt->rrl_whitelist_ratelimit = RRL_WLIST_LIMIT/2;
  111 #  endif
  112 #endif
  113 #ifdef USE_DNSTAP
  114     opt->dnstap_enable = 0;
  115     opt->dnstap_socket_path = DNSTAP_SOCKET_PATH;
  116     opt->dnstap_send_identity = 0;
  117     opt->dnstap_send_version = 0;
  118     opt->dnstap_identity = NULL;
  119     opt->dnstap_version = NULL;
  120     opt->dnstap_log_auth_query_messages = 0;
  121     opt->dnstap_log_auth_response_messages = 0;
  122 #endif
  123     opt->zonefiles_check = 1;
  124     if(opt->database == NULL || opt->database[0] == 0)
  125         opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL;
  126     else    opt->zonefiles_write = 0;
  127     opt->xfrd_reload_timeout = 1;
  128     opt->tls_service_key = NULL;
  129     opt->tls_service_ocsp = NULL;
  130     opt->tls_service_pem = NULL;
  131     opt->tls_port = TLS_PORT;
  132     opt->control_enable = 0;
  133     opt->control_interface = NULL;
  134     opt->control_port = NSD_CONTROL_PORT;
  135     opt->server_key_file = CONFIGDIR"/nsd_server.key";
  136     opt->server_cert_file = CONFIGDIR"/nsd_server.pem";
  137     opt->control_key_file = CONFIGDIR"/nsd_control.key";
  138     opt->control_cert_file = CONFIGDIR"/nsd_control.pem";
  139     return opt;
  140 }
  141 
  142 int
  143 nsd_options_insert_zone(struct nsd_options* opt, struct zone_options* zone)
  144 {
  145     /* create dname for lookup */
  146     const dname_type* dname = dname_parse(opt->region, zone->name);
  147     if(!dname)
  148         return 0;
  149     zone->node.key = dname;
  150     if(!rbtree_insert(opt->zone_options, (rbnode_type*)zone))
  151         return 0;
  152     return 1;
  153 }
  154 
  155 int
  156 nsd_options_insert_pattern(struct nsd_options* opt,
  157     struct pattern_options* pat)
  158 {
  159     if(!pat->pname)
  160         return 0;
  161     pat->node.key = pat->pname;
  162     if(!rbtree_insert(opt->patterns, (rbnode_type*)pat))
  163         return 0;
  164     return 1;
  165 }
  166 
  167 void
  168 warn_if_directory(const char* filetype, FILE* f, const char* fname)
  169 {
  170     if(fileno(f) != -1) {
  171         struct stat st;
  172         memset(&st, 0, sizeof(st));
  173         if(fstat(fileno(f), &st) != -1) {
  174             if(S_ISDIR(st.st_mode)) {
  175                 log_msg(LOG_WARNING, "trying to read %s but it is a directory: %s", filetype, fname);
  176             }
  177         }
  178     }
  179 }
  180 
  181 int
  182 parse_options_file(struct nsd_options* opt, const char* file,
  183     void (*err)(void*,const char*), void* err_arg)
  184 {
  185     FILE *in = 0;
  186     struct pattern_options* pat;
  187     struct acl_options* acl;
  188 
  189     if(!cfg_parser) {
  190         cfg_parser = (config_parser_state_type*)region_alloc(
  191             opt->region, sizeof(config_parser_state_type));
  192         cfg_parser->chroot = 0;
  193     }
  194     cfg_parser->err = err;
  195     cfg_parser->err_arg = err_arg;
  196     cfg_parser->filename = (char*)file;
  197     cfg_parser->line = 1;
  198     cfg_parser->errors = 0;
  199     cfg_parser->opt = opt;
  200     cfg_parser->pattern = NULL;
  201     cfg_parser->zone = NULL;
  202     cfg_parser->key = NULL;
  203 
  204     in = fopen(cfg_parser->filename, "r");
  205     if(!in) {
  206         if(err) {
  207             char m[MAXSYSLOGMSGLEN];
  208             snprintf(m, sizeof(m), "Could not open %s: %s\n",
  209                 file, strerror(errno));
  210             err(err_arg, m);
  211         } else {
  212             fprintf(stderr, "Could not open %s: %s\n",
  213                 file, strerror(errno));
  214         }
  215         return 0;
  216     }
  217     warn_if_directory("configfile", in, file);
  218     c_in = in;
  219     c_parse();
  220     fclose(in);
  221 
  222     opt->configfile = region_strdup(opt->region, file);
  223 
  224     RBTREE_FOR(pat, struct pattern_options*, opt->patterns)
  225     {
  226         /* lookup keys for acls */
  227         for(acl=pat->allow_notify; acl; acl=acl->next)
  228         {
  229             if(acl->nokey || acl->blocked)
  230                 continue;
  231             acl->key_options = key_options_find(opt, acl->key_name);
  232             if(!acl->key_options)
  233                 c_error("key %s in pattern %s could not be found",
  234                     acl->key_name, pat->pname);
  235         }
  236         for(acl=pat->notify; acl; acl=acl->next)
  237         {
  238             if(acl->nokey || acl->blocked)
  239                 continue;
  240             acl->key_options = key_options_find(opt, acl->key_name);
  241             if(!acl->key_options)
  242                 c_error("key %s in pattern %s could not be found",
  243                     acl->key_name, pat->pname);
  244         }
  245         for(acl=pat->request_xfr; acl; acl=acl->next)
  246         {
  247             if(acl->nokey || acl->blocked)
  248                 continue;
  249             acl->key_options = key_options_find(opt, acl->key_name);
  250             if(!acl->key_options)
  251                 c_error("key %s in pattern %s could not be found",
  252                     acl->key_name, pat->pname);
  253         }
  254         for(acl=pat->provide_xfr; acl; acl=acl->next)
  255         {
  256             if(acl->nokey || acl->blocked)
  257                 continue;
  258             acl->key_options = key_options_find(opt, acl->key_name);
  259             if(!acl->key_options)
  260                 c_error("key %s in pattern %s could not be found",
  261                     acl->key_name, pat->pname);
  262         }
  263         for(acl=pat->allow_query; acl; acl=acl->next)
  264         {
  265             if(acl->nokey || acl->blocked)
  266                 continue;
  267             acl->key_options = key_options_find(opt, acl->key_name);
  268             if(!acl->key_options)
  269                 c_error("key %s in pattern %s could not be found",
  270                     acl->key_name, pat->pname);
  271         }
  272     }
  273 
  274     if(cfg_parser->errors > 0)
  275     {
  276         if(err) {
  277             char m[MAXSYSLOGMSGLEN];
  278             snprintf(m, sizeof(m), "read %s failed: %d errors in "
  279                 "configuration file\n", file,
  280                 cfg_parser->errors);
  281             err(err_arg, m);
  282         } else {
  283             fprintf(stderr, "read %s failed: %d errors in "
  284                 "configuration file\n", file,
  285                 cfg_parser->errors);
  286         }
  287         return 0;
  288     }
  289     return 1;
  290 }
  291 
  292 void options_zonestatnames_create(struct nsd_options* opt)
  293 {
  294     struct zone_options* zopt;
  295     /* allocate "" as zonestat 0, for zones without a zonestat */
  296     if(!rbtree_search(opt->zonestatnames, "")) {
  297         struct zonestatname* n;
  298         n = (struct zonestatname*)region_alloc_zero(opt->region,
  299             sizeof(*n));
  300         n->node.key = region_strdup(opt->region, "");
  301         if(!n->node.key) {
  302             log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
  303             exit(1);
  304         }
  305         n->id = (unsigned)(opt->zonestatnames->count);
  306         rbtree_insert(opt->zonestatnames, (rbnode_type*)n);
  307     }
  308     RBTREE_FOR(zopt, struct zone_options*, opt->zone_options) {
  309         /* insert into tree, so that when read in later id exists */
  310         (void)getzonestatid(opt, zopt);
  311     }
  312 }
  313 
  314 #define ZONELIST_HEADER "# NSD zone list\n# name pattern\n"
  315 static int
  316 comp_zonebucket(const void* a, const void* b)
  317 {
  318     /* the line size is much smaller than max-int, and positive,
  319      * so the subtraction works */
  320     return *(const int*)b - *(const int*)a;
  321 }
  322 
  323 /* insert free entry into zonelist free buckets */
  324 static void
  325 zone_list_free_insert(struct nsd_options* opt, int linesize, off_t off)
  326 {
  327     struct zonelist_free* e;
  328     struct zonelist_bucket* b = (struct zonelist_bucket*)rbtree_search(
  329         opt->zonefree, &linesize);
  330     if(!b) {
  331         b = region_alloc_zero(opt->region, sizeof(*b));
  332         b->linesize = linesize;
  333         b->node = *RBTREE_NULL;
  334         b->node.key = &b->linesize;
  335         rbtree_insert(opt->zonefree, &b->node);
  336     }
  337     e = (struct zonelist_free*)region_alloc_zero(opt->region, sizeof(*e));
  338     e->next = b->list;
  339     b->list = e;
  340     e->off = off;
  341     opt->zonefree_number++;
  342 }
  343 
  344 struct zone_options*
  345 zone_list_zone_insert(struct nsd_options* opt, const char* nm,
  346     const char* patnm, int linesize, off_t off)
  347 {
  348     struct pattern_options* pat = pattern_options_find(opt, patnm);
  349     struct zone_options* zone;
  350     if(!pat) {
  351         log_msg(LOG_ERR, "pattern does not exist for zone %s "
  352             "pattern %s", nm, patnm);
  353         return NULL;
  354     }
  355     zone = zone_options_create(opt->region);
  356     zone->part_of_config = 0;
  357     zone->name = region_strdup(opt->region, nm);
  358     zone->linesize = linesize;
  359     zone->off = off;
  360     zone->pattern = pat;
  361     if(!nsd_options_insert_zone(opt, zone)) {
  362         log_msg(LOG_ERR, "bad domain name or duplicate zone '%s' "
  363             "pattern %s", nm, patnm);
  364         region_recycle(opt->region, (void*)zone->name, strlen(nm)+1);
  365         region_recycle(opt->region, zone, sizeof(*zone));
  366         return NULL;
  367     }
  368     return zone;
  369 }
  370 
  371 int
  372 parse_zone_list_file(struct nsd_options* opt)
  373 {
  374     /* zonelist looks like this:
  375     # name pattern
  376     add example.com master
  377     del example.net slave
  378     add foo.bar.nl slave
  379     add rutabaga.uk config
  380     */
  381     char hdr[64];
  382     char buf[1024];
  383     
  384     /* create empty data structures */
  385     opt->zonefree = rbtree_create(opt->region, comp_zonebucket);
  386     opt->zonelist = NULL;
  387     opt->zonefree_number = 0;
  388     opt->zonelist_off = 0;
  389 
  390     /* try to open the zonelist file, an empty or nonexist file is OK */
  391     opt->zonelist = fopen(opt->zonelistfile, "r+");
  392     if(!opt->zonelist) {
  393         if(errno == ENOENT)
  394             return 1; /* file does not exist, it is created later */
  395         log_msg(LOG_ERR, "could not open zone list %s: %s", opt->zonelistfile,
  396             strerror(errno));
  397         return 0;
  398     }
  399     /* read header */
  400     hdr[strlen(ZONELIST_HEADER)] = 0;
  401     if(fread(hdr, 1, strlen(ZONELIST_HEADER), opt->zonelist) !=
  402         strlen(ZONELIST_HEADER) || strncmp(hdr, ZONELIST_HEADER,
  403         strlen(ZONELIST_HEADER)) != 0) {
  404         log_msg(LOG_ERR, "zone list %s contains bad header\n", opt->zonelistfile);
  405         fclose(opt->zonelist);
  406         opt->zonelist = NULL;
  407         return 0;
  408     }
  409     buf[sizeof(buf)-1]=0;
  410 
  411     /* read entries in file */
  412     while(fgets(buf, sizeof(buf), opt->zonelist)) {
  413         /* skip comments and empty lines */
  414         if(buf[0] == 0 || buf[0] == '\n' || buf[0] == '#')
  415             continue;
  416         if(strncmp(buf, "add ", 4) == 0) {
  417             int linesize = strlen(buf);
  418             /* parse the 'add' line */
  419             /* pick last space on the line, so that the domain
  420              * name can have a space in it (but not the pattern)*/
  421             char* space = strrchr(buf+4, ' ');
  422             char* nm, *patnm;
  423             if(!space) {
  424                 /* parse error */
  425                 log_msg(LOG_ERR, "parse error in %s: '%s'",
  426                     opt->zonelistfile, buf);
  427                 continue;
  428             }
  429             nm = buf+4;
  430             *space = 0;
  431             patnm = space+1;
  432             if(linesize && buf[linesize-1] == '\n')
  433                 buf[linesize-1] = 0;
  434 
  435             /* store offset and line size for zone entry */
  436             /* and create zone entry in zonetree */
  437             (void)zone_list_zone_insert(opt, nm, patnm, linesize,
  438                 ftello(opt->zonelist)-linesize);
  439         } else if(strncmp(buf, "del ", 4) == 0) {
  440             /* store offset and line size for deleted entry */
  441             int linesize = strlen(buf);
  442             zone_list_free_insert(opt, linesize,
  443                 ftello(opt->zonelist)-linesize);
  444         } else {
  445             log_msg(LOG_WARNING, "bad data in %s, '%s'", opt->zonelistfile,
  446                 buf);
  447         }
  448     }
  449     /* store EOF offset */
  450     opt->zonelist_off = ftello(opt->zonelist);
  451     return 1;
  452 }
  453 
  454 void
  455 zone_options_delete(struct nsd_options* opt, struct zone_options* zone)
  456 {
  457     rbtree_delete(opt->zone_options, zone->node.key);
  458     region_recycle(opt->region, (void*)zone->node.key, dname_total_size(
  459         (dname_type*)zone->node.key));
  460     region_recycle(opt->region, zone, sizeof(*zone));
  461 }
  462 
  463 /* add a new zone to the zonelist */
  464 struct zone_options*
  465 zone_list_add(struct nsd_options* opt, const char* zname, const char* pname)
  466 {
  467     int r;
  468     struct zonelist_free* e;
  469     struct zonelist_bucket* b;
  470     int linesize = 6 + strlen(zname) + strlen(pname);
  471     /* create zone entry */
  472     struct zone_options* zone = zone_list_zone_insert(opt, zname, pname,
  473         linesize, 0);
  474     if(!zone)
  475         return NULL;
  476 
  477     /* use free entry or append to file or create new file */
  478     if(!opt->zonelist || opt->zonelist_off == 0) {
  479         /* create new file */
  480         if(opt->zonelist) fclose(opt->zonelist);
  481         opt->zonelist = fopen(opt->zonelistfile, "w+");
  482         if(!opt->zonelist) {
  483             log_msg(LOG_ERR, "could not create zone list %s: %s",
  484                 opt->zonelistfile, strerror(errno));
  485             log_msg(LOG_ERR, "zone %s could not be added", zname);
  486             zone_options_delete(opt, zone);
  487             return NULL;
  488         }
  489         r = fprintf(opt->zonelist, ZONELIST_HEADER);
  490         if(r != strlen(ZONELIST_HEADER)) {
  491             if(r == -1)
  492                 log_msg(LOG_ERR, "could not write to %s: %s",
  493                     opt->zonelistfile, strerror(errno));
  494             else log_msg(LOG_ERR, "partial write to %s: disk full",
  495                 opt->zonelistfile);
  496             log_msg(LOG_ERR, "zone %s could not be added", zname);
  497             zone_options_delete(opt, zone);
  498             return NULL;
  499         }
  500         zone->off = ftello(opt->zonelist);
  501         if(zone->off == -1)
  502             log_msg(LOG_ERR, "ftello(%s): %s", opt->zonelistfile, strerror(errno));
  503         r = fprintf(opt->zonelist, "add %s %s\n", zname, pname);
  504         if(r != zone->linesize) {
  505             if(r == -1)
  506                 log_msg(LOG_ERR, "could not write to %s: %s",
  507                     opt->zonelistfile, strerror(errno));
  508             else log_msg(LOG_ERR, "partial write to %s: disk full",
  509                 opt->zonelistfile);
  510             log_msg(LOG_ERR, "zone %s could not be added", zname);
  511             zone_options_delete(opt, zone);
  512             return NULL;
  513         }
  514         opt->zonelist_off = ftello(opt->zonelist);
  515         if(opt->zonelist_off == -1)
  516             log_msg(LOG_ERR, "ftello(%s): %s", opt->zonelistfile, strerror(errno));
  517         if(fflush(opt->zonelist) != 0) {
  518             log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
  519         }
  520         return zone;
  521     }
  522     b = (struct zonelist_bucket*)rbtree_search(opt->zonefree,
  523         &zone->linesize);
  524     if(!b || b->list == NULL) {
  525         /* no empty place, append to file */
  526         zone->off = opt->zonelist_off;
  527         if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) {
  528             log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno));
  529             log_msg(LOG_ERR, "zone %s could not be added", zname);
  530             zone_options_delete(opt, zone);
  531             return NULL;
  532         }
  533         r = fprintf(opt->zonelist, "add %s %s\n", zname, pname);
  534         if(r != zone->linesize) {
  535             if(r == -1)
  536                 log_msg(LOG_ERR, "could not write to %s: %s",
  537                     opt->zonelistfile, strerror(errno));
  538             else log_msg(LOG_ERR, "partial write to %s: disk full",
  539                 opt->zonelistfile);
  540             log_msg(LOG_ERR, "zone %s could not be added", zname);
  541             zone_options_delete(opt, zone);
  542             return NULL;
  543         }
  544         opt->zonelist_off += linesize;
  545         if(fflush(opt->zonelist) != 0) {
  546             log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
  547         }
  548         return zone;
  549     }
  550     /* reuse empty spot */
  551     e = b->list;
  552     zone->off = e->off;
  553     if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) {
  554         log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno));
  555         log_msg(LOG_ERR, "zone %s could not be added", zname);
  556         zone_options_delete(opt, zone);
  557         return NULL;
  558     }
  559     r = fprintf(opt->zonelist, "add %s %s\n", zname, pname);
  560     if(r != zone->linesize) {
  561         if(r == -1)
  562             log_msg(LOG_ERR, "could not write to %s: %s",
  563                 opt->zonelistfile, strerror(errno));
  564         else log_msg(LOG_ERR, "partial write to %s: disk full",
  565             opt->zonelistfile);
  566         log_msg(LOG_ERR, "zone %s could not be added", zname);
  567         zone_options_delete(opt, zone);
  568         return NULL;
  569     }
  570     if(fflush(opt->zonelist) != 0) {
  571         log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
  572     }
  573 
  574     /* snip off and recycle element */
  575     b->list = e->next;
  576     region_recycle(opt->region, e, sizeof(*e));
  577     if(b->list == NULL) {
  578         rbtree_delete(opt->zonefree, &b->linesize);
  579         region_recycle(opt->region, b, sizeof(*b));
  580     }
  581     opt->zonefree_number--;
  582     return zone;
  583 }
  584 
  585 /* remove a zone on the zonelist */
  586 void
  587 zone_list_del(struct nsd_options* opt, struct zone_options* zone)
  588 {
  589     /* put its space onto the free entry */
  590     if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) {
  591         log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno));
  592         return;
  593     }
  594     fprintf(opt->zonelist, "del");
  595     zone_list_free_insert(opt, zone->linesize, zone->off);
  596 
  597     /* remove zone_options */
  598     zone_options_delete(opt, zone);
  599 
  600     /* see if we need to compact: it is going to halve the zonelist */
  601     if(opt->zonefree_number > opt->zone_options->count) {
  602         zone_list_compact(opt);
  603     } else {
  604         if(fflush(opt->zonelist) != 0) {
  605             log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
  606         }
  607     }
  608 }
  609 /* postorder delete of zonelist free space tree */
  610 static void
  611 delbucket(region_type* region, struct zonelist_bucket* b)
  612 {
  613     struct zonelist_free* e, *f;
  614     if(!b || (rbnode_type*)b==RBTREE_NULL)
  615         return;
  616     delbucket(region, (struct zonelist_bucket*)b->node.left);
  617     delbucket(region, (struct zonelist_bucket*)b->node.right);
  618     e = b->list;
  619     while(e) {
  620         f = e->next;
  621         region_recycle(region, e, sizeof(*e));
  622         e = f;
  623     }
  624     region_recycle(region, b, sizeof(*b));
  625 }
  626 
  627 /* compact zonelist file */
  628 void
  629 zone_list_compact(struct nsd_options* opt)
  630 {
  631     char outname[1024];
  632     FILE* out;
  633     struct zone_options* zone;
  634     off_t off;
  635     int r;
  636     snprintf(outname, sizeof(outname), "%s~", opt->zonelistfile);
  637     /* useful, when : count-of-free > count-of-used */
  638     /* write zonelist to zonelist~ */
  639     out = fopen(outname, "w+");
  640     if(!out) {
  641         log_msg(LOG_ERR, "could not open %s: %s", outname, strerror(errno));
  642         return;
  643     }
  644     r = fprintf(out, ZONELIST_HEADER);
  645     if(r == -1) {
  646         log_msg(LOG_ERR, "write %s failed: %s", outname,
  647             strerror(errno));
  648         fclose(out);
  649         return;
  650     } else if(r != strlen(ZONELIST_HEADER)) {
  651         log_msg(LOG_ERR, "write %s was partial: disk full",
  652             outname);
  653         fclose(out);
  654         return;
  655     }
  656     off = ftello(out);
  657     if(off == -1) {
  658         log_msg(LOG_ERR, "ftello(%s): %s", outname, strerror(errno));
  659         fclose(out);
  660         return;
  661     }
  662     RBTREE_FOR(zone, struct zone_options*, opt->zone_options) {
  663         if(zone->part_of_config)
  664             continue;
  665         r = fprintf(out, "add %s %s\n", zone->name,
  666             zone->pattern->pname);
  667         if(r < 0) {
  668             log_msg(LOG_ERR, "write %s failed: %s", outname,
  669                 strerror(errno));
  670             fclose(out);
  671             return;
  672         } else if(r != zone->linesize) {
  673             log_msg(LOG_ERR, "write %s was partial: disk full",
  674                 outname);
  675             fclose(out);
  676             return;
  677         }
  678     }
  679     if(fflush(out) != 0) {
  680         log_msg(LOG_ERR, "fflush %s: %s", outname, strerror(errno));
  681     }
  682 
  683     /* rename zonelist~ onto zonelist */
  684     if(rename(outname, opt->zonelistfile) == -1) {
  685         log_msg(LOG_ERR, "rename(%s to %s) failed: %s",
  686             outname, opt->zonelistfile, strerror(errno));
  687         fclose(out);
  688         return;
  689     }
  690     fclose(opt->zonelist);
  691     /* set offsets */
  692     RBTREE_FOR(zone, struct zone_options*, opt->zone_options) {
  693         if(zone->part_of_config)
  694             continue;
  695         zone->off = off;
  696         off += zone->linesize;
  697     }
  698     /* empty the free tree */
  699     delbucket(opt->region, (struct zonelist_bucket*)opt->zonefree->root);
  700     opt->zonefree->root = RBTREE_NULL;
  701     opt->zonefree->count = 0;
  702     opt->zonefree_number = 0;
  703     /* finish */
  704     opt->zonelist = out;
  705     opt->zonelist_off = off;
  706 }
  707 
  708 /* close zonelist file */
  709 void
  710 zone_list_close(struct nsd_options* opt)
  711 {
  712     if(opt->zonelist) {
  713         fclose(opt->zonelist);
  714         opt->zonelist = NULL;
  715     }
  716 }
  717 
  718 static void
  719 c_error_va_list_pos(int showpos, const char* fmt, va_list args)
  720 {
  721     char* at = NULL;
  722     cfg_parser->errors++;
  723     if(showpos && c_text && c_text[0]!=0) {
  724         at = c_text;
  725     }
  726     if(cfg_parser->err) {
  727         char m[MAXSYSLOGMSGLEN];
  728         snprintf(m, sizeof(m), "%s:%d: ", cfg_parser->filename,
  729             cfg_parser->line);
  730         (*cfg_parser->err)(cfg_parser->err_arg, m);
  731         if(at) {
  732             snprintf(m, sizeof(m), "at '%s': ", at);
  733             (*cfg_parser->err)(cfg_parser->err_arg, m);
  734         }
  735         (*cfg_parser->err)(cfg_parser->err_arg, "error: ");
  736         vsnprintf(m, sizeof(m), fmt, args);
  737         (*cfg_parser->err)(cfg_parser->err_arg, m);
  738         (*cfg_parser->err)(cfg_parser->err_arg, "\n");
  739         return;
  740     }
  741         fprintf(stderr, "%s:%d: ", cfg_parser->filename, cfg_parser->line);
  742     if(at) fprintf(stderr, "at '%s': ", at);
  743     fprintf(stderr, "error: ");
  744     vfprintf(stderr, fmt, args);
  745     fprintf(stderr, "\n");
  746 }
  747 
  748 void
  749 c_error(const char *fmt, ...)
  750 {
  751     va_list ap;
  752     int showpos = 0;
  753 
  754     if (strcmp(fmt, "syntax error") == 0 || strcmp(fmt, "parse error") == 0) {
  755         showpos = 1;
  756     }
  757 
  758     va_start(ap, fmt);
  759     c_error_va_list_pos(showpos, fmt, ap);
  760     va_end(ap);
  761 }
  762 
  763 int
  764 c_wrap(void)
  765 {
  766     return 1;
  767 }
  768 
  769 struct zone_options*
  770 zone_options_create(region_type* region)
  771 {
  772     struct zone_options* zone;
  773     zone = (struct zone_options*)region_alloc(region, sizeof(
  774         struct zone_options));
  775     zone->node = *RBTREE_NULL;
  776     zone->name = 0;
  777     zone->pattern = 0;
  778     zone->part_of_config = 0;
  779     return zone;
  780 }
  781 
  782 /* true is booleans are the same truth value */
  783 #define booleq(x,y) ( ((x) && (y)) || (!(x) && !(y)) )
  784 
  785 /* true is min_expire_time_expr has either an equal known value
  786  * or none of these known values but booleanally equal
  787  */
  788 #define expire_expr_eq(x,y) (  (  (x) == REFRESHPLUSRETRYPLUS1 \
  789                                && (y) == REFRESHPLUSRETRYPLUS1 ) \
  790                             || (  (x) != REFRESHPLUSRETRYPLUS1 \
  791                                && (y) != REFRESHPLUSRETRYPLUS1 \
  792                                && booleq((x), (y))))
  793 
  794 
  795 int
  796 acl_equal(struct acl_options* p, struct acl_options* q)
  797 {
  798     if(!booleq(p->use_axfr_only, q->use_axfr_only)) return 0;
  799     if(!booleq(p->allow_udp, q->allow_udp)) return 0;
  800     if(strcmp(p->ip_address_spec, q->ip_address_spec)!=0) return 0;
  801     /* the ip6, port, addr, mask, type: are derived from the ip_address_spec */
  802     if(!booleq(p->nokey, q->nokey)) return 0;
  803     if(!booleq(p->blocked, q->blocked)) return 0;
  804     if(p->key_name && q->key_name) {
  805         if(strcmp(p->key_name, q->key_name)!=0) return 0;
  806     } else if(p->key_name && !q->key_name) return 0;
  807     else if(!p->key_name && q->key_name) return 0;
  808     /* key_options is derived from key_name */
  809     return 1;
  810 }
  811 
  812 int
  813 acl_list_equal(struct acl_options* p, struct acl_options* q)
  814 {
  815     /* must be same and in same order */
  816     while(p && q) {
  817         if(!acl_equal(p, q))
  818             return 0;
  819         p = p->next;
  820         q = q->next;
  821     }
  822     if(!p && !q) return 1;
  823     /* different lengths */
  824     return 0;
  825 }
  826 
  827 struct pattern_options*
  828 pattern_options_create(region_type* region)
  829 {
  830     struct pattern_options* p;
  831     p = (struct pattern_options*)region_alloc(region, sizeof(
  832         struct pattern_options));
  833     p->node = *RBTREE_NULL;
  834     p->pname = 0;
  835     p->zonefile = 0;
  836     p->zonestats = 0;
  837     p->allow_notify = 0;
  838     p->request_xfr = 0;
  839     p->size_limit_xfr = 0;
  840     p->notify = 0;
  841     p->provide_xfr = 0;
  842     p->allow_query = 0;
  843     p->outgoing_interface = 0;
  844     p->notify_retry = 5;
  845     p->notify_retry_is_default = 1;
  846     p->allow_axfr_fallback = 1;
  847     p->allow_axfr_fallback_is_default = 1;
  848     p->implicit = 0;
  849     p->xfrd_flags = 0;
  850     p->max_refresh_time = 2419200;  /* 4 weeks */
  851     p->max_refresh_time_is_default = 1;
  852     p->min_refresh_time = 0;
  853     p->min_refresh_time_is_default = 1;
  854     p->max_retry_time = 1209600;    /* 2 weeks */
  855     p->max_retry_time_is_default = 1;
  856     p->min_retry_time = 0;
  857     p->min_retry_time_is_default = 1;
  858     p->min_expire_time = 0;
  859     p->min_expire_time_expr = EXPIRE_TIME_IS_DEFAULT;
  860 #ifdef RATELIMIT
  861     p->rrl_whitelist = 0;
  862 #endif
  863     p->multi_master_check = 0;
  864     return p;
  865 }
  866 
  867 static void
  868 acl_delete(region_type* region, struct acl_options* acl)
  869 {
  870     if(acl->ip_address_spec)
  871         region_recycle(region, (void*)acl->ip_address_spec,
  872             strlen(acl->ip_address_spec)+1);
  873     if(acl->key_name)
  874         region_recycle(region, (void*)acl->key_name,
  875             strlen(acl->key_name)+1);
  876     /* key_options is a convenience pointer, not owned by the acl */
  877     region_recycle(region, acl, sizeof(*acl));
  878 }
  879 
  880 static void
  881 acl_list_delete(region_type* region, struct acl_options* list)
  882 {
  883     struct acl_options* n;
  884     while(list) {
  885         n = list->next;
  886         acl_delete(region, list);
  887         list = n;
  888     }
  889 }
  890 
  891 void
  892 pattern_options_remove(struct nsd_options* opt, const char* name)
  893 {
  894     struct pattern_options* p = (struct pattern_options*)rbtree_delete(
  895         opt->patterns, name);
  896     /* delete p and its contents */
  897     if (!p)
  898         return;
  899     if(p->pname)
  900         region_recycle(opt->region, (void*)p->pname,
  901             strlen(p->pname)+1);
  902     if(p->zonefile)
  903         region_recycle(opt->region, (void*)p->zonefile,
  904             strlen(p->zonefile)+1);
  905     if(p->zonestats)
  906         region_recycle(opt->region, (void*)p->zonestats,
  907             strlen(p->zonestats)+1);
  908     acl_list_delete(opt->region, p->allow_notify);
  909     acl_list_delete(opt->region, p->request_xfr);
  910     acl_list_delete(opt->region, p->notify);
  911     acl_list_delete(opt->region, p->provide_xfr);
  912     acl_list_delete(opt->region, p->allow_query);
  913     acl_list_delete(opt->region, p->outgoing_interface);
  914 
  915     region_recycle(opt->region, p, sizeof(struct pattern_options));
  916 }
  917 
  918 static struct acl_options*
  919 copy_acl(region_type* region, struct acl_options* a)
  920 {
  921     struct acl_options* b;
  922     if(!a) return NULL;
  923     b = (struct acl_options*)region_alloc(region, sizeof(*b));
  924     /* copy the whole lot */
  925     *b = *a;
  926     /* fix the pointers */
  927     if(a->ip_address_spec)
  928         b->ip_address_spec = region_strdup(region, a->ip_address_spec);
  929     if(a->key_name)
  930         b->key_name = region_strdup(region, a->key_name);
  931     b->next = NULL;
  932     b->key_options = NULL;
  933     return b;
  934 }
  935 
  936 static struct acl_options*
  937 copy_acl_list(struct nsd_options* opt, struct acl_options* a)
  938 {
  939     struct acl_options* b, *blast = NULL, *blist = NULL;
  940     while(a) {
  941         b = copy_acl(opt->region, a);
  942         /* fixup key_options */
  943         if(b->key_name)
  944             b->key_options = key_options_find(opt, b->key_name);
  945         else    b->key_options = NULL;
  946 
  947         /* link as last into list */
  948         b->next = NULL;
  949         if(!blist) blist = b;
  950         else blast->next = b;
  951         blast = b;
  952         
  953         a = a->next;
  954     }
  955     return blist;
  956 }
  957 
  958 static void
  959 copy_changed_acl(struct nsd_options* opt, struct acl_options** orig,
  960     struct acl_options* anew)
  961 {
  962     if(!acl_list_equal(*orig, anew)) {
  963         acl_list_delete(opt->region, *orig);
  964         *orig = copy_acl_list(opt, anew);
  965     }
  966 }
  967 
  968 static void
  969 copy_pat_fixed(region_type* region, struct pattern_options* orig,
  970     struct pattern_options* p)
  971 {
  972     orig->allow_axfr_fallback = p->allow_axfr_fallback;
  973     orig->allow_axfr_fallback_is_default =
  974         p->allow_axfr_fallback_is_default;
  975     orig->notify_retry = p->notify_retry;
  976     orig->notify_retry_is_default = p->notify_retry_is_default;
  977     orig->implicit = p->implicit;
  978     if(p->zonefile)
  979         orig->zonefile = region_strdup(region, p->zonefile);
  980     else orig->zonefile = NULL;
  981     if(p->zonestats)
  982         orig->zonestats = region_strdup(region, p->zonestats);
  983     else orig->zonestats = NULL;
  984     orig->max_refresh_time = p->max_refresh_time;
  985     orig->max_refresh_time_is_default = p->max_refresh_time_is_default;
  986     orig->min_refresh_time = p->min_refresh_time;
  987     orig->min_refresh_time_is_default = p->min_refresh_time_is_default;
  988     orig->max_retry_time = p->max_retry_time;
  989     orig->max_retry_time_is_default = p->max_retry_time_is_default;
  990     orig->min_retry_time = p->min_retry_time;
  991     orig->min_retry_time_is_default = p->min_retry_time_is_default;
  992     orig->min_expire_time = p->min_expire_time;
  993     orig->min_expire_time_expr = p->min_expire_time_expr;
  994 #ifdef RATELIMIT
  995     orig->rrl_whitelist = p->rrl_whitelist;
  996 #endif
  997     orig->multi_master_check = p->multi_master_check;
  998 }
  999 
 1000 void
 1001 pattern_options_add_modify(struct nsd_options* opt, struct pattern_options* p)
 1002 {
 1003     struct pattern_options* orig = pattern_options_find(opt, p->pname);
 1004     if(!orig) {
 1005         /* needs to be copied to opt region */
 1006         orig = pattern_options_create(opt->region);
 1007         orig->pname = region_strdup(opt->region, p->pname);
 1008         copy_pat_fixed(opt->region, orig, p);
 1009         orig->allow_notify = copy_acl_list(opt, p->allow_notify);
 1010         orig->request_xfr = copy_acl_list(opt, p->request_xfr);
 1011         orig->notify = copy_acl_list(opt, p->notify);
 1012         orig->provide_xfr = copy_acl_list(opt, p->provide_xfr);
 1013         orig->allow_query = copy_acl_list(opt, p->allow_query);
 1014         orig->outgoing_interface = copy_acl_list(opt,
 1015             p->outgoing_interface);
 1016         nsd_options_insert_pattern(opt, orig);
 1017     } else {
 1018         /* modify in place so pointers stay valid (and copy
 1019            into region). Do not touch unchanged acls. */
 1020         if(orig->zonefile)
 1021             region_recycle(opt->region, (char*)orig->zonefile,
 1022                 strlen(orig->zonefile)+1);
 1023         if(orig->zonestats)
 1024             region_recycle(opt->region, (char*)orig->zonestats,
 1025                 strlen(orig->zonestats)+1);
 1026         copy_pat_fixed(opt->region, orig, p);
 1027         copy_changed_acl(opt, &orig->allow_notify, p->allow_notify);
 1028         copy_changed_acl(opt, &orig->request_xfr, p->request_xfr);
 1029         copy_changed_acl(opt, &orig->notify, p->notify);
 1030         copy_changed_acl(opt, &orig->provide_xfr, p->provide_xfr);
 1031         copy_changed_acl(opt, &orig->allow_query, p->allow_query);
 1032         copy_changed_acl(opt, &orig->outgoing_interface,
 1033             p->outgoing_interface);
 1034     }
 1035 }
 1036 
 1037 struct pattern_options*
 1038 pattern_options_find(struct nsd_options* opt, const char* name)
 1039 {
 1040     return (struct pattern_options*)rbtree_search(opt->patterns, name);
 1041 }
 1042 
 1043 int
 1044 pattern_options_equal(struct pattern_options* p, struct pattern_options* q)
 1045 {
 1046     if(strcmp(p->pname, q->pname) != 0) return 0;
 1047     if(!p->zonefile && q->zonefile) return 0;
 1048     else if(p->zonefile && !q->zonefile) return 0;
 1049     else if(p->zonefile && q->zonefile) {
 1050         if(strcmp(p->zonefile, q->zonefile) != 0) return 0;
 1051     }
 1052     if(!p->zonestats && q->zonestats) return 0;
 1053     else if(p->zonestats && !q->zonestats) return 0;
 1054     else if(p->zonestats && q->zonestats) {
 1055         if(strcmp(p->zonestats, q->zonestats) != 0) return 0;
 1056     }
 1057     if(!booleq(p->allow_axfr_fallback, q->allow_axfr_fallback)) return 0;
 1058     if(!booleq(p->allow_axfr_fallback_is_default,
 1059         q->allow_axfr_fallback_is_default)) return 0;
 1060     if(p->notify_retry != q->notify_retry) return 0;
 1061     if(!booleq(p->notify_retry_is_default,
 1062         q->notify_retry_is_default)) return 0;
 1063     if(!booleq(p->implicit, q->implicit)) return 0;
 1064     if(!acl_list_equal(p->allow_notify, q->allow_notify)) return 0;
 1065     if(!acl_list_equal(p->request_xfr, q->request_xfr)) return 0;
 1066     if(!acl_list_equal(p->notify, q->notify)) return 0;
 1067     if(!acl_list_equal(p->provide_xfr, q->provide_xfr)) return 0;
 1068     if(!acl_list_equal(p->allow_query, q->allow_query)) return 0;
 1069     if(!acl_list_equal(p->outgoing_interface, q->outgoing_interface))
 1070         return 0;
 1071     if(p->max_refresh_time != q->max_refresh_time) return 0;
 1072     if(!booleq(p->max_refresh_time_is_default,
 1073         q->max_refresh_time_is_default)) return 0;
 1074     if(p->min_refresh_time != q->min_refresh_time) return 0;
 1075     if(!booleq(p->min_refresh_time_is_default,
 1076         q->min_refresh_time_is_default)) return 0;
 1077     if(p->max_retry_time != q->max_retry_time) return 0;
 1078     if(!booleq(p->max_retry_time_is_default,
 1079         q->max_retry_time_is_default)) return 0;
 1080     if(p->min_retry_time != q->min_retry_time) return 0;
 1081     if(!booleq(p->min_retry_time_is_default,
 1082         q->min_retry_time_is_default)) return 0;
 1083     if(p->min_expire_time != q->min_expire_time) return 0;
 1084     if(!expire_expr_eq(p->min_expire_time_expr,
 1085         q->min_expire_time_expr)) return 0;
 1086 #ifdef RATELIMIT
 1087     if(p->rrl_whitelist != q->rrl_whitelist) return 0;
 1088 #endif
 1089     if(!booleq(p->multi_master_check,q->multi_master_check)) return 0;
 1090     if(p->size_limit_xfr != q->size_limit_xfr) return 0;
 1091     return 1;
 1092 }
 1093 
 1094 static void
 1095 marshal_u8(struct buffer* b, uint8_t v)
 1096 {
 1097     buffer_reserve(b, 1);
 1098     buffer_write_u8(b, v);
 1099 }
 1100 
 1101 static uint8_t
 1102 unmarshal_u8(struct buffer* b)
 1103 {
 1104     return buffer_read_u8(b);
 1105 }
 1106 
 1107 static void
 1108 marshal_u64(struct buffer* b, uint64_t v)
 1109 {
 1110     buffer_reserve(b, 8);
 1111     buffer_write_u64(b, v);
 1112 }
 1113 
 1114 static uint64_t
 1115 unmarshal_u64(struct buffer* b)
 1116 {
 1117     return buffer_read_u64(b);
 1118 }
 1119 
 1120 #ifdef RATELIMIT
 1121 static void
 1122 marshal_u16(struct buffer* b, uint16_t v)
 1123 {
 1124     buffer_reserve(b, 2);
 1125     buffer_write_u16(b, v);
 1126 }
 1127 #endif
 1128 
 1129 #ifdef RATELIMIT
 1130 static uint16_t
 1131 unmarshal_u16(struct buffer* b)
 1132 {
 1133     return buffer_read_u16(b);
 1134 }
 1135 #endif
 1136 
 1137 static void
 1138 marshal_u32(struct buffer* b, uint32_t v)
 1139 {
 1140     buffer_reserve(b, 4);
 1141     buffer_write_u32(b, v);
 1142 }
 1143 
 1144 static uint32_t
 1145 unmarshal_u32(struct buffer* b)
 1146 {
 1147     return buffer_read_u32(b);
 1148 }
 1149 
 1150 static void
 1151 marshal_str(struct buffer* b, const char* s)
 1152 {
 1153     if(!s) marshal_u8(b, 0);
 1154     else {
 1155         size_t len = strlen(s);
 1156         marshal_u8(b, 1);
 1157         buffer_reserve(b, len+1);
 1158         buffer_write(b, s, len+1);
 1159     }
 1160 }
 1161 
 1162 static char*
 1163 unmarshal_str(region_type* r, struct buffer* b)
 1164 {
 1165     uint8_t nonnull = unmarshal_u8(b);
 1166     if(nonnull) {
 1167         char* result = region_strdup(r, (char*)buffer_current(b));
 1168         size_t len = strlen((char*)buffer_current(b));
 1169         buffer_skip(b, len+1);
 1170         return result;
 1171     } else return NULL;
 1172 }
 1173 
 1174 static void
 1175 marshal_acl(struct buffer* b, struct acl_options* acl)
 1176 {
 1177     buffer_reserve(b, sizeof(*acl));
 1178     buffer_write(b, acl, sizeof(*acl));
 1179     marshal_str(b, acl->ip_address_spec);
 1180     marshal_str(b, acl->key_name);
 1181 }
 1182 
 1183 static struct acl_options*
 1184 unmarshal_acl(region_type* r, struct buffer* b)
 1185 {
 1186     struct acl_options* acl = (struct acl_options*)region_alloc(r,
 1187         sizeof(*acl));
 1188     buffer_read(b, acl, sizeof(*acl));
 1189     acl->next = NULL;
 1190     acl->key_options = NULL;
 1191     acl->ip_address_spec = unmarshal_str(r, b);
 1192     acl->key_name = unmarshal_str(r, b);
 1193     return acl;
 1194 }
 1195 
 1196 static void
 1197 marshal_acl_list(struct buffer* b, struct acl_options* list)
 1198 {
 1199     while(list) {
 1200         marshal_u8(b, 1); /* is there a next one marker */
 1201         marshal_acl(b, list);
 1202         list = list->next;
 1203     }
 1204     marshal_u8(b, 0); /* end of list marker */
 1205 }
 1206 
 1207 static struct acl_options*
 1208 unmarshal_acl_list(region_type* r, struct buffer* b)
 1209 {
 1210     struct acl_options* a, *last=NULL, *list=NULL;
 1211     while(unmarshal_u8(b)) {
 1212         a = unmarshal_acl(r, b);
 1213         /* link in */
 1214         a->next = NULL;
 1215         if(!list) list = a;
 1216         else last->next = a;
 1217         last = a;
 1218     }
 1219     return list;
 1220 }
 1221 
 1222 void
 1223 pattern_options_marshal(struct buffer* b, struct pattern_options* p)
 1224 {
 1225     marshal_str(b, p->pname);
 1226     marshal_str(b, p->zonefile);
 1227     marshal_str(b, p->zonestats);
 1228 #ifdef RATELIMIT
 1229     marshal_u16(b, p->rrl_whitelist);
 1230 #endif
 1231     marshal_u8(b, p->allow_axfr_fallback);
 1232     marshal_u8(b, p->allow_axfr_fallback_is_default);
 1233     marshal_u8(b, p->notify_retry);
 1234     marshal_u8(b, p->notify_retry_is_default);
 1235     marshal_u8(b, p->implicit);
 1236     marshal_u64(b, p->size_limit_xfr);
 1237     marshal_acl_list(b, p->allow_notify);
 1238     marshal_acl_list(b, p->request_xfr);
 1239     marshal_acl_list(b, p->notify);
 1240     marshal_acl_list(b, p->provide_xfr);
 1241     marshal_acl_list(b, p->allow_query);
 1242     marshal_acl_list(b, p->outgoing_interface);
 1243     marshal_u32(b, p->max_refresh_time);
 1244     marshal_u8(b, p->max_refresh_time_is_default);
 1245     marshal_u32(b, p->min_refresh_time);
 1246     marshal_u8(b, p->min_refresh_time_is_default);
 1247     marshal_u32(b, p->max_retry_time);
 1248     marshal_u8(b, p->max_retry_time_is_default);
 1249     marshal_u32(b, p->min_retry_time);
 1250     marshal_u8(b, p->min_retry_time_is_default);
 1251     marshal_u32(b, p->min_expire_time);
 1252     marshal_u8(b, p->min_expire_time_expr);
 1253     marshal_u8(b, p->multi_master_check);
 1254 }
 1255 
 1256 struct pattern_options*
 1257 pattern_options_unmarshal(region_type* r, struct buffer* b)
 1258 {
 1259     struct pattern_options* p = pattern_options_create(r);
 1260     p->pname = unmarshal_str(r, b);
 1261     p->zonefile = unmarshal_str(r, b);
 1262     p->zonestats = unmarshal_str(r, b);
 1263 #ifdef RATELIMIT
 1264     p->rrl_whitelist = unmarshal_u16(b);
 1265 #endif
 1266     p->allow_axfr_fallback = unmarshal_u8(b);
 1267     p->allow_axfr_fallback_is_default = unmarshal_u8(b);
 1268     p->notify_retry = unmarshal_u8(b);
 1269     p->notify_retry_is_default = unmarshal_u8(b);
 1270     p->implicit = unmarshal_u8(b);
 1271     p->size_limit_xfr = unmarshal_u64(b);
 1272     p->allow_notify = unmarshal_acl_list(r, b);
 1273     p->request_xfr = unmarshal_acl_list(r, b);
 1274     p->notify = unmarshal_acl_list(r, b);
 1275     p->provide_xfr = unmarshal_acl_list(r, b);
 1276     p->allow_query = unmarshal_acl_list(r, b);
 1277     p->outgoing_interface = unmarshal_acl_list(r, b);
 1278     p->max_refresh_time = unmarshal_u32(b);
 1279     p->max_refresh_time_is_default = unmarshal_u8(b);
 1280     p->min_refresh_time = unmarshal_u32(b);
 1281     p->min_refresh_time_is_default = unmarshal_u8(b);
 1282     p->max_retry_time = unmarshal_u32(b);
 1283     p->max_retry_time_is_default = unmarshal_u8(b);
 1284     p->min_retry_time = unmarshal_u32(b);
 1285     p->min_retry_time_is_default = unmarshal_u8(b);
 1286     p->min_expire_time = unmarshal_u32(b);
 1287     p->min_expire_time_expr = unmarshal_u8(b);
 1288     p->multi_master_check = unmarshal_u8(b);
 1289     return p;
 1290 }
 1291 
 1292 struct key_options*
 1293 key_options_create(region_type* region)
 1294 {
 1295     struct key_options* key;
 1296     key = (struct key_options*)region_alloc_zero(region,
 1297         sizeof(struct key_options));
 1298     return key;
 1299 }
 1300 
 1301 void
 1302 key_options_insert(struct nsd_options* opt, struct key_options* key)
 1303 {
 1304     if(!key->name) return;
 1305     key->node.key = key->name;
 1306     (void)rbtree_insert(opt->keys, &key->node);
 1307 }
 1308 
 1309 struct key_options*
 1310 key_options_find(struct nsd_options* opt, const char* name)
 1311 {
 1312     return (struct key_options*)rbtree_search(opt->keys, name);
 1313 }
 1314 
 1315 /** remove tsig_key contents */
 1316 void
 1317 key_options_desetup(region_type* region, struct key_options* key)
 1318 {
 1319     /* keep tsig_key pointer so that existing references keep valid */
 1320     if(!key->tsig_key)
 1321         return;
 1322     /* name stays the same */
 1323     if(key->tsig_key->data) {
 1324         /* wipe secret! */
 1325         memset(key->tsig_key->data, 0xdd, key->tsig_key->size);
 1326         region_recycle(region, key->tsig_key->data,
 1327             key->tsig_key->size);
 1328         key->tsig_key->data = NULL;
 1329         key->tsig_key->size = 0;
 1330     }
 1331 }
 1332 
 1333 /** add tsig_key contents */
 1334 void
 1335 key_options_setup(region_type* region, struct key_options* key)
 1336 {
 1337     uint8_t data[16384]; /* 16KB */
 1338     int size;
 1339     if(!key->tsig_key) {
 1340         /* create it */
 1341         key->tsig_key = (tsig_key_type *) region_alloc(region,
 1342             sizeof(tsig_key_type));
 1343         /* create name */
 1344         key->tsig_key->name = dname_parse(region, key->name);
 1345         if(!key->tsig_key->name) {
 1346             log_msg(LOG_ERR, "Failed to parse tsig key name %s",
 1347                 key->name);
 1348             /* key and base64 were checked during syntax parse */
 1349             exit(1);
 1350         }
 1351         key->tsig_key->size = 0;
 1352         key->tsig_key->data = NULL;
 1353     }
 1354     size = b64_pton(key->secret, data, sizeof(data));
 1355     if(size == -1) {
 1356         log_msg(LOG_ERR, "Failed to parse tsig key data %s",
 1357             key->name);
 1358         /* key and base64 were checked during syntax parse */
 1359         exit(1);
 1360     }
 1361     key->tsig_key->size = size;
 1362     key->tsig_key->data = (uint8_t *)region_alloc_init(region, data, size);
 1363 }
 1364 
 1365 void
 1366 key_options_remove(struct nsd_options* opt, const char* name)
 1367 {
 1368     struct key_options* k = key_options_find(opt, name);
 1369     if(!k) return;
 1370     (void)rbtree_delete(opt->keys, name);
 1371     if(k->name)
 1372         region_recycle(opt->region, k->name, strlen(k->name)+1);
 1373     if(k->algorithm)
 1374         region_recycle(opt->region, k->algorithm, strlen(k->algorithm)+1);
 1375     if(k->secret) {
 1376         memset(k->secret, 0xdd, strlen(k->secret)); /* wipe secret! */
 1377         region_recycle(opt->region, k->secret, strlen(k->secret)+1);
 1378     }
 1379     if(k->tsig_key) {
 1380         tsig_del_key(k->tsig_key);
 1381         if(k->tsig_key->name)
 1382             region_recycle(opt->region, (void*)k->tsig_key->name,
 1383                 dname_total_size(k->tsig_key->name));
 1384         key_options_desetup(opt->region, k);
 1385         region_recycle(opt->region, k->tsig_key, sizeof(tsig_key_type));
 1386     }
 1387     region_recycle(opt->region, k, sizeof(struct key_options));
 1388 }
 1389 
 1390 int
 1391 key_options_equal(struct key_options* p, struct key_options* q)
 1392 {
 1393     return strcmp(p->name, q->name)==0 && strcmp(p->algorithm,
 1394         q->algorithm)==0 && strcmp(p->secret, q->secret)==0;
 1395 }
 1396 
 1397 void
 1398 key_options_add_modify(struct nsd_options* opt, struct key_options* key)
 1399 {
 1400     struct key_options* orig = key_options_find(opt, key->name);
 1401     if(!orig) {
 1402         /* needs to be copied to opt region */
 1403         orig = key_options_create(opt->region);
 1404         orig->name = region_strdup(opt->region, key->name);
 1405         orig->algorithm = region_strdup(opt->region, key->algorithm);
 1406         orig->secret = region_strdup(opt->region, key->secret);
 1407         key_options_setup(opt->region, orig);
 1408         tsig_add_key(orig->tsig_key);
 1409         key_options_insert(opt, orig);
 1410     } else {
 1411         /* modify entries in existing key, and copy to opt region */
 1412         key_options_desetup(opt->region, orig);
 1413         region_recycle(opt->region, orig->algorithm,
 1414             strlen(orig->algorithm)+1);
 1415         orig->algorithm = region_strdup(opt->region, key->algorithm);
 1416         region_recycle(opt->region, orig->secret,
 1417             strlen(orig->secret)+1);
 1418         orig->secret = region_strdup(opt->region, key->secret);
 1419         key_options_setup(opt->region, orig);
 1420     }
 1421 }
 1422 
 1423 int
 1424 acl_check_incoming(struct acl_options* acl, struct query* q,
 1425     struct acl_options** reason)
 1426 {
 1427     /* check each acl element.
 1428        if 1 blocked element matches - return -1.
 1429        if any element matches - return number.
 1430        else return -1. */
 1431     int found_match = -1;
 1432     int number = 0;
 1433     struct acl_options* match = 0;
 1434 
 1435     if(reason)
 1436         *reason = NULL;
 1437 
 1438     while(acl)
 1439     {
 1440         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "testing acl %s %s",
 1441             acl->ip_address_spec, acl->nokey?"NOKEY":
 1442             (acl->blocked?"BLOCKED":acl->key_name)));
 1443         if(acl_addr_matches(acl, q) && acl_key_matches(acl, q)) {
 1444             if(!match)
 1445             {
 1446                 match = acl; /* remember first match */
 1447                 found_match=number;
 1448             }
 1449             if(acl->blocked) {
 1450                 if(reason)
 1451                     *reason = acl;
 1452                 return -1;
 1453             }
 1454         }
 1455         number++;
 1456         acl = acl->next;
 1457     }
 1458 
 1459     if(reason)
 1460         *reason = match;
 1461     return found_match;
 1462 }
 1463 
 1464 #ifdef INET6
 1465 int
 1466 acl_addr_matches_ipv6host(struct acl_options* acl, struct sockaddr_storage* addr_storage, unsigned int port)
 1467 {
 1468     struct sockaddr_in6* addr = (struct sockaddr_in6*)addr_storage;
 1469     if(acl->port != 0 && acl->port != port)
 1470         return 0;
 1471     switch(acl->rangetype) {
 1472     case acl_range_mask:
 1473     case acl_range_subnet:
 1474         if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
 1475             (uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
 1476             return 0;
 1477         break;
 1478     case acl_range_minmax:
 1479         if(!acl_addr_match_range_v6((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
 1480             (uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
 1481             return 0;
 1482         break;
 1483     case acl_range_single:
 1484     default:
 1485         if(memcmp(&addr->sin6_addr, &acl->addr.addr6,
 1486             sizeof(struct in6_addr)) != 0)
 1487             return 0;
 1488         break;
 1489     }
 1490     return 1;
 1491 }
 1492 #endif
 1493 
 1494 int
 1495 acl_addr_matches_ipv4host(struct acl_options* acl, struct sockaddr_in* addr, unsigned int port)
 1496 {
 1497     if(acl->port != 0 && acl->port != port)
 1498         return 0;
 1499     switch(acl->rangetype) {
 1500     case acl_range_mask:
 1501     case acl_range_subnet:
 1502         if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
 1503             (uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
 1504             return 0;
 1505         break;
 1506     case acl_range_minmax:
 1507         if(!acl_addr_match_range_v4((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
 1508             (uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
 1509             return 0;
 1510         break;
 1511     case acl_range_single:
 1512     default:
 1513         if(memcmp(&addr->sin_addr, &acl->addr.addr,
 1514             sizeof(struct in_addr)) != 0)
 1515             return 0;
 1516         break;
 1517     }
 1518     return 1;
 1519 }
 1520 
 1521 int
 1522 acl_addr_matches_host(struct acl_options* acl, struct acl_options* host)
 1523 {
 1524     if(acl->is_ipv6)
 1525     {
 1526 #ifdef INET6
 1527         struct sockaddr_storage* addr = (struct sockaddr_storage*)&host->addr;
 1528         if(!host->is_ipv6) return 0;
 1529         return acl_addr_matches_ipv6host(acl, addr, host->port);
 1530 #else
 1531         return 0; /* no inet6, no match */
 1532 #endif
 1533     }
 1534     else
 1535     {
 1536         struct sockaddr_in* addr = (struct sockaddr_in*)&host->addr;
 1537         if(host->is_ipv6) return 0;
 1538         return acl_addr_matches_ipv4host(acl, addr, host->port);
 1539     }
 1540     /* ENOTREACH */
 1541     return 0;
 1542 }
 1543 
 1544 int
 1545 acl_addr_matches(struct acl_options* acl, struct query* q)
 1546 {
 1547     if(acl->is_ipv6)
 1548     {
 1549 #ifdef INET6
 1550         struct sockaddr_storage* addr = (struct sockaddr_storage*)&q->addr;
 1551         if(addr->ss_family != AF_INET6)
 1552             return 0;
 1553         return acl_addr_matches_ipv6host(acl, addr, ntohs(((struct sockaddr_in6*)addr)->sin6_port));
 1554 #else
 1555         return 0; /* no inet6, no match */
 1556 #endif
 1557     }
 1558     else
 1559     {
 1560         struct sockaddr_in* addr = (struct sockaddr_in*)&q->addr;
 1561         if(addr->sin_family != AF_INET)
 1562             return 0;
 1563         return acl_addr_matches_ipv4host(acl, addr, ntohs(addr->sin_port));
 1564     }
 1565     /* ENOTREACH */
 1566     return 0;
 1567 }
 1568 
 1569 int
 1570 acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz)
 1571 {
 1572     size_t i;
 1573 #ifndef NDEBUG
 1574     assert(sz % 4 == 0);
 1575 #endif
 1576     sz /= 4;
 1577     for(i=0; i<sz; ++i)
 1578     {
 1579         if(((*a++)&*mask) != ((*b++)&*mask))
 1580             return 0;
 1581         ++mask;
 1582     }
 1583     return 1;
 1584 }
 1585 
 1586 int
 1587 acl_addr_match_range_v4(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
 1588 {
 1589     assert(sz == 4); (void)sz;
 1590     /* check treats x as one huge number */
 1591 
 1592     /* if outside bounds, we are done */
 1593     if(*minval > *x)
 1594         return 0;
 1595     if(*maxval < *x)
 1596         return 0;
 1597 
 1598     return 1;
 1599 }
 1600 
 1601 #ifdef INET6
 1602 int
 1603 acl_addr_match_range_v6(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
 1604 {
 1605     size_t i;
 1606     uint8_t checkmin = 1, checkmax = 1;
 1607 #ifndef NDEBUG
 1608     assert(sz % 4 == 0);
 1609 #endif
 1610     /* check treats x as one huge number */
 1611     sz /= 4;
 1612     for(i=0; i<sz; ++i)
 1613     {
 1614         /* if outside bounds, we are done */
 1615         if(checkmin)
 1616             if(minval[i] > x[i])
 1617                 return 0;
 1618         if(checkmax)
 1619             if(maxval[i] < x[i])
 1620                 return 0;
 1621         /* if x is equal to a bound, that bound needs further checks */
 1622         if(checkmin && minval[i]!=x[i])
 1623             checkmin = 0;
 1624         if(checkmax && maxval[i]!=x[i])
 1625             checkmax = 0;
 1626         if(!checkmin && !checkmax)
 1627             return 1; /* will always match */
 1628     }
 1629     return 1;
 1630 }
 1631 #endif /* INET6 */
 1632 
 1633 int
 1634 acl_key_matches(struct acl_options* acl, struct query* q)
 1635 {
 1636     if(acl->blocked)
 1637         return 1;
 1638     if(acl->nokey) {
 1639         if(q->tsig.status == TSIG_NOT_PRESENT)
 1640             return 1;
 1641         return 0;
 1642     }
 1643     /* check name of tsig key */
 1644     if(q->tsig.status != TSIG_OK) {
 1645         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail query has no TSIG"));
 1646         return 0; /* query has no TSIG */
 1647     }
 1648     if(q->tsig.error_code != TSIG_ERROR_NOERROR) {
 1649         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail, tsig has error"));
 1650         return 0; /* some tsig error */
 1651     }
 1652     if(!acl->key_options->tsig_key) {
 1653         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail no config"));
 1654         return 0; /* key not properly configured */
 1655     }
 1656     if(dname_compare(q->tsig.key_name,
 1657         acl->key_options->tsig_key->name) != 0) {
 1658         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail wrong key name"));
 1659         return 0; /* wrong key name */
 1660     }
 1661     if(tsig_strlowercmp(q->tsig.algorithm->short_name,
 1662         acl->key_options->algorithm) != 0 && (
 1663         strncmp("hmac-", q->tsig.algorithm->short_name, 5) != 0 ||
 1664         tsig_strlowercmp(q->tsig.algorithm->short_name+5,
 1665         acl->key_options->algorithm) != 0) ) {
 1666         DEBUG(DEBUG_XFRD,2, (LOG_ERR, "query tsig wrong algorithm"));
 1667         return 0; /* no such algo */
 1668     }
 1669     return 1;
 1670 }
 1671 
 1672 int
 1673 acl_same_host(struct acl_options* a, struct acl_options* b)
 1674 {
 1675     if(a->is_ipv6 && !b->is_ipv6)
 1676         return 0;
 1677     if(!a->is_ipv6 && b->is_ipv6)
 1678         return 0;
 1679     if(a->port != b->port)
 1680         return 0;
 1681     if(a->rangetype != b->rangetype)
 1682         return 0;
 1683     if(!a->is_ipv6) {
 1684         if(memcmp(&a->addr.addr, &b->addr.addr,
 1685            sizeof(struct in_addr)) != 0)
 1686             return 0;
 1687         if(a->rangetype != acl_range_single &&
 1688            memcmp(&a->range_mask.addr, &b->range_mask.addr,
 1689            sizeof(struct in_addr)) != 0)
 1690             return 0;
 1691     } else {
 1692 #ifdef INET6
 1693         if(memcmp(&a->addr.addr6, &b->addr.addr6,
 1694            sizeof(struct in6_addr)) != 0)
 1695             return 0;
 1696         if(a->rangetype != acl_range_single &&
 1697            memcmp(&a->range_mask.addr6, &b->range_mask.addr6,
 1698            sizeof(struct in6_addr)) != 0)
 1699             return 0;
 1700 #else
 1701         return 0;
 1702 #endif
 1703     }
 1704     return 1;
 1705 }
 1706 
 1707 #if defined(HAVE_SSL)
 1708 void
 1709 key_options_tsig_add(struct nsd_options* opt)
 1710 {
 1711     struct key_options* optkey;
 1712     RBTREE_FOR(optkey, struct key_options*, opt->keys) {
 1713         key_options_setup(opt->region, optkey);
 1714         tsig_add_key(optkey->tsig_key);
 1715     }
 1716 }
 1717 #endif
 1718 
 1719 int
 1720 zone_is_slave(struct zone_options* opt)
 1721 {
 1722     return opt && opt->pattern && opt->pattern->request_xfr != 0;
 1723 }
 1724 
 1725 /* get a character in string (or replacement char if not long enough) */
 1726 static const char*
 1727 get_char(const char* str, size_t i)
 1728 {
 1729     static char res[2];
 1730     if(i >= strlen(str))
 1731         return ".";
 1732     res[0] = str[i];
 1733     res[1] = 0;
 1734     return res;
 1735 }
 1736 /* get end label of the zone name (or .) */
 1737 static const char*
 1738 get_end_label(struct zone_options* zone, int i)
 1739 {
 1740     const dname_type* d = (const dname_type*)zone->node.key;
 1741     if(i >= d->label_count) {
 1742         return ".";
 1743     }
 1744     return wirelabel2str(dname_label(d, i));
 1745 }
 1746 /* replace occurrences of one with two */
 1747 void
 1748 replace_str(char* str, size_t len, const char* one, const char* two)
 1749 {
 1750     char* pos;
 1751     char* at = str;
 1752     while( (pos=strstr(at, one)) ) {
 1753         if(strlen(str)+strlen(two)-strlen(one) >= len)
 1754             return; /* no more space to replace */
 1755         /* stuff before pos is fine */
 1756         /* move the stuff after pos to make space for two, add
 1757          * one to length of remainder to also copy the 0 byte end */
 1758         memmove(pos+strlen(two), pos+strlen(one),
 1759             strlen(pos+strlen(one))+1);
 1760         /* copy in two */
 1761         memmove(pos, two, strlen(two));
 1762         /* at is end of the newly inserted two (avoids recursion if
 1763          * two contains one) */
 1764         at = pos+strlen(two);
 1765     }
 1766 }
 1767 
 1768 const char*
 1769 config_cook_string(struct zone_options* zone, const char* input)
 1770 {
 1771     static char f[1024];
 1772     /* if not a template, return as-is */
 1773     if(!strchr(input, '%')) {
 1774         return input;
 1775     }
 1776     strlcpy(f, input, sizeof(f));
 1777     if(strstr(f, "%1"))
 1778         replace_str(f, sizeof(f), "%1", get_char(zone->name, 0));
 1779     if(strstr(f, "%2"))
 1780         replace_str(f, sizeof(f), "%2", get_char(zone->name, 1));
 1781     if(strstr(f, "%3"))
 1782         replace_str(f, sizeof(f), "%3", get_char(zone->name, 2));
 1783     if(strstr(f, "%z"))
 1784         replace_str(f, sizeof(f), "%z", get_end_label(zone, 1));
 1785     if(strstr(f, "%y"))
 1786         replace_str(f, sizeof(f), "%y", get_end_label(zone, 2));
 1787     if(strstr(f, "%x"))
 1788         replace_str(f, sizeof(f), "%x", get_end_label(zone, 3));
 1789     if(strstr(f, "%s"))
 1790         replace_str(f, sizeof(f), "%s", zone->name);
 1791     return f;
 1792 }
 1793 
 1794 const char*
 1795 config_make_zonefile(struct zone_options* zone, struct nsd* nsd)
 1796 {
 1797     static char f[1024];
 1798     /* if not a template, return as-is */
 1799     if(!strchr(zone->pattern->zonefile, '%')) {
 1800         if (nsd->chrootdir && nsd->chrootdir[0] && 
 1801             zone->pattern->zonefile &&
 1802             zone->pattern->zonefile[0] == '/' &&
 1803             strncmp(zone->pattern->zonefile, nsd->chrootdir,
 1804             strlen(nsd->chrootdir)) == 0)
 1805             /* -1 because chrootdir ends in trailing slash */
 1806             return zone->pattern->zonefile + strlen(nsd->chrootdir) - 1;
 1807         return zone->pattern->zonefile;
 1808     }
 1809     strlcpy(f, zone->pattern->zonefile, sizeof(f));
 1810     if(strstr(f, "%1"))
 1811         replace_str(f, sizeof(f), "%1", get_char(zone->name, 0));
 1812     if(strstr(f, "%2"))
 1813         replace_str(f, sizeof(f), "%2", get_char(zone->name, 1));
 1814     if(strstr(f, "%3"))
 1815         replace_str(f, sizeof(f), "%3", get_char(zone->name, 2));
 1816     if(strstr(f, "%z"))
 1817         replace_str(f, sizeof(f), "%z", get_end_label(zone, 1));
 1818     if(strstr(f, "%y"))
 1819         replace_str(f, sizeof(f), "%y", get_end_label(zone, 2));
 1820     if(strstr(f, "%x"))
 1821         replace_str(f, sizeof(f), "%x", get_end_label(zone, 3));
 1822     if(strstr(f, "%s"))
 1823         replace_str(f, sizeof(f), "%s", zone->name);
 1824     if (nsd->chrootdir && nsd->chrootdir[0] && f[0] == '/' &&
 1825         strncmp(f, nsd->chrootdir, strlen(nsd->chrootdir)) == 0)
 1826         /* -1 because chrootdir ends in trailing slash */
 1827         return f + strlen(nsd->chrootdir) - 1;
 1828     return f;
 1829 }
 1830 
 1831 struct zone_options*
 1832 zone_options_find(struct nsd_options* opt, const struct dname* apex)
 1833 {
 1834     return (struct zone_options*) rbtree_search(opt->zone_options, apex);
 1835 }
 1836 
 1837 struct acl_options*
 1838 acl_find_num(struct acl_options* acl, int num)
 1839 {
 1840     int count = num;
 1841     if(num < 0)
 1842         return 0;
 1843     while(acl && count > 0) {
 1844         acl = acl->next;
 1845         count--;
 1846     }
 1847     if(count == 0)
 1848         return acl;
 1849     return 0;
 1850 }
 1851 
 1852 /* true if ipv6 address, false if ipv4 */
 1853 int
 1854 parse_acl_is_ipv6(const char* p)
 1855 {
 1856     /* see if addr is ipv6 or ipv4 -- by : and . */
 1857     while(*p) {
 1858         if(*p == '.') return 0;
 1859         if(*p == ':') return 1;
 1860         ++p;
 1861     }
 1862     return 0;
 1863 }
 1864 
 1865 /* returns range type. mask is the 2nd part of the range */
 1866 int
 1867 parse_acl_range_type(char* ip, char** mask)
 1868 {
 1869     char *p;
 1870     if((p=strchr(ip, '&'))!=0) {
 1871         *p = 0;
 1872         *mask = p+1;
 1873         return acl_range_mask;
 1874     }
 1875     if((p=strchr(ip, '/'))!=0) {
 1876         *p = 0;
 1877         *mask = p+1;
 1878         return acl_range_subnet;
 1879     }
 1880     if((p=strchr(ip, '-'))!=0) {
 1881         *p = 0;
 1882         *mask = p+1;
 1883         return acl_range_minmax;
 1884     }
 1885     *mask = 0;
 1886     return acl_range_single;
 1887 }
 1888 
 1889 /* parses subnet mask, fills 0 mask as well */
 1890 void
 1891 parse_acl_range_subnet(char* p, void* addr, int maxbits)
 1892 {
 1893     int subnet_bits = atoi(p);
 1894     uint8_t* addr_bytes = (uint8_t*)addr;
 1895     if(subnet_bits == 0 && strcmp(p, "0")!=0) {
 1896         c_error("bad subnet range '%s'", p);
 1897         return;
 1898     }
 1899     if(subnet_bits < 0 || subnet_bits > maxbits) {
 1900         c_error("subnet of %d bits out of range [0..%d]", subnet_bits, maxbits);
 1901         return;
 1902     }
 1903     /* fill addr with n bits of 1s (struct has been zeroed) */
 1904     while(subnet_bits >= 8) {
 1905         *addr_bytes++ = 0xff;
 1906         subnet_bits -= 8;
 1907     }
 1908     if(subnet_bits > 0) {
 1909         uint8_t shifts[] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
 1910         *addr_bytes = shifts[subnet_bits];
 1911     }
 1912 }
 1913 
 1914 struct acl_options*
 1915 parse_acl_info(region_type* region, char* ip, const char* key)
 1916 {
 1917     char* p;
 1918     struct acl_options* acl = (struct acl_options*)region_alloc(region,
 1919         sizeof(struct acl_options));
 1920     acl->next = 0;
 1921     /* ip */
 1922     acl->ip_address_spec = region_strdup(region, ip);
 1923     acl->use_axfr_only = 0;
 1924     acl->allow_udp = 0;
 1925     acl->ixfr_disabled = 0;
 1926     acl->bad_xfr_count = 0;
 1927     acl->key_options = 0;
 1928     acl->is_ipv6 = 0;
 1929     acl->port = 0;
 1930     memset(&acl->addr, 0, sizeof(union acl_addr_storage));
 1931     memset(&acl->range_mask, 0, sizeof(union acl_addr_storage));
 1932     if((p=strrchr(ip, '@'))!=0) {
 1933         if(atoi(p+1) == 0) c_error("expected port number after '@'");
 1934         else acl->port = atoi(p+1);
 1935         *p=0;
 1936     }
 1937     acl->rangetype = parse_acl_range_type(ip, &p);
 1938     if(parse_acl_is_ipv6(ip)) {
 1939         acl->is_ipv6 = 1;
 1940 #ifdef INET6
 1941         if(inet_pton(AF_INET6, ip, &acl->addr.addr6) != 1)
 1942             c_error("Bad ip6 address '%s'", ip);
 1943         if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) {
 1944             assert(p);
 1945             if(inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1)
 1946                 c_error("Bad ip6 address mask '%s'", p);
 1947         }
 1948         if(acl->rangetype==acl_range_subnet) {
 1949             assert(p);
 1950             parse_acl_range_subnet(p, &acl->range_mask.addr6, 128);
 1951         }
 1952 #else
 1953         c_error("encountered IPv6 address '%s'.", ip);
 1954 #endif /* INET6 */
 1955     } else {
 1956         acl->is_ipv6 = 0;
 1957         if(inet_pton(AF_INET, ip, &acl->addr.addr) != 1)
 1958             c_error("Bad ip4 address '%s'", ip);
 1959         if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) {
 1960             assert(p);
 1961             if(inet_pton(AF_INET, p, &acl->range_mask.addr) != 1)
 1962                 c_error("Bad ip4 address mask '%s'", p);
 1963         }
 1964         if(acl->rangetype==acl_range_subnet) {
 1965             assert(p);
 1966             parse_acl_range_subnet(p, &acl->range_mask.addr, 32);
 1967         }
 1968     }
 1969 
 1970     /* key */
 1971     if(strcmp(key, "NOKEY")==0) {
 1972         acl->nokey = 1;
 1973         acl->blocked = 0;
 1974         acl->key_name = 0;
 1975     } else if(strcmp(key, "BLOCKED")==0) {
 1976         acl->nokey = 0;
 1977         acl->blocked = 1;
 1978         acl->key_name = 0;
 1979     } else {
 1980         acl->nokey = 0;
 1981         acl->blocked = 0;
 1982         acl->key_name = region_strdup(region, key);
 1983     }
 1984     return acl;
 1985 }
 1986 
 1987 /* copy acl list at end of parser start, update current */
 1988 static
 1989 void copy_and_append_acls(struct acl_options** start, struct acl_options* list)
 1990 {
 1991     struct acl_options *tail = NULL;
 1992 
 1993     assert(start != NULL);
 1994 
 1995     tail = *start;
 1996     if(tail) {
 1997         while(tail->next) {
 1998             tail = tail->next;
 1999         }
 2000     }
 2001 
 2002     while(list) {
 2003         struct acl_options* acl = copy_acl(cfg_parser->opt->region,
 2004             list);
 2005         acl->next = NULL;
 2006         if(tail) {
 2007             tail->next = acl;
 2008         } else {
 2009             *start = acl;
 2010         }
 2011         tail = acl;
 2012         list = list->next;
 2013     }
 2014 }
 2015 
 2016 void
 2017 config_apply_pattern(struct pattern_options *dest, const char* name)
 2018 {
 2019     /* find the pattern */
 2020     struct pattern_options* pat = pattern_options_find(cfg_parser->opt,
 2021         name);
 2022     if(!pat) {
 2023         c_error("could not find pattern %s", name);
 2024         return;
 2025     }
 2026 
 2027     /* apply settings */
 2028     if(pat->zonefile)
 2029         dest->zonefile = region_strdup(cfg_parser->opt->region,
 2030             pat->zonefile);
 2031     if(pat->zonestats)
 2032         dest->zonestats = region_strdup(cfg_parser->opt->region,
 2033             pat->zonestats);
 2034     if(!pat->allow_axfr_fallback_is_default) {
 2035         dest->allow_axfr_fallback = pat->allow_axfr_fallback;
 2036         dest->allow_axfr_fallback_is_default = 0;
 2037     }
 2038     if(!pat->notify_retry_is_default) {
 2039         dest->notify_retry = pat->notify_retry;
 2040         dest->notify_retry_is_default = 0;
 2041     }
 2042     if(!pat->max_refresh_time_is_default) {
 2043         dest->max_refresh_time = pat->max_refresh_time;
 2044         dest->max_refresh_time_is_default = 0;
 2045     }
 2046     if(!pat->min_refresh_time_is_default) {
 2047         dest->min_refresh_time = pat->min_refresh_time;
 2048         dest->min_refresh_time_is_default = 0;
 2049     }
 2050     if(!pat->max_retry_time_is_default) {
 2051         dest->max_retry_time = pat->max_retry_time;
 2052         dest->max_retry_time_is_default = 0;
 2053     }
 2054     if(!pat->min_retry_time_is_default) {
 2055         dest->min_retry_time = pat->min_retry_time;
 2056         dest->min_retry_time_is_default = 0;
 2057     }
 2058     if(!expire_time_is_default(pat->min_expire_time_expr)) {
 2059         dest->min_expire_time = pat->min_expire_time;
 2060         dest->min_expire_time_expr = pat->min_expire_time_expr;
 2061     }
 2062     dest->size_limit_xfr = pat->size_limit_xfr;
 2063 #ifdef RATELIMIT
 2064     dest->rrl_whitelist |= pat->rrl_whitelist;
 2065 #endif
 2066     /* append acl items */
 2067     copy_and_append_acls(&dest->allow_notify, pat->allow_notify);
 2068     copy_and_append_acls(&dest->request_xfr, pat->request_xfr);
 2069     copy_and_append_acls(&dest->notify, pat->notify);
 2070     copy_and_append_acls(&dest->provide_xfr, pat->provide_xfr);
 2071     copy_and_append_acls(&dest->allow_query, pat->allow_query);
 2072     copy_and_append_acls(&dest->outgoing_interface, pat->outgoing_interface);
 2073     if(pat->multi_master_check)
 2074         dest->multi_master_check = pat->multi_master_check;
 2075 }
 2076 
 2077 void
 2078 nsd_options_destroy(struct nsd_options* opt)
 2079 {
 2080     region_destroy(opt->region);
 2081 #ifdef MEMCLEAN /* OS collects memory pages */
 2082     c_lex_destroy();
 2083 #endif
 2084 }
 2085 
 2086 unsigned getzonestatid(struct nsd_options* opt, struct zone_options* zopt)
 2087 {
 2088 #ifdef USE_ZONE_STATS
 2089     const char* statname;
 2090     struct zonestatname* n;
 2091     rbnode_type* res;
 2092     /* try to find the instantiated zonestat name */
 2093     if(!zopt->pattern->zonestats || zopt->pattern->zonestats[0]==0)
 2094         return 0; /* no zone stats */
 2095     statname = config_cook_string(zopt, zopt->pattern->zonestats);
 2096     res = rbtree_search(opt->zonestatnames, statname);
 2097     if(res)
 2098         return ((struct zonestatname*)res)->id;
 2099     /* create it */
 2100     n = (struct zonestatname*)region_alloc_zero(opt->region, sizeof(*n));
 2101     n->node.key = region_strdup(opt->region, statname);
 2102     if(!n->node.key) {
 2103         log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
 2104         exit(1);
 2105     }
 2106     n->id = (unsigned)(opt->zonestatnames->count);
 2107     rbtree_insert(opt->zonestatnames, (rbnode_type*)n);
 2108     return n->id;
 2109 #else /* USE_ZONE_STATS */
 2110     (void)opt; (void)zopt;
 2111     return 0;
 2112 #endif /* USE_ZONE_STATS */
 2113 }
 2114 
 2115 /** check if config turns on IP-address interface with certificates or a
 2116  * named pipe without certificates. */
 2117 int
 2118 options_remote_is_address(struct nsd_options* cfg)
 2119 {
 2120     if(!cfg->control_enable) return 0;
 2121     if(!cfg->control_interface) return 1;
 2122     if(!cfg->control_interface->address) return 1;
 2123     if(cfg->control_interface->address[0] == 0) return 1;
 2124     return (cfg->control_interface->address[0] != '/');
 2125 }
 2126 
 2127 #ifdef HAVE_GETIFADDRS
 2128 static void
 2129 resolve_ifa_name(struct ifaddrs *ifas, const char *search_ifa, char ***ip_addresses, size_t *ip_addresses_size)
 2130 {
 2131     struct ifaddrs *ifa;
 2132     size_t last_ip_addresses_size = *ip_addresses_size;
 2133 
 2134     for(ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
 2135         sa_family_t family;
 2136         const char* atsign;
 2137 #ifdef INET6      /* |   address ip    | % |  ifa name  | @ |  port  | nul */
 2138         char addr_buf[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1 + 16 + 1];
 2139 #else
 2140         char addr_buf[INET_ADDRSTRLEN + 1 + 16 + 1];
 2141 #endif
 2142 
 2143         if((atsign=strrchr(search_ifa, '@')) != NULL) {
 2144             if(strlen(ifa->ifa_name) != (size_t)(atsign-search_ifa)
 2145                || strncmp(ifa->ifa_name, search_ifa,
 2146                atsign-search_ifa) != 0)
 2147                 continue;
 2148         } else {
 2149             if(strcmp(ifa->ifa_name, search_ifa) != 0)
 2150                 continue;
 2151             atsign = "";
 2152         }
 2153 
 2154         if(ifa->ifa_addr == NULL)
 2155             continue;
 2156 
 2157         family = ifa->ifa_addr->sa_family;
 2158         if(family == AF_INET) {
 2159             char a4[INET_ADDRSTRLEN + 1];
 2160             struct sockaddr_in *in4 = (struct sockaddr_in *)
 2161                 ifa->ifa_addr;
 2162             if(!inet_ntop(family, &in4->sin_addr, a4, sizeof(a4)))
 2163                 error("inet_ntop");
 2164             snprintf(addr_buf, sizeof(addr_buf), "%s%s",
 2165                 a4, atsign);
 2166         }
 2167 #ifdef INET6
 2168         else if(family == AF_INET6) {
 2169             struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)
 2170                 ifa->ifa_addr;
 2171             char a6[INET6_ADDRSTRLEN + 1];
 2172             char if_index_name[IF_NAMESIZE + 1];
 2173             if_index_name[0] = 0;
 2174             if(!inet_ntop(family, &in6->sin6_addr, a6, sizeof(a6)))
 2175                 error("inet_ntop");
 2176             if_indextoname(in6->sin6_scope_id,
 2177                 (char *)if_index_name);
 2178             if (strlen(if_index_name) != 0) {
 2179                 snprintf(addr_buf, sizeof(addr_buf),
 2180                     "%s%%%s%s", a6, if_index_name, atsign);
 2181             } else {
 2182                 snprintf(addr_buf, sizeof(addr_buf), "%s%s",
 2183                     a6, atsign);
 2184             }
 2185         }
 2186 #endif
 2187         else {
 2188             continue;
 2189         }
 2190         VERBOSITY(4, (LOG_INFO, "interface %s has address %s",
 2191             search_ifa, addr_buf));
 2192 
 2193         *ip_addresses = xrealloc(*ip_addresses, sizeof(char *) * (*ip_addresses_size + 1));
 2194         (*ip_addresses)[*ip_addresses_size] = xstrdup(addr_buf);
 2195         (*ip_addresses_size)++;
 2196     }
 2197 
 2198     if (*ip_addresses_size == last_ip_addresses_size) {
 2199         *ip_addresses = xrealloc(*ip_addresses, sizeof(char *) * (*ip_addresses_size + 1));
 2200         (*ip_addresses)[*ip_addresses_size] = xstrdup(search_ifa);
 2201         (*ip_addresses_size)++;
 2202     }
 2203 }
 2204 
 2205 static void
 2206 resolve_interface_names_for_ref(struct ip_address_option** ip_addresses_ref,
 2207         struct ifaddrs *addrs, region_type* region)
 2208 {
 2209     struct ip_address_option *ip_addr;
 2210     struct ip_address_option *last = NULL;
 2211     struct ip_address_option *first = NULL;
 2212 
 2213     /* replace the list of ip_adresses with a new list where the
 2214      * interface names are replaced with their ip-address strings
 2215      * from getifaddrs.  An interface can have several addresses. */
 2216     for(ip_addr = *ip_addresses_ref; ip_addr; ip_addr = ip_addr->next) {
 2217         char **ip_addresses = NULL;
 2218         size_t ip_addresses_size = 0, i;
 2219         resolve_ifa_name(addrs, ip_addr->address, &ip_addresses,
 2220             &ip_addresses_size);
 2221 
 2222         for (i = 0; i < ip_addresses_size; i++) {
 2223             struct ip_address_option *current;
 2224             /* this copies the range_option, dev, and fib from
 2225              * the original ip_address option to the new ones
 2226              * with the addresses spelled out by resolve_ifa_name*/
 2227             current = region_alloc_init(region, ip_addr,
 2228                 sizeof(*ip_addr));
 2229             current->address = region_strdup(region,
 2230                 ip_addresses[i]);
 2231             current->next = NULL;
 2232             free(ip_addresses[i]);
 2233 
 2234             if(first == NULL) {
 2235                 first = current;
 2236             } else {
 2237                 last->next = current;
 2238             }
 2239             last = current;
 2240         }
 2241         free(ip_addresses);
 2242     }
 2243     *ip_addresses_ref = first;
 2244 
 2245 }
 2246 #endif /* HAVE_GETIFADDRS */
 2247 
 2248 void
 2249 resolve_interface_names(struct nsd_options* options)
 2250 {
 2251 #ifdef HAVE_GETIFADDRS
 2252     struct ifaddrs *addrs;
 2253 
 2254     if(getifaddrs(&addrs) == -1)
 2255           error("failed to list interfaces");
 2256 
 2257     resolve_interface_names_for_ref(&options->ip_addresses, 
 2258             addrs, options->region);
 2259     resolve_interface_names_for_ref(&options->control_interface, 
 2260             addrs, options->region);
 2261 
 2262     freeifaddrs(addrs);
 2263 #else
 2264     (void)options;
 2265 #endif /* HAVE_GETIFADDRS */
 2266 }