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