"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/bin/named/zoneconf.c" (4 Sep 2020, 58801 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


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

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <inttypes.h>
   13 #include <stdbool.h>
   14 
   15 #include <isc/buffer.h>
   16 #include <isc/file.h>
   17 #include <isc/mem.h>
   18 #include <isc/print.h>
   19 #include <isc/stats.h>
   20 #include <isc/string.h> /* Required for HP/UX (and others?) */
   21 #include <isc/util.h>
   22 
   23 #include <dns/acl.h>
   24 #include <dns/db.h>
   25 #include <dns/fixedname.h>
   26 #include <dns/ipkeylist.h>
   27 #include <dns/journal.h>
   28 #include <dns/kasp.h>
   29 #include <dns/log.h>
   30 #include <dns/masterdump.h>
   31 #include <dns/name.h>
   32 #include <dns/rdata.h>
   33 #include <dns/rdatalist.h>
   34 #include <dns/rdataset.h>
   35 #include <dns/rdatatype.h>
   36 #include <dns/result.h>
   37 #include <dns/sdlz.h>
   38 #include <dns/ssu.h>
   39 #include <dns/stats.h>
   40 #include <dns/tsig.h>
   41 #include <dns/view.h>
   42 #include <dns/zone.h>
   43 
   44 #include <ns/client.h>
   45 
   46 #include <named/config.h>
   47 #include <named/globals.h>
   48 #include <named/log.h>
   49 #include <named/server.h>
   50 #include <named/zoneconf.h>
   51 
   52 /* ACLs associated with zone */
   53 typedef enum {
   54     allow_notify,
   55     allow_query,
   56     allow_query_on,
   57     allow_transfer,
   58     allow_update,
   59     allow_update_forwarding
   60 } acl_type_t;
   61 
   62 #define RETERR(x)                        \
   63     do {                             \
   64         isc_result_t _r = (x);   \
   65         if (_r != ISC_R_SUCCESS) \
   66             return ((_r));   \
   67     } while (0)
   68 
   69 #define CHECK(x)                             \
   70     do {                                 \
   71         result = (x);                \
   72         if (result != ISC_R_SUCCESS) \
   73             goto cleanup;        \
   74     } while (0)
   75 
   76 /*%
   77  * Convenience function for configuring a single zone ACL.
   78  */
   79 static isc_result_t
   80 configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
   81            const cfg_obj_t *config, acl_type_t acltype,
   82            cfg_aclconfctx_t *actx, dns_zone_t *zone,
   83            void (*setzacl)(dns_zone_t *, dns_acl_t *),
   84            void (*clearzacl)(dns_zone_t *)) {
   85     isc_result_t result;
   86     const cfg_obj_t *maps[5] = { NULL, NULL, NULL, NULL, NULL };
   87     const cfg_obj_t *aclobj = NULL;
   88     int i = 0;
   89     dns_acl_t **aclp = NULL, *acl = NULL;
   90     const char *aclname;
   91     dns_view_t *view;
   92 
   93     view = dns_zone_getview(zone);
   94 
   95     switch (acltype) {
   96     case allow_notify:
   97         if (view != NULL) {
   98             aclp = &view->notifyacl;
   99         }
  100         aclname = "allow-notify";
  101         break;
  102     case allow_query:
  103         if (view != NULL) {
  104             aclp = &view->queryacl;
  105         }
  106         aclname = "allow-query";
  107         break;
  108     case allow_query_on:
  109         if (view != NULL) {
  110             aclp = &view->queryonacl;
  111         }
  112         aclname = "allow-query-on";
  113         break;
  114     case allow_transfer:
  115         if (view != NULL) {
  116             aclp = &view->transferacl;
  117         }
  118         aclname = "allow-transfer";
  119         break;
  120     case allow_update:
  121         if (view != NULL) {
  122             aclp = &view->updateacl;
  123         }
  124         aclname = "allow-update";
  125         break;
  126     case allow_update_forwarding:
  127         if (view != NULL) {
  128             aclp = &view->upfwdacl;
  129         }
  130         aclname = "allow-update-forwarding";
  131         break;
  132     default:
  133         INSIST(0);
  134         ISC_UNREACHABLE();
  135     }
  136 
  137     /* First check to see if ACL is defined within the zone */
  138     if (zconfig != NULL) {
  139         maps[0] = cfg_tuple_get(zconfig, "options");
  140         (void)named_config_get(maps, aclname, &aclobj);
  141         if (aclobj != NULL) {
  142             aclp = NULL;
  143             goto parse_acl;
  144         }
  145     }
  146 
  147     /* Failing that, see if there's a default ACL already in the view */
  148     if (aclp != NULL && *aclp != NULL) {
  149         (*setzacl)(zone, *aclp);
  150         return (ISC_R_SUCCESS);
  151     }
  152 
  153     /* Check for default ACLs that haven't been parsed yet */
  154     if (vconfig != NULL) {
  155         const cfg_obj_t *options = cfg_tuple_get(vconfig, "options");
  156         if (options != NULL) {
  157             maps[i++] = options;
  158         }
  159     }
  160     if (config != NULL) {
  161         const cfg_obj_t *options = NULL;
  162         (void)cfg_map_get(config, "options", &options);
  163         if (options != NULL) {
  164             maps[i++] = options;
  165         }
  166     }
  167     maps[i++] = named_g_defaults;
  168     maps[i] = NULL;
  169 
  170     (void)named_config_get(maps, aclname, &aclobj);
  171     if (aclobj == NULL) {
  172         (*clearzacl)(zone);
  173         return (ISC_R_SUCCESS);
  174     }
  175 
  176 parse_acl:
  177     result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx,
  178                     dns_zone_getmctx(zone), 0, &acl);
  179     if (result != ISC_R_SUCCESS) {
  180         return (result);
  181     }
  182     (*setzacl)(zone, acl);
  183 
  184     /* Set the view default now */
  185     if (aclp != NULL) {
  186         dns_acl_attach(acl, aclp);
  187     }
  188 
  189     dns_acl_detach(&acl);
  190     return (ISC_R_SUCCESS);
  191 }
  192 
  193 /*%
  194  * Parse the zone update-policy statement.
  195  */
  196 static isc_result_t
  197 configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
  198             const char *zname) {
  199     const cfg_obj_t *updatepolicy = NULL;
  200     const cfg_listelt_t *element, *element2;
  201     dns_ssutable_t *table = NULL;
  202     isc_mem_t *mctx = dns_zone_getmctx(zone);
  203     bool autoddns = false;
  204     isc_result_t result;
  205 
  206     (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
  207 
  208     if (updatepolicy == NULL) {
  209         dns_zone_setssutable(zone, NULL);
  210         return (ISC_R_SUCCESS);
  211     }
  212 
  213     if (cfg_obj_isstring(updatepolicy) &&
  214         strcmp("local", cfg_obj_asstring(updatepolicy)) == 0)
  215     {
  216         autoddns = true;
  217         updatepolicy = NULL;
  218     }
  219 
  220     result = dns_ssutable_create(mctx, &table);
  221     if (result != ISC_R_SUCCESS) {
  222         return (result);
  223     }
  224 
  225     for (element = cfg_list_first(updatepolicy); element != NULL;
  226          element = cfg_list_next(element))
  227     {
  228         const cfg_obj_t *stmt = cfg_listelt_value(element);
  229         const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
  230         const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
  231         const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
  232         const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
  233         const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
  234         const char *str;
  235         bool grant = false;
  236         bool usezone = false;
  237         dns_ssumatchtype_t mtype = dns_ssumatchtype_name;
  238         dns_fixedname_t fname, fident;
  239         isc_buffer_t b;
  240         dns_rdatatype_t *types;
  241         unsigned int i, n;
  242 
  243         str = cfg_obj_asstring(mode);
  244         if (strcasecmp(str, "grant") == 0) {
  245             grant = true;
  246         } else if (strcasecmp(str, "deny") == 0) {
  247             grant = false;
  248         } else {
  249             INSIST(0);
  250             ISC_UNREACHABLE();
  251         }
  252 
  253         str = cfg_obj_asstring(matchtype);
  254         CHECK(dns_ssu_mtypefromstring(str, &mtype));
  255         if (mtype == dns_ssumatchtype_subdomain &&
  256             strcasecmp(str, "zonesub") == 0) {
  257             usezone = true;
  258         }
  259 
  260         dns_fixedname_init(&fident);
  261         str = cfg_obj_asstring(identity);
  262         isc_buffer_constinit(&b, str, strlen(str));
  263         isc_buffer_add(&b, strlen(str));
  264         result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
  265                        dns_rootname, 0, NULL);
  266         if (result != ISC_R_SUCCESS) {
  267             cfg_obj_log(identity, named_g_lctx, ISC_LOG_ERROR,
  268                     "'%s' is not a valid name", str);
  269             goto cleanup;
  270         }
  271 
  272         dns_fixedname_init(&fname);
  273         if (usezone) {
  274             dns_name_copynf(dns_zone_getorigin(zone),
  275                     dns_fixedname_name(&fname));
  276         } else {
  277             str = cfg_obj_asstring(dname);
  278             isc_buffer_constinit(&b, str, strlen(str));
  279             isc_buffer_add(&b, strlen(str));
  280             result = dns_name_fromtext(dns_fixedname_name(&fname),
  281                            &b, dns_rootname, 0, NULL);
  282             if (result != ISC_R_SUCCESS) {
  283                 cfg_obj_log(identity, named_g_lctx,
  284                         ISC_LOG_ERROR,
  285                         "'%s' is not a valid name", str);
  286                 goto cleanup;
  287             }
  288         }
  289 
  290         n = named_config_listcount(typelist);
  291         if (n == 0) {
  292             types = NULL;
  293         } else {
  294             types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
  295         }
  296 
  297         i = 0;
  298         for (element2 = cfg_list_first(typelist); element2 != NULL;
  299              element2 = cfg_list_next(element2))
  300         {
  301             const cfg_obj_t *typeobj;
  302             isc_textregion_t r;
  303 
  304             INSIST(i < n);
  305 
  306             typeobj = cfg_listelt_value(element2);
  307             str = cfg_obj_asstring(typeobj);
  308             DE_CONST(str, r.base);
  309             r.length = strlen(str);
  310 
  311             result = dns_rdatatype_fromtext(&types[i++], &r);
  312             if (result != ISC_R_SUCCESS) {
  313                 cfg_obj_log(identity, named_g_lctx,
  314                         ISC_LOG_ERROR,
  315                         "'%s' is not a valid type", str);
  316                 isc_mem_put(mctx, types,
  317                         n * sizeof(dns_rdatatype_t));
  318                 goto cleanup;
  319             }
  320         }
  321         INSIST(i == n);
  322 
  323         result = dns_ssutable_addrule(
  324             table, grant, dns_fixedname_name(&fident), mtype,
  325             dns_fixedname_name(&fname), n, types);
  326         if (types != NULL) {
  327             isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
  328         }
  329         if (result != ISC_R_SUCCESS) {
  330             goto cleanup;
  331         }
  332     }
  333 
  334     /*
  335      * If "update-policy local;" and a session key exists,
  336      * then use the default policy, which is equivalent to:
  337      * update-policy { grant <session-keyname> zonesub any; };
  338      */
  339     if (autoddns) {
  340         dns_rdatatype_t any = dns_rdatatype_any;
  341 
  342         if (named_g_server->session_keyname == NULL) {
  343             isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
  344                       NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
  345                       "failed to enable auto DDNS policy "
  346                       "for zone %s: session key not found",
  347                       zname);
  348             result = ISC_R_NOTFOUND;
  349             goto cleanup;
  350         }
  351 
  352         result = dns_ssutable_addrule(
  353             table, true, named_g_server->session_keyname,
  354             dns_ssumatchtype_local, dns_zone_getorigin(zone), 1,
  355             &any);
  356 
  357         if (result != ISC_R_SUCCESS) {
  358             goto cleanup;
  359         }
  360     }
  361 
  362     result = ISC_R_SUCCESS;
  363     dns_zone_setssutable(zone, table);
  364 
  365 cleanup:
  366     dns_ssutable_detach(&table);
  367     return (result);
  368 }
  369 
  370 /*
  371  * This is the TTL used for internally generated RRsets for static-stub zones.
  372  * The value doesn't matter because the mapping is static, but needs to be
  373  * defined for the sake of implementation.
  374  */
  375 #define STATICSTUB_SERVER_TTL 86400
  376 
  377 /*%
  378  * Configure an apex NS with glues for a static-stub zone.
  379  * For example, for the zone named "example.com", the following RRs will be
  380  * added to the zone DB:
  381  * example.com. NS example.com.
  382  * example.com. A 192.0.2.1
  383  * example.com. AAAA 2001:db8::1
  384  */
  385 static isc_result_t
  386 configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
  387                  dns_rdatalist_t *rdatalist_ns,
  388                  dns_rdatalist_t *rdatalist_a,
  389                  dns_rdatalist_t *rdatalist_aaaa) {
  390     const cfg_listelt_t *element;
  391     isc_mem_t *mctx = dns_zone_getmctx(zone);
  392     isc_region_t region, sregion;
  393     dns_rdata_t *rdata;
  394     isc_result_t result = ISC_R_SUCCESS;
  395 
  396     for (element = cfg_list_first(zconfig); element != NULL;
  397          element = cfg_list_next(element))
  398     {
  399         const isc_sockaddr_t *sa;
  400         isc_netaddr_t na;
  401         const cfg_obj_t *address = cfg_listelt_value(element);
  402         dns_rdatalist_t *rdatalist;
  403 
  404         sa = cfg_obj_assockaddr(address);
  405         if (isc_sockaddr_getport(sa) != 0) {
  406             cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
  407                     "port is not configurable for "
  408                     "static stub server-addresses");
  409             return (ISC_R_FAILURE);
  410         }
  411         isc_netaddr_fromsockaddr(&na, sa);
  412         if (isc_netaddr_getzone(&na) != 0) {
  413             cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
  414                     "scoped address is not allowed "
  415                     "for static stub "
  416                     "server-addresses");
  417             return (ISC_R_FAILURE);
  418         }
  419 
  420         switch (na.family) {
  421         case AF_INET:
  422             region.length = sizeof(na.type.in);
  423             rdatalist = rdatalist_a;
  424             break;
  425         default:
  426             INSIST(na.family == AF_INET6);
  427             region.length = sizeof(na.type.in6);
  428             rdatalist = rdatalist_aaaa;
  429             break;
  430         }
  431 
  432         rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
  433         region.base = (unsigned char *)(rdata + 1);
  434         memmove(region.base, &na.type, region.length);
  435         dns_rdata_init(rdata);
  436         dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
  437                      rdatalist->type, &region);
  438         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  439     }
  440 
  441     /*
  442      * If no address is specified (unlikely in this context, but possible),
  443      * there's nothing to do anymore.
  444      */
  445     if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
  446         ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) {
  447         return (ISC_R_SUCCESS);
  448     }
  449 
  450     /* Add to the list an apex NS with the ns name being the origin name */
  451     dns_name_toregion(dns_zone_getorigin(zone), &sregion);
  452     rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
  453     region.length = sregion.length;
  454     region.base = (unsigned char *)(rdata + 1);
  455     memmove(region.base, sregion.base, region.length);
  456     dns_rdata_init(rdata);
  457     dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns,
  458                  &region);
  459     ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);
  460 
  461     return (result);
  462 }
  463 
  464 /*%
  465  * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
  466  * For example, for the zone named "example.com", something like the following
  467  * RRs will be added to the zone DB:
  468  * example.com. NS ns.example.net.
  469  */
  470 static isc_result_t
  471 configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
  472                  dns_rdatalist_t *rdatalist,
  473                  const char *zname) {
  474     const cfg_listelt_t *element;
  475     isc_mem_t *mctx = dns_zone_getmctx(zone);
  476     dns_rdata_t *rdata;
  477     isc_region_t sregion, region;
  478     isc_result_t result = ISC_R_SUCCESS;
  479 
  480     for (element = cfg_list_first(zconfig); element != NULL;
  481          element = cfg_list_next(element))
  482     {
  483         const cfg_obj_t *obj;
  484         const char *str;
  485         dns_fixedname_t fixed_name;
  486         dns_name_t *nsname;
  487         isc_buffer_t b;
  488 
  489         obj = cfg_listelt_value(element);
  490         str = cfg_obj_asstring(obj);
  491 
  492         nsname = dns_fixedname_initname(&fixed_name);
  493 
  494         isc_buffer_constinit(&b, str, strlen(str));
  495         isc_buffer_add(&b, strlen(str));
  496         result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
  497         if (result != ISC_R_SUCCESS) {
  498             cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
  499                     "server-name '%s' is not a valid "
  500                     "name",
  501                     str);
  502             return (result);
  503         }
  504         if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
  505             cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
  506                     "server-name '%s' must not be a "
  507                     "subdomain of zone name '%s'",
  508                     str, zname);
  509             return (ISC_R_FAILURE);
  510         }
  511 
  512         dns_name_toregion(nsname, &sregion);
  513         rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
  514         region.length = sregion.length;
  515         region.base = (unsigned char *)(rdata + 1);
  516         memmove(region.base, sregion.base, region.length);
  517         dns_rdata_init(rdata);
  518         dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
  519                      dns_rdatatype_ns, &region);
  520         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  521     }
  522 
  523     return (result);
  524 }
  525 
  526 /*%
  527  * Configure static-stub zone.
  528  */
  529 static isc_result_t
  530 configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
  531              const char *zname, const char *dbtype) {
  532     int i = 0;
  533     const cfg_obj_t *obj;
  534     isc_mem_t *mctx = dns_zone_getmctx(zone);
  535     dns_db_t *db = NULL;
  536     dns_dbversion_t *dbversion = NULL;
  537     dns_dbnode_t *apexnode = NULL;
  538     dns_name_t apexname;
  539     isc_result_t result;
  540     dns_rdataset_t rdataset;
  541     dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
  542     dns_rdatalist_t *rdatalists[] = { &rdatalist_ns, &rdatalist_a,
  543                       &rdatalist_aaaa, NULL };
  544     dns_rdata_t *rdata;
  545     isc_region_t region;
  546 
  547     /* Create the DB beforehand */
  548     RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
  549                  dns_dbtype_stub, dns_zone_getclass(zone), 0, NULL,
  550                  &db));
  551 
  552     dns_rdataset_init(&rdataset);
  553 
  554     dns_rdatalist_init(&rdatalist_ns);
  555     rdatalist_ns.rdclass = dns_zone_getclass(zone);
  556     rdatalist_ns.type = dns_rdatatype_ns;
  557     rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;
  558 
  559     dns_rdatalist_init(&rdatalist_a);
  560     rdatalist_a.rdclass = dns_zone_getclass(zone);
  561     rdatalist_a.type = dns_rdatatype_a;
  562     rdatalist_a.ttl = STATICSTUB_SERVER_TTL;
  563 
  564     dns_rdatalist_init(&rdatalist_aaaa);
  565     rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
  566     rdatalist_aaaa.type = dns_rdatatype_aaaa;
  567     rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;
  568 
  569     /* Prepare zone RRs from the configuration */
  570     obj = NULL;
  571     result = cfg_map_get(zconfig, "server-addresses", &obj);
  572     if (result == ISC_R_SUCCESS) {
  573         INSIST(obj != NULL);
  574         CHECK(configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns,
  575                                &rdatalist_a,
  576                                &rdatalist_aaaa));
  577     }
  578 
  579     obj = NULL;
  580     result = cfg_map_get(zconfig, "server-names", &obj);
  581     if (result == ISC_R_SUCCESS) {
  582         INSIST(obj != NULL);
  583         CHECK(configure_staticstub_servernames(obj, zone, &rdatalist_ns,
  584                                zname));
  585     }
  586 
  587     /*
  588      * Sanity check: there should be at least one NS RR at the zone apex
  589      * to trigger delegation.
  590      */
  591     if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
  592         isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
  593                   NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
  594                   "No NS record is configured for a "
  595                   "static-stub zone '%s'",
  596                   zname);
  597         result = ISC_R_FAILURE;
  598         goto cleanup;
  599     }
  600 
  601     /*
  602      * Now add NS and glue A/AAAA RRsets to the zone DB.
  603      * First open a new version for the add operation and get a pointer
  604      * to the apex node (all RRs are of the apex name).
  605      */
  606     CHECK(dns_db_newversion(db, &dbversion));
  607 
  608     dns_name_init(&apexname, NULL);
  609     dns_name_clone(dns_zone_getorigin(zone), &apexname);
  610     CHECK(dns_db_findnode(db, &apexname, false, &apexnode));
  611 
  612     /* Add NS RRset */
  613     RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) ==
  614               ISC_R_SUCCESS);
  615     CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0,
  616                  NULL));
  617     dns_rdataset_disassociate(&rdataset);
  618 
  619     /* Add glue A RRset, if any */
  620     if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
  621         RUNTIME_CHECK(
  622             dns_rdatalist_tordataset(&rdatalist_a, &rdataset) ==
  623             ISC_R_SUCCESS);
  624         CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
  625                      0, NULL));
  626         dns_rdataset_disassociate(&rdataset);
  627     }
  628 
  629     /* Add glue AAAA RRset, if any */
  630     if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
  631         RUNTIME_CHECK(
  632             dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset) ==
  633             ISC_R_SUCCESS);
  634         CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
  635                      0, NULL));
  636         dns_rdataset_disassociate(&rdataset);
  637     }
  638 
  639     dns_db_closeversion(db, &dbversion, true);
  640     dns_zone_setdb(zone, db);
  641 
  642     result = ISC_R_SUCCESS;
  643 
  644 cleanup:
  645     if (dns_rdataset_isassociated(&rdataset)) {
  646         dns_rdataset_disassociate(&rdataset);
  647     }
  648     if (apexnode != NULL) {
  649         dns_db_detachnode(db, &apexnode);
  650     }
  651     if (dbversion != NULL) {
  652         dns_db_closeversion(db, &dbversion, false);
  653     }
  654     if (db != NULL) {
  655         dns_db_detach(&db);
  656     }
  657     for (i = 0; rdatalists[i] != NULL; i++) {
  658         while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
  659             ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
  660             dns_rdata_toregion(rdata, &region);
  661             isc_mem_put(mctx, rdata,
  662                     sizeof(*rdata) + region.length);
  663         }
  664     }
  665 
  666     INSIST(dbversion == NULL);
  667 
  668     return (result);
  669 }
  670 
  671 /*%
  672  * Convert a config file zone type into a server zone type.
  673  */
  674 static inline dns_zonetype_t
  675 zonetype_fromconfig(const cfg_obj_t *map) {
  676     const cfg_obj_t *obj = NULL;
  677     isc_result_t result;
  678 
  679     result = cfg_map_get(map, "type", &obj);
  680     INSIST(result == ISC_R_SUCCESS && obj != NULL);
  681     return (named_config_getzonetype(obj));
  682 }
  683 
  684 /*%
  685  * Helper function for strtoargv().  Pardon the gratuitous recursion.
  686  */
  687 static isc_result_t
  688 strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp,
  689          unsigned int n) {
  690     isc_result_t result;
  691 
  692     /* Discard leading whitespace. */
  693     while (*s == ' ' || *s == '\t') {
  694         s++;
  695     }
  696 
  697     if (*s == '\0') {
  698         /* We have reached the end of the string. */
  699         *argcp = n;
  700         *argvp = isc_mem_get(mctx, n * sizeof(char *));
  701     } else {
  702         char *p = s;
  703         while (*p != ' ' && *p != '\t' && *p != '\0') {
  704             p++;
  705         }
  706         if (*p != '\0') {
  707             *p++ = '\0';
  708         }
  709 
  710         result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
  711         if (result != ISC_R_SUCCESS) {
  712             return (result);
  713         }
  714         (*argvp)[n] = s;
  715     }
  716     return (ISC_R_SUCCESS);
  717 }
  718 
  719 /*%
  720  * Tokenize the string "s" into whitespace-separated words,
  721  * return the number of words in '*argcp' and an array
  722  * of pointers to the words in '*argvp'.  The caller
  723  * must free the array using isc_mem_put().  The string
  724  * is modified in-place.
  725  */
  726 static isc_result_t
  727 strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
  728     return (strtoargvsub(mctx, s, argcp, argvp, 0));
  729 }
  730 
  731 static void
  732 checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
  733        const cfg_obj_t **objp) {
  734     isc_result_t result;
  735 
  736     switch (ztype) {
  737     case dns_zone_slave:
  738     case dns_zone_mirror:
  739         result = named_checknames_get(maps, "secondary", objp);
  740         if (result != ISC_R_SUCCESS) {
  741             result = named_checknames_get(maps, "slave", objp);
  742         }
  743         break;
  744     case dns_zone_master:
  745         result = named_checknames_get(maps, "primary", objp);
  746         if (result != ISC_R_SUCCESS) {
  747             result = named_checknames_get(maps, "master", objp);
  748         }
  749         break;
  750     default:
  751         INSIST(0);
  752         ISC_UNREACHABLE();
  753     }
  754 
  755     INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
  756 }
  757 
  758 /*
  759  * Callback to see if a non-recursive query coming from 'srcaddr' to
  760  * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
  761  * delivered to 'myview'.
  762  *
  763  * We run this unlocked as both the view list and the interface list
  764  * are updated when the appropriate task has exclusivity.
  765  */
  766 static bool
  767 isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr,
  768        const isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, void *arg) {
  769     ns_interfacemgr_t *interfacemgr = (ns_interfacemgr_t *)arg;
  770     dns_aclenv_t *env = ns_interfacemgr_getaclenv(interfacemgr);
  771     dns_view_t *view;
  772     dns_tsigkey_t *key = NULL;
  773     isc_netaddr_t netsrc;
  774     isc_netaddr_t netdst;
  775 
  776     if (interfacemgr == NULL) {
  777         return (true);
  778     }
  779 
  780     if (!ns_interfacemgr_listeningon(interfacemgr, dstaddr)) {
  781         return (false);
  782     }
  783 
  784     isc_netaddr_fromsockaddr(&netsrc, srcaddr);
  785     isc_netaddr_fromsockaddr(&netdst, dstaddr);
  786 
  787     for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL;
  788          view = ISC_LIST_NEXT(view, link))
  789     {
  790         const dns_name_t *tsig = NULL;
  791 
  792         if (view->matchrecursiveonly) {
  793             continue;
  794         }
  795 
  796         if (rdclass != view->rdclass) {
  797             continue;
  798         }
  799 
  800         if (mykey != NULL) {
  801             bool match;
  802             isc_result_t result;
  803 
  804             result = dns_view_gettsig(view, &mykey->name, &key);
  805             if (result != ISC_R_SUCCESS) {
  806                 continue;
  807             }
  808             match = dst_key_compare(mykey->key, key->key);
  809             dns_tsigkey_detach(&key);
  810             if (!match) {
  811                 continue;
  812             }
  813             tsig = dns_tsigkey_identity(mykey);
  814         }
  815 
  816         if (dns_acl_allowed(&netsrc, tsig, view->matchclients, env) &&
  817             dns_acl_allowed(&netdst, tsig, view->matchdestinations,
  818                     env))
  819         {
  820             break;
  821         }
  822     }
  823     return (view == myview);
  824 }
  825 
  826 /*%
  827  * For mirror zones, change "notify yes;" to "notify explicit;", informing the
  828  * user only if "notify" was explicitly configured rather than inherited from
  829  * default configuration.
  830  */
  831 static dns_notifytype_t
  832 process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype,
  833            const char *zname, const cfg_obj_t **maps) {
  834     const cfg_obj_t *obj = NULL;
  835 
  836     /*
  837      * Return the original setting if this is not a mirror zone or if the
  838      * zone is configured with something else than "notify yes;".
  839      */
  840     if (ztype != dns_zone_mirror || ntype != dns_notifytype_yes) {
  841         return (ntype);
  842     }
  843 
  844     /*
  845      * Only log a message if "notify" was set in the configuration
  846      * hierarchy supplied in 'maps'.
  847      */
  848     if (named_config_get(maps, "notify", &obj) == ISC_R_SUCCESS) {
  849         cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO,
  850                 "'notify explicit;' will be used for mirror zone "
  851                 "'%s'",
  852                 zname);
  853     }
  854 
  855     return (dns_notifytype_explicit);
  856 }
  857 
  858 isc_result_t
  859 named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
  860              const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
  861              dns_kasplist_t *kasplist, dns_zone_t *zone,
  862              dns_zone_t *raw) {
  863     isc_result_t result;
  864     const char *zname;
  865     dns_rdataclass_t zclass;
  866     dns_rdataclass_t vclass;
  867     const cfg_obj_t *maps[5];
  868     const cfg_obj_t *nodefault[4];
  869     const cfg_obj_t *zoptions = NULL;
  870     const cfg_obj_t *options = NULL;
  871     const cfg_obj_t *obj;
  872     const char *filename = NULL;
  873     const char *kaspname = NULL;
  874     const char *dupcheck;
  875     dns_notifytype_t notifytype = dns_notifytype_yes;
  876     uint32_t count;
  877     unsigned int dbargc;
  878     char **dbargv;
  879     static char default_dbtype[] = "rbt";
  880     static char dlz_dbtype[] = "dlz";
  881     char *cpval = default_dbtype;
  882     isc_mem_t *mctx = dns_zone_getmctx(zone);
  883     dns_dialuptype_t dialup = dns_dialuptype_no;
  884     dns_zonetype_t ztype;
  885     int i;
  886     int32_t journal_size;
  887     bool multi;
  888     bool alt;
  889     dns_view_t *view = NULL;
  890     dns_kasp_t *kasp = NULL;
  891     bool check = false, fail = false;
  892     bool warn = false, ignore = false;
  893     bool ixfrdiff;
  894     dns_masterformat_t masterformat;
  895     const dns_master_style_t *masterstyle = &dns_master_style_default;
  896     isc_stats_t *zoneqrystats;
  897     dns_stats_t *rcvquerystats;
  898     dns_stats_t *dnssecsignstats;
  899     dns_zonestat_level_t statlevel = dns_zonestat_none;
  900     int seconds;
  901     dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
  902     isc_dscp_t dscp;
  903 
  904     i = 0;
  905     if (zconfig != NULL) {
  906         zoptions = cfg_tuple_get(zconfig, "options");
  907         nodefault[i] = maps[i] = zoptions;
  908         i++;
  909     }
  910     if (vconfig != NULL) {
  911         nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options");
  912         i++;
  913     }
  914     if (config != NULL) {
  915         (void)cfg_map_get(config, "options", &options);
  916         if (options != NULL) {
  917             nodefault[i] = maps[i] = options;
  918             i++;
  919         }
  920     }
  921     nodefault[i] = NULL;
  922     maps[i++] = named_g_defaults;
  923     maps[i] = NULL;
  924 
  925     if (vconfig != NULL) {
  926         RETERR(named_config_getclass(cfg_tuple_get(vconfig, "class"),
  927                          dns_rdataclass_in, &vclass));
  928     } else {
  929         vclass = dns_rdataclass_in;
  930     }
  931 
  932     /*
  933      * Configure values common to all zone types.
  934      */
  935 
  936     zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
  937 
  938     RETERR(named_config_getclass(cfg_tuple_get(zconfig, "class"), vclass,
  939                      &zclass));
  940     dns_zone_setclass(zone, zclass);
  941     if (raw != NULL) {
  942         dns_zone_setclass(raw, zclass);
  943     }
  944 
  945     ztype = zonetype_fromconfig(zoptions);
  946     if (raw != NULL) {
  947         dns_zone_settype(raw, ztype);
  948         dns_zone_settype(zone, dns_zone_master);
  949     } else {
  950         dns_zone_settype(zone, ztype);
  951     }
  952 
  953     obj = NULL;
  954     result = cfg_map_get(zoptions, "database", &obj);
  955     if (result == ISC_R_SUCCESS) {
  956         cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
  957     }
  958     if (cpval == NULL) {
  959         return (ISC_R_NOMEMORY);
  960     }
  961 
  962     obj = NULL;
  963     result = cfg_map_get(zoptions, "dlz", &obj);
  964     if (result == ISC_R_SUCCESS) {
  965         const char *dlzname = cfg_obj_asstring(obj);
  966         size_t len;
  967 
  968         if (cpval != default_dbtype) {
  969             isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
  970                       NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
  971                       "zone '%s': both 'database' and 'dlz' "
  972                       "specified",
  973                       zname);
  974             return (ISC_R_FAILURE);
  975         }
  976 
  977         len = strlen(dlzname) + 5;
  978         cpval = isc_mem_allocate(mctx, len);
  979         snprintf(cpval, len, "dlz %s", dlzname);
  980     }
  981 
  982     result = strtoargv(mctx, cpval, &dbargc, &dbargv);
  983     if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
  984         isc_mem_free(mctx, cpval);
  985         return (result);
  986     }
  987 
  988     /*
  989      * ANSI C is strange here.  There is no logical reason why (char **)
  990      * cannot be promoted automatically to (const char * const *) by the
  991      * compiler w/o generating a warning.
  992      */
  993     dns_zone_setdbtype(zone, dbargc, (const char *const *)dbargv);
  994     isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
  995     if (cpval != default_dbtype && cpval != dlz_dbtype) {
  996         isc_mem_free(mctx, cpval);
  997     }
  998 
  999     obj = NULL;
 1000     result = cfg_map_get(zoptions, "file", &obj);
 1001     if (result == ISC_R_SUCCESS) {
 1002         filename = cfg_obj_asstring(obj);
 1003     }
 1004 
 1005     /*
 1006      * Unless we're using some alternative database, a master zone
 1007      * will be needing a master file.
 1008      */
 1009     if (ztype == dns_zone_master && cpval == default_dbtype &&
 1010         filename == NULL) {
 1011         isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
 1012                   NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
 1013                   "zone '%s': 'file' not specified", zname);
 1014         return (ISC_R_FAILURE);
 1015     }
 1016 
 1017     if (ztype == dns_zone_slave || ztype == dns_zone_mirror) {
 1018         masterformat = dns_masterformat_raw;
 1019     } else {
 1020         masterformat = dns_masterformat_text;
 1021     }
 1022     obj = NULL;
 1023     result = named_config_get(maps, "masterfile-format", &obj);
 1024     if (result == ISC_R_SUCCESS) {
 1025         const char *masterformatstr = cfg_obj_asstring(obj);
 1026 
 1027         if (strcasecmp(masterformatstr, "text") == 0) {
 1028             masterformat = dns_masterformat_text;
 1029         } else if (strcasecmp(masterformatstr, "raw") == 0) {
 1030             masterformat = dns_masterformat_raw;
 1031         } else if (strcasecmp(masterformatstr, "map") == 0) {
 1032             masterformat = dns_masterformat_map;
 1033         } else {
 1034             INSIST(0);
 1035             ISC_UNREACHABLE();
 1036         }
 1037     }
 1038 
 1039     obj = NULL;
 1040     result = named_config_get(maps, "masterfile-style", &obj);
 1041     if (result == ISC_R_SUCCESS) {
 1042         const char *masterstylestr = cfg_obj_asstring(obj);
 1043 
 1044         if (masterformat != dns_masterformat_text) {
 1045             cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
 1046                     "zone '%s': 'masterfile-style' "
 1047                     "can only be used with "
 1048                     "'masterfile-format text'",
 1049                     zname);
 1050             return (ISC_R_FAILURE);
 1051         }
 1052 
 1053         if (strcasecmp(masterstylestr, "full") == 0) {
 1054             masterstyle = &dns_master_style_full;
 1055         } else if (strcasecmp(masterstylestr, "relative") == 0) {
 1056             masterstyle = &dns_master_style_default;
 1057         } else {
 1058             INSIST(0);
 1059             ISC_UNREACHABLE();
 1060         }
 1061     }
 1062 
 1063     obj = NULL;
 1064     result = named_config_get(maps, "max-zone-ttl", &obj);
 1065     if (result == ISC_R_SUCCESS && masterformat == dns_masterformat_map) {
 1066         isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
 1067                   NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
 1068                   "zone '%s': 'max-zone-ttl' is not compatible "
 1069                   "with 'masterfile-format map'",
 1070                   zname);
 1071         return (ISC_R_FAILURE);
 1072     } else if (result == ISC_R_SUCCESS) {
 1073         dns_ttl_t maxttl = 0; /* unlimited */
 1074 
 1075         if (cfg_obj_isduration(obj)) {
 1076             maxttl = cfg_obj_asduration(obj);
 1077         }
 1078         dns_zone_setmaxttl(zone, maxttl);
 1079         if (raw != NULL) {
 1080             dns_zone_setmaxttl(raw, maxttl);
 1081         }
 1082     }
 1083 
 1084     obj = NULL;
 1085     result = named_config_get(maps, "max-records", &obj);
 1086     INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1087     dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj));
 1088     if (zone != mayberaw) {
 1089         dns_zone_setmaxrecords(zone, 0);
 1090     }
 1091 
 1092     if (raw != NULL && filename != NULL) {
 1093 #define SIGNED ".signed"
 1094         size_t signedlen = strlen(filename) + sizeof(SIGNED);
 1095         char *signedname;
 1096 
 1097         RETERR(dns_zone_setfile(raw, filename, masterformat,
 1098                     masterstyle));
 1099         signedname = isc_mem_get(mctx, signedlen);
 1100 
 1101         (void)snprintf(signedname, signedlen, "%s" SIGNED, filename);
 1102         result = dns_zone_setfile(zone, signedname,
 1103                       dns_masterformat_raw, NULL);
 1104         isc_mem_put(mctx, signedname, signedlen);
 1105         if (result != ISC_R_SUCCESS) {
 1106             return (result);
 1107         }
 1108     } else {
 1109         RETERR(dns_zone_setfile(zone, filename, masterformat,
 1110                     masterstyle));
 1111     }
 1112 
 1113     obj = NULL;
 1114     result = cfg_map_get(zoptions, "journal", &obj);
 1115     if (result == ISC_R_SUCCESS) {
 1116         RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj)));
 1117     }
 1118 
 1119     /*
 1120      * Notify messages are processed by the raw zone if it exists.
 1121      */
 1122     if (ztype == dns_zone_slave || ztype == dns_zone_mirror) {
 1123         RETERR(configure_zone_acl(
 1124             zconfig, vconfig, config, allow_notify, ac, mayberaw,
 1125             dns_zone_setnotifyacl, dns_zone_clearnotifyacl));
 1126     }
 1127 
 1128     /*
 1129      * XXXAG This probably does not make sense for stubs.
 1130      */
 1131     RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query, ac,
 1132                   zone, dns_zone_setqueryacl,
 1133                   dns_zone_clearqueryacl));
 1134 
 1135     RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac,
 1136                   zone, dns_zone_setqueryonacl,
 1137                   dns_zone_clearqueryonacl));
 1138 
 1139     obj = NULL;
 1140     result = named_config_get(maps, "dialup", &obj);
 1141     INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1142     if (cfg_obj_isboolean(obj)) {
 1143         if (cfg_obj_asboolean(obj)) {
 1144             dialup = dns_dialuptype_yes;
 1145         } else {
 1146             dialup = dns_dialuptype_no;
 1147         }
 1148     } else {
 1149         const char *dialupstr = cfg_obj_asstring(obj);
 1150         if (strcasecmp(dialupstr, "notify") == 0) {
 1151             dialup = dns_dialuptype_notify;
 1152         } else if (strcasecmp(dialupstr, "notify-passive") == 0) {
 1153             dialup = dns_dialuptype_notifypassive;
 1154         } else if (strcasecmp(dialupstr, "refresh") == 0) {
 1155             dialup = dns_dialuptype_refresh;
 1156         } else if (strcasecmp(dialupstr, "passive") == 0) {
 1157             dialup = dns_dialuptype_passive;
 1158         } else {
 1159             INSIST(0);
 1160             ISC_UNREACHABLE();
 1161         }
 1162     }
 1163     if (raw != NULL) {
 1164         dns_zone_setdialup(raw, dialup);
 1165     }
 1166     dns_zone_setdialup(zone, dialup);
 1167 
 1168     obj = NULL;
 1169     result = named_config_get(maps, "zone-statistics", &obj);
 1170     INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1171     if (cfg_obj_isboolean(obj)) {
 1172         if (cfg_obj_asboolean(obj)) {
 1173             statlevel = dns_zonestat_full;
 1174         } else {
 1175             statlevel = dns_zonestat_none;
 1176         }
 1177     } else {
 1178         const char *levelstr = cfg_obj_asstring(obj);
 1179         if (strcasecmp(levelstr, "full") == 0) {
 1180             statlevel = dns_zonestat_full;
 1181         } else if (strcasecmp(levelstr, "terse") == 0) {
 1182             statlevel = dns_zonestat_terse;
 1183         } else if (strcasecmp(levelstr, "none") == 0) {
 1184             statlevel = dns_zonestat_none;
 1185         } else {
 1186             INSIST(0);
 1187             ISC_UNREACHABLE();
 1188         }
 1189     }
 1190     dns_zone_setstatlevel(zone, statlevel);
 1191 
 1192     zoneqrystats = NULL;
 1193     rcvquerystats = NULL;
 1194     dnssecsignstats = NULL;
 1195     if (statlevel == dns_zonestat_full) {
 1196         RETERR(isc_stats_create(mctx, &zoneqrystats,
 1197                     ns_statscounter_max));
 1198         RETERR(dns_rdatatypestats_create(mctx, &rcvquerystats));
 1199         RETERR(dns_dnssecsignstats_create(mctx, &dnssecsignstats));
 1200     }
 1201     dns_zone_setrequeststats(zone, zoneqrystats);
 1202     dns_zone_setrcvquerystats(zone, rcvquerystats);
 1203     dns_zone_setdnssecsignstats(zone, dnssecsignstats);
 1204 
 1205     if (zoneqrystats != NULL) {
 1206         isc_stats_detach(&zoneqrystats);
 1207     }
 1208 
 1209     if (rcvquerystats != NULL) {
 1210         dns_stats_detach(&rcvquerystats);
 1211     }
 1212 
 1213     if (dnssecsignstats != NULL) {
 1214         dns_stats_detach(&dnssecsignstats);
 1215     }
 1216 
 1217     /*
 1218      * Configure master functionality.  This applies
 1219      * to primary masters (type "master") and slaves
 1220      * acting as masters (type "slave"), but not to stubs.
 1221      */
 1222     if (ztype != dns_zone_stub && ztype != dns_zone_staticstub &&
 1223         ztype != dns_zone_redirect)
 1224     {
 1225         obj = NULL;
 1226         result = named_config_get(maps, "dnssec-policy", &obj);
 1227         if (result == ISC_R_SUCCESS) {
 1228             kaspname = cfg_obj_asstring(obj);
 1229             if (strcmp(kaspname, "none") != 0) {
 1230                 result = dns_kasplist_find(kasplist, kaspname,
 1231                                &kasp);
 1232                 if (result != ISC_R_SUCCESS) {
 1233                     cfg_obj_log(obj, named_g_lctx,
 1234                             ISC_LOG_ERROR,
 1235                             "'dnssec-policy '%s' not "
 1236                             "found ",
 1237                             kaspname);
 1238                     RETERR(result);
 1239                 }
 1240                 dns_zone_setkasp(zone, kasp);
 1241             }
 1242         }
 1243 
 1244         obj = NULL;
 1245         result = named_config_get(maps, "notify", &obj);
 1246         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1247         if (cfg_obj_isboolean(obj)) {
 1248             if (cfg_obj_asboolean(obj)) {
 1249                 notifytype = dns_notifytype_yes;
 1250             } else {
 1251                 notifytype = dns_notifytype_no;
 1252             }
 1253         } else {
 1254             const char *notifystr = cfg_obj_asstring(obj);
 1255             if (strcasecmp(notifystr, "explicit") == 0) {
 1256                 notifytype = dns_notifytype_explicit;
 1257             } else if (strcasecmp(notifystr, "master-only") == 0) {
 1258                 notifytype = dns_notifytype_masteronly;
 1259             } else {
 1260                 INSIST(0);
 1261                 ISC_UNREACHABLE();
 1262             }
 1263         }
 1264         notifytype = process_notifytype(notifytype, ztype, zname,
 1265                         nodefault);
 1266         if (raw != NULL) {
 1267             dns_zone_setnotifytype(raw, dns_notifytype_no);
 1268         }
 1269         dns_zone_setnotifytype(zone, notifytype);
 1270 
 1271         obj = NULL;
 1272         result = named_config_get(maps, "also-notify", &obj);
 1273         if (result == ISC_R_SUCCESS &&
 1274             (notifytype == dns_notifytype_yes ||
 1275              notifytype == dns_notifytype_explicit ||
 1276              (notifytype == dns_notifytype_masteronly &&
 1277               ztype == dns_zone_master)))
 1278         {
 1279             dns_ipkeylist_t ipkl;
 1280             dns_ipkeylist_init(&ipkl);
 1281 
 1282             RETERR(named_config_getipandkeylist(config, obj, mctx,
 1283                                 &ipkl));
 1284             result = dns_zone_setalsonotifydscpkeys(
 1285                 zone, ipkl.addrs, ipkl.dscps, ipkl.keys,
 1286                 ipkl.count);
 1287             dns_ipkeylist_clear(mctx, &ipkl);
 1288             RETERR(result);
 1289         } else {
 1290             RETERR(dns_zone_setalsonotify(zone, NULL, 0));
 1291         }
 1292 
 1293         obj = NULL;
 1294         result = named_config_get(maps, "notify-source", &obj);
 1295         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1296         RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
 1297         dscp = cfg_obj_getdscp(obj);
 1298         if (dscp == -1) {
 1299             dscp = named_g_dscp;
 1300         }
 1301         RETERR(dns_zone_setnotifysrc4dscp(zone, dscp));
 1302         named_add_reserved_dispatch(named_g_server,
 1303                         cfg_obj_assockaddr(obj));
 1304 
 1305         obj = NULL;
 1306         result = named_config_get(maps, "notify-source-v6", &obj);
 1307         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1308         RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
 1309         dscp = cfg_obj_getdscp(obj);
 1310         if (dscp == -1) {
 1311             dscp = named_g_dscp;
 1312         }
 1313         RETERR(dns_zone_setnotifysrc6dscp(zone, dscp));
 1314         named_add_reserved_dispatch(named_g_server,
 1315                         cfg_obj_assockaddr(obj));
 1316 
 1317         obj = NULL;
 1318         result = named_config_get(maps, "notify-to-soa", &obj);
 1319         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1320         dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
 1321                    cfg_obj_asboolean(obj));
 1322 
 1323         dns_zone_setisself(zone, isself, named_g_server->interfacemgr);
 1324 
 1325         RETERR(configure_zone_acl(
 1326             zconfig, vconfig, config, allow_transfer, ac, zone,
 1327             dns_zone_setxfracl, dns_zone_clearxfracl));
 1328 
 1329         obj = NULL;
 1330         result = named_config_get(maps, "max-transfer-time-out", &obj);
 1331         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1332         dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
 1333 
 1334         obj = NULL;
 1335         result = named_config_get(maps, "max-transfer-idle-out", &obj);
 1336         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1337         dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
 1338 
 1339         obj = NULL;
 1340         result = named_config_get(maps, "max-journal-size", &obj);
 1341         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1342         if (raw != NULL) {
 1343             dns_zone_setjournalsize(raw, -1);
 1344         }
 1345         dns_zone_setjournalsize(zone, -1);
 1346         if (cfg_obj_isstring(obj)) {
 1347             const char *str = cfg_obj_asstring(obj);
 1348             if (strcasecmp(str, "unlimited") == 0) {
 1349                 journal_size = DNS_JOURNAL_SIZE_MAX;
 1350             } else {
 1351                 INSIST(strcasecmp(str, "default") == 0);
 1352                 journal_size = -1;
 1353             }
 1354         } else {
 1355             isc_resourcevalue_t value;
 1356             value = cfg_obj_asuint64(obj);
 1357             if (value > DNS_JOURNAL_SIZE_MAX) {
 1358                 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
 1359                         "'max-journal-size "
 1360                         "%" PRId64 "' "
 1361                         "is too large",
 1362                         value);
 1363                 RETERR(ISC_R_RANGE);
 1364             }
 1365             journal_size = (uint32_t)value;
 1366         }
 1367         if (raw != NULL) {
 1368             dns_zone_setjournalsize(raw, journal_size);
 1369         }
 1370         dns_zone_setjournalsize(zone, journal_size);
 1371 
 1372         obj = NULL;
 1373         result = named_config_get(maps, "ixfr-from-differences", &obj);
 1374         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1375         if (cfg_obj_isboolean(obj)) {
 1376             ixfrdiff = cfg_obj_asboolean(obj);
 1377         } else if ((strcasecmp(cfg_obj_asstring(obj), "primary") == 0 ||
 1378                 strcasecmp(cfg_obj_asstring(obj), "master") == 0) &&
 1379                ztype == dns_zone_master)
 1380         {
 1381             ixfrdiff = true;
 1382         } else if ((strcasecmp(cfg_obj_asstring(obj), "secondary") ==
 1383                     0 ||
 1384                 strcasecmp(cfg_obj_asstring(obj), "slave") == 0) &&
 1385                ztype == dns_zone_slave)
 1386         {
 1387             ixfrdiff = true;
 1388         } else {
 1389             ixfrdiff = false;
 1390         }
 1391         if (raw != NULL) {
 1392             dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS,
 1393                        true);
 1394             dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
 1395                        false);
 1396         } else {
 1397             dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
 1398                        ixfrdiff);
 1399         }
 1400 
 1401         obj = NULL;
 1402         result = named_config_get(maps, "request-expire", &obj);
 1403         INSIST(result == ISC_R_SUCCESS);
 1404         dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj));
 1405 
 1406         obj = NULL;
 1407         result = named_config_get(maps, "request-ixfr", &obj);
 1408         INSIST(result == ISC_R_SUCCESS);
 1409         dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj));
 1410 
 1411         obj = NULL;
 1412         checknames(ztype, maps, &obj);
 1413         INSIST(obj != NULL);
 1414         if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
 1415             fail = false;
 1416             check = true;
 1417         } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
 1418             fail = check = true;
 1419         } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
 1420             fail = check = false;
 1421         } else {
 1422             INSIST(0);
 1423             ISC_UNREACHABLE();
 1424         }
 1425         if (raw != NULL) {
 1426             dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check);
 1427             dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL,
 1428                        fail);
 1429             dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, false);
 1430             dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
 1431                        false);
 1432         } else {
 1433             dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
 1434             dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
 1435                        fail);
 1436         }
 1437 
 1438         obj = NULL;
 1439         result = named_config_get(maps, "notify-delay", &obj);
 1440         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1441         dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
 1442 
 1443         obj = NULL;
 1444         result = named_config_get(maps, "check-sibling", &obj);
 1445         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1446         dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
 1447                    cfg_obj_asboolean(obj));
 1448 
 1449         obj = NULL;
 1450         result = named_config_get(maps, "check-spf", &obj);
 1451         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1452         if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
 1453             check = true;
 1454         } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
 1455             check = false;
 1456         } else {
 1457             INSIST(0);
 1458             ISC_UNREACHABLE();
 1459         }
 1460         dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
 1461 
 1462         obj = NULL;
 1463         result = named_config_get(maps, "zero-no-soa-ttl", &obj);
 1464         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1465         dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
 1466 
 1467         obj = NULL;
 1468         result = named_config_get(maps, "nsec3-test-zone", &obj);
 1469         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1470         dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
 1471                    cfg_obj_asboolean(obj));
 1472     } else if (ztype == dns_zone_redirect) {
 1473         dns_zone_setnotifytype(zone, dns_notifytype_no);
 1474 
 1475         obj = NULL;
 1476         result = named_config_get(maps, "max-journal-size", &obj);
 1477         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1478         dns_zone_setjournalsize(zone, -1);
 1479         if (cfg_obj_isstring(obj)) {
 1480             const char *str = cfg_obj_asstring(obj);
 1481             if (strcasecmp(str, "unlimited") == 0) {
 1482                 journal_size = DNS_JOURNAL_SIZE_MAX;
 1483             } else {
 1484                 INSIST(strcasecmp(str, "default") == 0);
 1485                 journal_size = -1;
 1486             }
 1487         } else {
 1488             isc_resourcevalue_t value;
 1489             value = cfg_obj_asuint64(obj);
 1490             if (value > DNS_JOURNAL_SIZE_MAX) {
 1491                 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
 1492                         "'max-journal-size "
 1493                         "%" PRId64 "' "
 1494                         "is too large",
 1495                         value);
 1496                 RETERR(ISC_R_RANGE);
 1497             }
 1498             journal_size = (uint32_t)value;
 1499         }
 1500         dns_zone_setjournalsize(zone, journal_size);
 1501     }
 1502 
 1503     /*
 1504      * Configure update-related options.  These apply to
 1505      * primary masters only.
 1506      */
 1507     if (ztype == dns_zone_master) {
 1508         dns_acl_t *updateacl;
 1509 
 1510         RETERR(configure_zone_acl(
 1511             zconfig, vconfig, config, allow_update, ac, mayberaw,
 1512             dns_zone_setupdateacl, dns_zone_clearupdateacl));
 1513 
 1514         updateacl = dns_zone_getupdateacl(mayberaw);
 1515         if (updateacl != NULL && dns_acl_isinsecure(updateacl)) {
 1516             isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
 1517                       NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
 1518                       "zone '%s' allows unsigned updates "
 1519                       "from remote hosts, which is insecure",
 1520                       zname);
 1521         }
 1522 
 1523         RETERR(configure_zone_ssutable(zoptions, mayberaw, zname));
 1524     }
 1525 
 1526     if (ztype == dns_zone_master || raw != NULL) {
 1527         const cfg_obj_t *validity, *resign;
 1528         bool allow = false, maint = false;
 1529         bool sigvalinsecs;
 1530 
 1531         if (kasp) {
 1532             seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp);
 1533         } else {
 1534             obj = NULL;
 1535             result = named_config_get(maps, "dnskey-sig-validity",
 1536                           &obj);
 1537             INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1538             seconds = cfg_obj_asuint32(obj) * 86400;
 1539         }
 1540         dns_zone_setkeyvalidityinterval(zone, seconds);
 1541 
 1542         if (kasp) {
 1543             seconds = (uint32_t)dns_kasp_sigvalidity(kasp);
 1544             dns_zone_setsigvalidityinterval(zone, seconds);
 1545             seconds = (uint32_t)dns_kasp_sigrefresh(kasp);
 1546             dns_zone_setsigresigninginterval(zone, seconds);
 1547         } else {
 1548             obj = NULL;
 1549             result = named_config_get(maps, "sig-validity-interval",
 1550                           &obj);
 1551             INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1552 
 1553             sigvalinsecs = ns_server_getoption(
 1554                 named_g_server->sctx, NS_SERVER_SIGVALINSECS);
 1555             validity = cfg_tuple_get(obj, "validity");
 1556             seconds = cfg_obj_asuint32(validity);
 1557             if (!sigvalinsecs) {
 1558                 seconds *= 86400;
 1559             }
 1560             dns_zone_setsigvalidityinterval(zone, seconds);
 1561 
 1562             resign = cfg_tuple_get(obj, "re-sign");
 1563             if (cfg_obj_isvoid(resign)) {
 1564                 seconds /= 4;
 1565             } else if (!sigvalinsecs) {
 1566                 uint32_t r = cfg_obj_asuint32(resign);
 1567                 if (seconds > 7 * 86400) {
 1568                     seconds = r * 86400;
 1569                 } else {
 1570                     seconds = r * 3600;
 1571                 }
 1572             } else {
 1573                 seconds = cfg_obj_asuint32(resign);
 1574             }
 1575             dns_zone_setsigresigninginterval(zone, seconds);
 1576         }
 1577 
 1578         obj = NULL;
 1579         result = named_config_get(maps, "key-directory", &obj);
 1580         if (result == ISC_R_SUCCESS) {
 1581             filename = cfg_obj_asstring(obj);
 1582             RETERR(dns_zone_setkeydirectory(zone, filename));
 1583         }
 1584 
 1585         obj = NULL;
 1586         result = named_config_get(maps, "sig-signing-signatures", &obj);
 1587         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1588         dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
 1589 
 1590         obj = NULL;
 1591         result = named_config_get(maps, "sig-signing-nodes", &obj);
 1592         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1593         dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
 1594 
 1595         obj = NULL;
 1596         result = named_config_get(maps, "sig-signing-type", &obj);
 1597         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1598         dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
 1599 
 1600         obj = NULL;
 1601         result = named_config_get(maps, "update-check-ksk", &obj);
 1602         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1603         dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
 1604                    cfg_obj_asboolean(obj));
 1605         /*
 1606          * This setting will be ignored if dnssec-policy is used.
 1607          * named-checkconf will error if both are configured.
 1608          */
 1609 
 1610         obj = NULL;
 1611         result = named_config_get(maps, "dnssec-dnskey-kskonly", &obj);
 1612         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1613         dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
 1614                    cfg_obj_asboolean(obj));
 1615         /*
 1616          * This setting will be ignored if dnssec-policy is used.
 1617          * named-checkconf will error if both are configured.
 1618          */
 1619 
 1620         obj = NULL;
 1621         result = named_config_get(maps, "dnssec-loadkeys-interval",
 1622                       &obj);
 1623         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1624         RETERR(dns_zone_setrefreshkeyinterval(zone,
 1625                               cfg_obj_asuint32(obj)));
 1626 
 1627         obj = NULL;
 1628         result = cfg_map_get(zoptions, "auto-dnssec", &obj);
 1629         if (dns_zone_getkasp(zone) != NULL) {
 1630             dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true);
 1631             dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, true);
 1632             dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true);
 1633         } else if (result == ISC_R_SUCCESS) {
 1634             const char *arg = cfg_obj_asstring(obj);
 1635             if (strcasecmp(arg, "allow") == 0) {
 1636                 allow = true;
 1637             } else if (strcasecmp(arg, "maintain") == 0) {
 1638                 allow = maint = true;
 1639             } else if (strcasecmp(arg, "off") == 0) {
 1640                 /* Default */
 1641             } else {
 1642                 INSIST(0);
 1643                 ISC_UNREACHABLE();
 1644             }
 1645             dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
 1646             dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
 1647             dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
 1648         }
 1649     }
 1650 
 1651     if (ztype == dns_zone_slave || ztype == dns_zone_mirror) {
 1652         RETERR(configure_zone_acl(zconfig, vconfig, config,
 1653                       allow_update_forwarding, ac, mayberaw,
 1654                       dns_zone_setforwardacl,
 1655                       dns_zone_clearforwardacl));
 1656     }
 1657 
 1658     /*%
 1659      * Primary master functionality.
 1660      */
 1661     if (ztype == dns_zone_master) {
 1662         obj = NULL;
 1663         result = named_config_get(maps, "check-wildcard", &obj);
 1664         if (result == ISC_R_SUCCESS) {
 1665             check = cfg_obj_asboolean(obj);
 1666         } else {
 1667             check = false;
 1668         }
 1669         dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check);
 1670 
 1671         /*
 1672          * With map files, the default is ignore duplicate
 1673          * records.  With other master formats, the default is
 1674          * taken from the global configuration.
 1675          */
 1676         obj = NULL;
 1677         if (masterformat != dns_masterformat_map) {
 1678             result = named_config_get(maps, "check-dup-records",
 1679                           &obj);
 1680             INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1681             dupcheck = cfg_obj_asstring(obj);
 1682         } else {
 1683             result = named_config_get(nodefault,
 1684                           "check-dup-records", &obj);
 1685             if (result == ISC_R_SUCCESS) {
 1686                 dupcheck = cfg_obj_asstring(obj);
 1687             } else {
 1688                 dupcheck = "ignore";
 1689             }
 1690         }
 1691         if (strcasecmp(dupcheck, "warn") == 0) {
 1692             fail = false;
 1693             check = true;
 1694         } else if (strcasecmp(dupcheck, "fail") == 0) {
 1695             fail = check = true;
 1696         } else if (strcasecmp(dupcheck, "ignore") == 0) {
 1697             fail = check = false;
 1698         } else {
 1699             INSIST(0);
 1700             ISC_UNREACHABLE();
 1701         }
 1702         dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check);
 1703         dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
 1704 
 1705         obj = NULL;
 1706         result = named_config_get(maps, "check-mx", &obj);
 1707         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1708         if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
 1709             fail = false;
 1710             check = true;
 1711         } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
 1712             fail = check = true;
 1713         } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
 1714             fail = check = false;
 1715         } else {
 1716             INSIST(0);
 1717             ISC_UNREACHABLE();
 1718         }
 1719         dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check);
 1720         dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail);
 1721 
 1722         /*
 1723          * With map files, the default is *not* to check
 1724          * integrity.  With other master formats, the default is
 1725          * taken from the global configuration.
 1726          */
 1727         obj = NULL;
 1728         if (masterformat != dns_masterformat_map) {
 1729             result = named_config_get(maps, "check-integrity",
 1730                           &obj);
 1731             INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1732             dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
 1733                        cfg_obj_asboolean(obj));
 1734         } else {
 1735             check = false;
 1736             result = named_config_get(nodefault, "check-integrity",
 1737                           &obj);
 1738             if (result == ISC_R_SUCCESS) {
 1739                 check = cfg_obj_asboolean(obj);
 1740             }
 1741             dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
 1742                        check);
 1743         }
 1744 
 1745         obj = NULL;
 1746         result = named_config_get(maps, "check-mx-cname", &obj);
 1747         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1748         if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
 1749             warn = true;
 1750             ignore = false;
 1751         } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
 1752             warn = ignore = false;
 1753         } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
 1754             warn = ignore = true;
 1755         } else {
 1756             INSIST(0);
 1757             ISC_UNREACHABLE();
 1758         }
 1759         dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn);
 1760         dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
 1761 
 1762         obj = NULL;
 1763         result = named_config_get(maps, "check-srv-cname", &obj);
 1764         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1765         if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
 1766             warn = true;
 1767             ignore = false;
 1768         } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
 1769             warn = ignore = false;
 1770         } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
 1771             warn = ignore = true;
 1772         } else {
 1773             INSIST(0);
 1774             ISC_UNREACHABLE();
 1775         }
 1776         dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn);
 1777         dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME,
 1778                    ignore);
 1779 
 1780         obj = NULL;
 1781         result = named_config_get(maps, "dnssec-secure-to-insecure",
 1782                       &obj);
 1783         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1784         dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE,
 1785                    cfg_obj_asboolean(obj));
 1786 
 1787         obj = NULL;
 1788         result = cfg_map_get(zoptions, "dnssec-update-mode", &obj);
 1789         if (result == ISC_R_SUCCESS) {
 1790             const char *arg = cfg_obj_asstring(obj);
 1791             if (strcasecmp(arg, "no-resign") == 0) {
 1792                 dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN,
 1793                            true);
 1794             } else if (strcasecmp(arg, "maintain") == 0) {
 1795                 /* Default */
 1796             } else {
 1797                 INSIST(0);
 1798                 ISC_UNREACHABLE();
 1799             }
 1800         }
 1801 
 1802         obj = NULL;
 1803         result = named_config_get(maps, "serial-update-method", &obj);
 1804         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1805         if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) {
 1806             dns_zone_setserialupdatemethod(
 1807                 zone, dns_updatemethod_unixtime);
 1808         } else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) {
 1809             dns_zone_setserialupdatemethod(zone,
 1810                                dns_updatemethod_date);
 1811         } else {
 1812             dns_zone_setserialupdatemethod(
 1813                 zone, dns_updatemethod_increment);
 1814         }
 1815     }
 1816 
 1817     /*
 1818      * Configure slave functionality.
 1819      */
 1820     switch (ztype) {
 1821     case dns_zone_mirror:
 1822         /*
 1823          * Disable outgoing zone transfers for mirror zones unless they
 1824          * are explicitly enabled by zone configuration.
 1825          */
 1826         obj = NULL;
 1827         (void)cfg_map_get(zoptions, "allow-transfer", &obj);
 1828         if (obj == NULL) {
 1829             dns_acl_t *none;
 1830             RETERR(dns_acl_none(mctx, &none));
 1831             dns_zone_setxfracl(zone, none);
 1832             dns_acl_detach(&none);
 1833         }
 1834     /* FALLTHROUGH */
 1835     case dns_zone_slave:
 1836     case dns_zone_stub:
 1837     case dns_zone_redirect:
 1838         count = 0;
 1839         obj = NULL;
 1840         (void)cfg_map_get(zoptions, "masters", &obj);
 1841         /*
 1842          * Use the built-in master server list if one was not
 1843          * explicitly specified and this is a root zone mirror.
 1844          */
 1845         if (obj == NULL && ztype == dns_zone_mirror &&
 1846             dns_name_equal(dns_zone_getorigin(zone), dns_rootname))
 1847         {
 1848             result = named_config_getmastersdef(
 1849                 named_g_config, DEFAULT_IANA_ROOT_ZONE_MASTERS,
 1850                 &obj);
 1851             RETERR(result);
 1852         }
 1853         if (obj != NULL) {
 1854             dns_ipkeylist_t ipkl;
 1855             dns_ipkeylist_init(&ipkl);
 1856 
 1857             RETERR(named_config_getipandkeylist(config, obj, mctx,
 1858                                 &ipkl));
 1859             result = dns_zone_setmasterswithkeys(
 1860                 mayberaw, ipkl.addrs, ipkl.keys, ipkl.count);
 1861             count = ipkl.count;
 1862             dns_ipkeylist_clear(mctx, &ipkl);
 1863             RETERR(result);
 1864         } else {
 1865             result = dns_zone_setmasters(mayberaw, NULL, 0);
 1866         }
 1867         RETERR(result);
 1868 
 1869         multi = false;
 1870         if (count > 1) {
 1871             obj = NULL;
 1872             result = named_config_get(maps, "multi-master", &obj);
 1873             INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1874             multi = cfg_obj_asboolean(obj);
 1875         }
 1876         dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi);
 1877 
 1878         obj = NULL;
 1879         result = named_config_get(maps, "max-transfer-time-in", &obj);
 1880         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1881         dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60);
 1882 
 1883         obj = NULL;
 1884         result = named_config_get(maps, "max-transfer-idle-in", &obj);
 1885         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1886         dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60);
 1887 
 1888         obj = NULL;
 1889         result = named_config_get(maps, "max-refresh-time", &obj);
 1890         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1891         dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj));
 1892 
 1893         obj = NULL;
 1894         result = named_config_get(maps, "min-refresh-time", &obj);
 1895         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1896         dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj));
 1897 
 1898         obj = NULL;
 1899         result = named_config_get(maps, "max-retry-time", &obj);
 1900         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1901         dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj));
 1902 
 1903         obj = NULL;
 1904         result = named_config_get(maps, "min-retry-time", &obj);
 1905         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1906         dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj));
 1907 
 1908         obj = NULL;
 1909         result = named_config_get(maps, "transfer-source", &obj);
 1910         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1911         RETERR(dns_zone_setxfrsource4(mayberaw,
 1912                           cfg_obj_assockaddr(obj)));
 1913         dscp = cfg_obj_getdscp(obj);
 1914         if (dscp == -1) {
 1915             dscp = named_g_dscp;
 1916         }
 1917         RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp));
 1918         named_add_reserved_dispatch(named_g_server,
 1919                         cfg_obj_assockaddr(obj));
 1920 
 1921         obj = NULL;
 1922         result = named_config_get(maps, "transfer-source-v6", &obj);
 1923         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1924         RETERR(dns_zone_setxfrsource6(mayberaw,
 1925                           cfg_obj_assockaddr(obj)));
 1926         dscp = cfg_obj_getdscp(obj);
 1927         if (dscp == -1) {
 1928             dscp = named_g_dscp;
 1929         }
 1930         RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp));
 1931         named_add_reserved_dispatch(named_g_server,
 1932                         cfg_obj_assockaddr(obj));
 1933 
 1934         obj = NULL;
 1935         result = named_config_get(maps, "alt-transfer-source", &obj);
 1936         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1937         RETERR(dns_zone_setaltxfrsource4(mayberaw,
 1938                          cfg_obj_assockaddr(obj)));
 1939         dscp = cfg_obj_getdscp(obj);
 1940         if (dscp == -1) {
 1941             dscp = named_g_dscp;
 1942         }
 1943         RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp));
 1944 
 1945         obj = NULL;
 1946         result = named_config_get(maps, "alt-transfer-source-v6", &obj);
 1947         INSIST(result == ISC_R_SUCCESS && obj != NULL);
 1948         RETERR(dns_zone_setaltxfrsource6(mayberaw,
 1949                          cfg_obj_assockaddr(obj)));
 1950         dscp = cfg_obj_getdscp(obj);
 1951         if (dscp == -1) {
 1952             dscp = named_g_dscp;
 1953         }
 1954         RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp));
 1955 
 1956         obj = NULL;
 1957         (void)named_config_get(maps, "use-alt-transfer-source", &obj);
 1958         if (obj == NULL) {
 1959             /*
 1960              * Default off when views are in use otherwise
 1961              * on for BIND 8 compatibility.
 1962              */
 1963             view = dns_zone_getview(zone);
 1964             if (view != NULL && strcmp(view->name, "_default") == 0)
 1965             {
 1966                 alt = true;
 1967             } else {
 1968                 alt = false;
 1969             }
 1970         } else {
 1971             alt = cfg_obj_asboolean(obj);
 1972         }
 1973         dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt);
 1974 
 1975         obj = NULL;
 1976         (void)named_config_get(maps, "try-tcp-refresh", &obj);
 1977         dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH,
 1978                    cfg_obj_asboolean(obj));
 1979         break;
 1980 
 1981     case dns_zone_staticstub:
 1982         RETERR(configure_staticstub(zoptions, zone, zname,
 1983                         default_dbtype));
 1984         break;
 1985 
 1986     default:
 1987         break;
 1988     }
 1989 
 1990     return (ISC_R_SUCCESS);
 1991 }
 1992 
 1993 /*
 1994  * Set up a DLZ zone as writeable
 1995  */
 1996 isc_result_t
 1997 named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
 1998                    dns_rdataclass_t rdclass, dns_name_t *name) {
 1999     dns_db_t *db = NULL;
 2000     isc_time_t now;
 2001     isc_result_t result;
 2002 
 2003     TIME_NOW(&now);
 2004 
 2005     dns_zone_settype(zone, dns_zone_dlz);
 2006     result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db);
 2007     if (result != ISC_R_SUCCESS) {
 2008         return (result);
 2009     }
 2010     result = dns_zone_dlzpostload(zone, db);
 2011     dns_db_detach(&db);
 2012     return (result);
 2013 }
 2014 
 2015 bool
 2016 named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
 2017     const cfg_obj_t *zoptions = NULL;
 2018     const cfg_obj_t *obj = NULL;
 2019     const char *cfilename;
 2020     const char *zfilename;
 2021     dns_zone_t *raw = NULL;
 2022     bool has_raw;
 2023     dns_zonetype_t ztype;
 2024 
 2025     zoptions = cfg_tuple_get(zconfig, "options");
 2026 
 2027     /*
 2028      * We always reconfigure a static-stub zone for simplicity, assuming
 2029      * the amount of data to be loaded is small.
 2030      */
 2031     if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) {
 2032         dns_zone_log(zone, ISC_LOG_DEBUG(1),
 2033                  "not reusable: staticstub");
 2034         return (false);
 2035     }
 2036 
 2037     /* If there's a raw zone, use that for filename and type comparison */
 2038     dns_zone_getraw(zone, &raw);
 2039     if (raw != NULL) {
 2040         zfilename = dns_zone_getfile(raw);
 2041         ztype = dns_zone_gettype(raw);
 2042         dns_zone_detach(&raw);
 2043         has_raw = true;
 2044     } else {
 2045         zfilename = dns_zone_getfile(zone);
 2046         ztype = dns_zone_gettype(zone);
 2047         has_raw = false;
 2048     }
 2049 
 2050     obj = NULL;
 2051     (void)cfg_map_get(zoptions, "inline-signing", &obj);
 2052     if ((obj == NULL || !cfg_obj_asboolean(obj)) && has_raw) {
 2053         dns_zone_log(zone, ISC_LOG_DEBUG(1),
 2054                  "not reusable: old zone was inline-signing");
 2055         return (false);
 2056     } else if ((obj != NULL && cfg_obj_asboolean(obj)) && !has_raw) {
 2057         dns_zone_log(zone, ISC_LOG_DEBUG(1),
 2058                  "not reusable: old zone was not inline-signing");
 2059         return (false);
 2060     }
 2061 
 2062     if (zonetype_fromconfig(zoptions) != ztype) {
 2063         dns_zone_log(zone, ISC_LOG_DEBUG(1),
 2064                  "not reusable: type mismatch");
 2065         return (false);
 2066     }
 2067 
 2068     obj = NULL;
 2069     (void)cfg_map_get(zoptions, "file", &obj);
 2070     if (obj != NULL) {
 2071         cfilename = cfg_obj_asstring(obj);
 2072     } else {
 2073         cfilename = NULL;
 2074     }
 2075     if (!((cfilename == NULL && zfilename == NULL) ||
 2076           (cfilename != NULL && zfilename != NULL &&
 2077            strcmp(cfilename, zfilename) == 0)))
 2078     {
 2079         dns_zone_log(zone, ISC_LOG_DEBUG(1),
 2080                  "not reusable: filename mismatch");
 2081         return (false);
 2082     }
 2083 
 2084     return (true);
 2085 }