"Fossies" - the Fresh Open Source Software Archive

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