zone.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 #include <config.h>
00021 #include <errno.h>
00022 
00023 #include <isc/file.h>
00024 #include <isc/hex.h>
00025 #include <isc/mutex.h>
00026 #include <isc/pool.h>
00027 #include <isc/print.h>
00028 #include <isc/random.h>
00029 #include <isc/ratelimiter.h>
00030 #include <isc/refcount.h>
00031 #include <isc/rwlock.h>
00032 #include <isc/serial.h>
00033 #include <isc/stats.h>
00034 #include <isc/stdtime.h>
00035 #include <isc/strerror.h>
00036 #include <isc/string.h>
00037 #include <isc/taskpool.h>
00038 #include <isc/thread.h>
00039 #include <isc/timer.h>
00040 #include <isc/util.h>
00041 
00042 #include <dns/acache.h>
00043 #include <dns/acl.h>
00044 #include <dns/adb.h>
00045 #include <dns/callbacks.h>
00046 #include <dns/db.h>
00047 #include <dns/dbiterator.h>
00048 #include <dns/dlz.h>
00049 #include <dns/dnssec.h>
00050 #include <dns/events.h>
00051 #include <dns/journal.h>
00052 #include <dns/keydata.h>
00053 #include <dns/keytable.h>
00054 #include <dns/keyvalues.h>
00055 #include <dns/log.h>
00056 #include <dns/master.h>
00057 #include <dns/masterdump.h>
00058 #include <dns/message.h>
00059 #include <dns/name.h>
00060 #include <dns/nsec.h>
00061 #include <dns/nsec3.h>
00062 #include <dns/peer.h>
00063 #include <dns/private.h>
00064 #include <dns/rbt.h>
00065 #include <dns/rcode.h>
00066 #include <dns/rdata.h>
00067 #include <dns/rdataclass.h>
00068 #include <dns/rdatalist.h>
00069 #include <dns/rdataset.h>
00070 #include <dns/rdatasetiter.h>
00071 #include <dns/rdatastruct.h>
00072 #include <dns/rdatatype.h>
00073 #include <dns/request.h>
00074 #include <dns/resolver.h>
00075 #include <dns/result.h>
00076 #include <dns/rriterator.h>
00077 #include <dns/soa.h>
00078 #include <dns/ssu.h>
00079 #include <dns/stats.h>
00080 #include <dns/time.h>
00081 #include <dns/tsig.h>
00082 #include <dns/update.h>
00083 #include <dns/xfrin.h>
00084 #include <dns/zone.h>
00085 #include <dns/zt.h>
00086 
00087 #include <dst/dst.h>
00088 
00089 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
00090 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
00091 
00092 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
00093 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
00094 
00095 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
00096 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
00097 
00098 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
00099 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
00100 
00101 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
00102 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
00103 
00104 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
00105 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
00106 
00107 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
00108 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
00109 
00110 /*%
00111  * Ensure 'a' is at least 'min' but not more than 'max'.
00112  */
00113 #define RANGE(a, min, max) \
00114                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
00115 
00116 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
00117 
00118 /*%
00119  * Key flags
00120  */
00121 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
00122 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
00123 #define ALG(x) dst_key_alg(x)
00124 
00125 /*
00126  * Default values.
00127  */
00128 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
00129 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
00130 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
00131 #define RESIGN_DELAY 3600               /*%< 1 hour */
00132 
00133 #ifndef DNS_MAX_EXPIRE
00134 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
00135 #endif
00136 
00137 #ifndef DNS_DUMP_DELAY
00138 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
00139 #endif
00140 
00141 typedef struct dns_notify dns_notify_t;
00142 typedef struct dns_stub dns_stub_t;
00143 typedef struct dns_load dns_load_t;
00144 typedef struct dns_forward dns_forward_t;
00145 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
00146 typedef struct dns_io dns_io_t;
00147 typedef ISC_LIST(dns_io_t) dns_iolist_t;
00148 typedef struct dns_signing dns_signing_t;
00149 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
00150 typedef struct dns_nsec3chain dns_nsec3chain_t;
00151 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
00152 typedef struct dns_keyfetch dns_keyfetch_t;
00153 typedef struct dns_asyncload dns_asyncload_t;
00154 typedef struct dns_include dns_include_t;
00155 
00156 #define DNS_ZONE_CHECKLOCK
00157 #ifdef DNS_ZONE_CHECKLOCK
00158 #define LOCK_ZONE(z) \
00159          do { LOCK(&(z)->lock); \
00160               INSIST((z)->locked == ISC_FALSE); \
00161              (z)->locked = ISC_TRUE; \
00162                 } while (0)
00163 #define UNLOCK_ZONE(z) \
00164         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
00165 #define LOCKED_ZONE(z) ((z)->locked)
00166 #define TRYLOCK_ZONE(result, z) \
00167         do { \
00168               result = isc_mutex_trylock(&(z)->lock); \
00169               if (result == ISC_R_SUCCESS) {  \
00170                      INSIST((z)->locked == ISC_FALSE); \
00171                      (z)->locked = ISC_TRUE; \
00172               } \
00173         } while (0)
00174 #else
00175 #define LOCK_ZONE(z) LOCK(&(z)->lock)
00176 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
00177 #define LOCKED_ZONE(z) ISC_TRUE
00178 #define TRYLOCK_ZONE(result, z) \
00179         do { result = isc_mutex_trylock(&(z)->lock); } while (0)
00180 #endif
00181 
00182 #ifdef ISC_RWLOCK_USEATOMIC
00183 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
00184 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
00185 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
00186 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
00187 #else
00188 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
00189 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
00190 #define ZONEDB_LOCK(l, t)       LOCK(l)
00191 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
00192 #endif
00193 
00194 struct dns_zone {
00195         /* Unlocked */
00196         unsigned int            magic;
00197         isc_mutex_t             lock;
00198 #ifdef DNS_ZONE_CHECKLOCK
00199         isc_boolean_t           locked;
00200 #endif
00201         isc_mem_t               *mctx;
00202         isc_refcount_t          erefs;
00203 
00204 #ifdef ISC_RWLOCK_USEATOMIC
00205         isc_rwlock_t            dblock;
00206 #else
00207         isc_mutex_t             dblock;
00208 #endif
00209         dns_db_t                *db;            /* Locked by dblock */
00210 
00211         /* Locked */
00212         dns_zonemgr_t           *zmgr;
00213         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
00214         isc_timer_t             *timer;
00215         unsigned int            irefs;
00216         dns_name_t              origin;
00217         char                    *masterfile;
00218         ISC_LIST(dns_include_t) includes;       /* Include files */
00219         ISC_LIST(dns_include_t) newincludes;    /* Loading */
00220         unsigned int            nincludes;
00221         dns_masterformat_t      masterformat;
00222         const dns_master_style_t *masterstyle;
00223         char                    *journal;
00224         isc_int32_t             journalsize;
00225         dns_rdataclass_t        rdclass;
00226         dns_zonetype_t          type;
00227         unsigned int            flags;
00228         unsigned int            options;
00229         unsigned int            options2;
00230         unsigned int            db_argc;
00231         char                    **db_argv;
00232         isc_time_t              expiretime;
00233         isc_time_t              refreshtime;
00234         isc_time_t              dumptime;
00235         isc_time_t              loadtime;
00236         isc_time_t              notifytime;
00237         isc_time_t              resigntime;
00238         isc_time_t              keywarntime;
00239         isc_time_t              signingtime;
00240         isc_time_t              nsec3chaintime;
00241         isc_time_t              refreshkeytime;
00242         isc_uint32_t            refreshkeyinterval;
00243         isc_uint32_t            refreshkeycount;
00244         isc_uint32_t            refresh;
00245         isc_uint32_t            retry;
00246         isc_uint32_t            expire;
00247         isc_uint32_t            minimum;
00248         isc_stdtime_t           key_expiry;
00249         isc_stdtime_t           log_key_expired_timer;
00250         char                    *keydirectory;
00251 
00252         isc_uint32_t            maxrefresh;
00253         isc_uint32_t            minrefresh;
00254         isc_uint32_t            maxretry;
00255         isc_uint32_t            minretry;
00256 
00257         isc_sockaddr_t          *masters;
00258         isc_dscp_t              *masterdscps;
00259         dns_name_t              **masterkeynames;
00260         isc_boolean_t           *mastersok;
00261         unsigned int            masterscnt;
00262         unsigned int            curmaster;
00263         isc_sockaddr_t          masteraddr;
00264         dns_notifytype_t        notifytype;
00265         isc_sockaddr_t          *notify;
00266         dns_name_t              **notifykeynames;
00267         isc_dscp_t              *notifydscp;
00268         unsigned int            notifycnt;
00269         isc_sockaddr_t          notifyfrom;
00270         isc_task_t              *task;
00271         isc_task_t              *loadtask;
00272         isc_sockaddr_t          notifysrc4;
00273         isc_sockaddr_t          notifysrc6;
00274         isc_sockaddr_t          xfrsource4;
00275         isc_sockaddr_t          xfrsource6;
00276         isc_sockaddr_t          altxfrsource4;
00277         isc_sockaddr_t          altxfrsource6;
00278         isc_sockaddr_t          sourceaddr;
00279         isc_dscp_t              notifysrc4dscp;
00280         isc_dscp_t              notifysrc6dscp;
00281         isc_dscp_t              xfrsource4dscp;
00282         isc_dscp_t              xfrsource6dscp;
00283         isc_dscp_t              altxfrsource4dscp;
00284         isc_dscp_t              altxfrsource6dscp;
00285         dns_xfrin_ctx_t         *xfr;           /* task locked */
00286         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
00287         /* Access Control Lists */
00288         dns_acl_t               *update_acl;
00289         dns_acl_t               *forward_acl;
00290         dns_acl_t               *notify_acl;
00291         dns_acl_t               *query_acl;
00292         dns_acl_t               *queryon_acl;
00293         dns_acl_t               *xfr_acl;
00294         isc_boolean_t           update_disabled;
00295         isc_boolean_t           zero_no_soa_ttl;
00296         dns_severity_t          check_names;
00297         ISC_LIST(dns_notify_t)  notifies;
00298         dns_request_t           *request;
00299         dns_loadctx_t           *lctx;
00300         dns_io_t                *readio;
00301         dns_dumpctx_t           *dctx;
00302         dns_io_t                *writeio;
00303         isc_uint32_t            maxxfrin;
00304         isc_uint32_t            maxxfrout;
00305         isc_uint32_t            idlein;
00306         isc_uint32_t            idleout;
00307         isc_event_t             ctlevent;
00308         dns_ssutable_t          *ssutable;
00309         isc_uint32_t            sigvalidityinterval;
00310         isc_uint32_t            sigresigninginterval;
00311         dns_view_t              *view;
00312         dns_acache_t            *acache;
00313         dns_checkmxfunc_t       checkmx;
00314         dns_checksrvfunc_t      checksrv;
00315         dns_checknsfunc_t       checkns;
00316         /*%
00317          * Zones in certain states such as "waiting for zone transfer"
00318          * or "zone transfer in progress" are kept on per-state linked lists
00319          * in the zone manager using the 'statelink' field.  The 'statelist'
00320          * field points at the list the zone is currently on.  It the zone
00321          * is not on any such list, statelist is NULL.
00322          */
00323         ISC_LINK(dns_zone_t)    statelink;
00324         dns_zonelist_t          *statelist;
00325         /*%
00326          * Statistics counters about zone management.
00327          */
00328         isc_stats_t             *stats;
00329         /*%
00330          * Optional per-zone statistics counters.  Counted outside of this
00331          * module.
00332          */
00333         dns_zonestat_level_t    statlevel;
00334         isc_boolean_t           requeststats_on;
00335         isc_stats_t             *requeststats;
00336         dns_stats_t             *rcvquerystats;
00337         isc_uint32_t            notifydelay;
00338         dns_isselffunc_t        isself;
00339         void                    *isselfarg;
00340 
00341         char *                  strnamerd;
00342         char *                  strname;
00343         char *                  strrdclass;
00344         char *                  strviewname;
00345 
00346         /*%
00347          * Serial number for deferred journal compaction.
00348          */
00349         isc_uint32_t            compact_serial;
00350         /*%
00351          * Keys that are signing the zone for the first time.
00352          */
00353         dns_signinglist_t       signing;
00354         dns_nsec3chainlist_t    nsec3chain;
00355         /*%
00356          * Signing / re-signing quantum stopping parameters.
00357          */
00358         isc_uint32_t            signatures;
00359         isc_uint32_t            nodes;
00360         dns_rdatatype_t         privatetype;
00361 
00362         /*%
00363          * Autosigning/key-maintenance options
00364          */
00365         isc_uint32_t            keyopts;
00366 
00367         /*%
00368          * True if added by "rndc addzone"
00369          */
00370         isc_boolean_t           added;
00371 
00372         /*%
00373          * True if added by automatically by named.
00374          */
00375         isc_boolean_t           automatic;
00376 
00377         /*%
00378          * response policy data to be relayed to the database
00379          */
00380         dns_rpz_zones_t         *rpzs;
00381         dns_rpz_num_t           rpz_num;
00382 
00383         /*%
00384          * Serial number update method.
00385          */
00386         dns_updatemethod_t      updatemethod;
00387 
00388         /*%
00389          * whether ixfr is requested
00390          */
00391         isc_boolean_t           requestixfr;
00392 
00393         /*%
00394          * whether EDNS EXPIRE is requested
00395          */
00396         isc_boolean_t           requestexpire;
00397 
00398         /*%
00399          * Outstanding forwarded UPDATE requests.
00400          */
00401         dns_forwardlist_t       forwards;
00402 
00403         dns_zone_t              *raw;
00404         dns_zone_t              *secure;
00405 
00406         isc_boolean_t           sourceserialset;
00407         isc_uint32_t            sourceserial;
00408 
00409         /*%
00410          * maximum zone ttl
00411          */
00412         dns_ttl_t               maxttl;
00413 
00414         /*
00415          * Inline zone signing state.
00416          */
00417         dns_diff_t              rss_diff;
00418         isc_eventlist_t         rss_events;
00419         dns_dbversion_t         *rss_newver;
00420         dns_dbversion_t         *rss_oldver;
00421         dns_db_t                *rss_db;
00422         dns_zone_t              *rss_raw;
00423         isc_event_t             *rss_event;
00424         dns_update_state_t      *rss_state;
00425 };
00426 
00427 typedef struct {
00428         dns_diff_t      *diff;
00429         isc_boolean_t   offline;
00430 } zonediff_t;
00431 
00432 #define zonediff_init(z, d) \
00433         do { \
00434                 zonediff_t *_z = (z); \
00435                 (_z)->diff = (d); \
00436                 (_z)->offline = ISC_FALSE; \
00437         } while (0)
00438 
00439 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
00440 #define DNS_ZONE_SETFLAG(z,f) do { \
00441                 INSIST(LOCKED_ZONE(z)); \
00442                 (z)->flags |= (f); \
00443                 } while (0)
00444 #define DNS_ZONE_CLRFLAG(z,f) do { \
00445                 INSIST(LOCKED_ZONE(z)); \
00446                 (z)->flags &= ~(f); \
00447                 } while (0)
00448         /* XXX MPA these may need to go back into zone.h */
00449 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
00450 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
00451 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
00452 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
00453 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
00454 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
00455 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
00456 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
00457 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
00458 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
00459                                                  * uptodate */
00460 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
00461                                                  * messages */
00462 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
00463                                                  * reload */
00464 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
00465                                                  * zone with no masters
00466                                                  * occurred */
00467 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
00468 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
00469                                                  * from SOA (if not set, we
00470                                                  * are still using
00471                                                  * default timer values) */
00472 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
00473 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
00474 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
00475 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
00476 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
00477 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
00478 #define DNS_ZONEFLG_FLUSH       0x00200000U
00479 #define DNS_ZONEFLG_NOEDNS      0x00400000U
00480 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
00481 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
00482 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
00483 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
00484 #define DNS_ZONEFLG_THAW        0x08000000U
00485 #define DNS_ZONEFLG_LOADPENDING 0x10000000U     /*%< Loading scheduled */
00486 #define DNS_ZONEFLG_NODELAY     0x20000000U
00487 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
00488 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
00489                                                    *   due to the zone just
00490                                                    *   being loaded for the
00491                                                    *   first time.  */
00492 
00493 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
00494 #define DNS_ZONE_OPTION2(z,o) (((z)->options2 & (o)) != 0)
00495 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
00496 
00497 /* Flags for zone_load() */
00498 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
00499 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
00500                                                    load. */
00501 
00502 #define UNREACH_CHACHE_SIZE     10U
00503 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
00504 
00505 #define CHECK(op) \
00506         do { result = (op); \
00507                 if (result != ISC_R_SUCCESS) goto failure; \
00508         } while (0)
00509 
00510 struct dns_unreachable {
00511         isc_sockaddr_t  remote;
00512         isc_sockaddr_t  local;
00513         isc_uint32_t    expire;
00514         isc_uint32_t    last;
00515         isc_uint32_t    count;
00516 };
00517 
00518 struct dns_zonemgr {
00519         unsigned int            magic;
00520         isc_mem_t *             mctx;
00521         int                     refs;           /* Locked by rwlock */
00522         isc_taskmgr_t *         taskmgr;
00523         isc_timermgr_t *        timermgr;
00524         isc_socketmgr_t *       socketmgr;
00525         isc_taskpool_t *        zonetasks;
00526         isc_taskpool_t *        loadtasks;
00527         isc_task_t *            task;
00528         isc_pool_t *            mctxpool;
00529         isc_ratelimiter_t *     notifyrl;
00530         isc_ratelimiter_t *     refreshrl;
00531         isc_ratelimiter_t *     startupnotifyrl;
00532         isc_ratelimiter_t *     startuprefreshrl;
00533         isc_rwlock_t            rwlock;
00534         isc_mutex_t             iolock;
00535         isc_rwlock_t            urlock;
00536 
00537         /* Locked by rwlock. */
00538         dns_zonelist_t          zones;
00539         dns_zonelist_t          waiting_for_xfrin;
00540         dns_zonelist_t          xfrin_in_progress;
00541 
00542         /* Configuration data. */
00543         isc_uint32_t            transfersin;
00544         isc_uint32_t            transfersperns;
00545         unsigned int            notifyrate;
00546         unsigned int            startupnotifyrate;
00547         unsigned int            serialqueryrate;
00548         unsigned int            startupserialqueryrate;
00549 
00550         /* Locked by iolock */
00551         isc_uint32_t            iolimit;
00552         isc_uint32_t            ioactive;
00553         dns_iolist_t            high;
00554         dns_iolist_t            low;
00555 
00556         /* Locked by urlock. */
00557         /* LRU cache */
00558         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
00559 };
00560 
00561 /*%
00562  * Hold notify state.
00563  */
00564 struct dns_notify {
00565         unsigned int            magic;
00566         unsigned int            flags;
00567         isc_mem_t               *mctx;
00568         dns_zone_t              *zone;
00569         dns_adbfind_t           *find;
00570         dns_request_t           *request;
00571         dns_name_t              ns;
00572         isc_sockaddr_t          dst;
00573         dns_tsigkey_t           *key;
00574         isc_dscp_t              dscp;
00575         ISC_LINK(dns_notify_t)  link;
00576         isc_event_t             *event;
00577 };
00578 
00579 #define DNS_NOTIFY_NOSOA        0x0001U
00580 #define DNS_NOTIFY_STARTUP      0x0002U
00581 
00582 /*%
00583  *      dns_stub holds state while performing a 'stub' transfer.
00584  *      'db' is the zone's 'db' or a new one if this is the initial
00585  *      transfer.
00586  */
00587 
00588 struct dns_stub {
00589         unsigned int            magic;
00590         isc_mem_t               *mctx;
00591         dns_zone_t              *zone;
00592         dns_db_t                *db;
00593         dns_dbversion_t         *version;
00594 };
00595 
00596 /*%
00597  *      Hold load state.
00598  */
00599 struct dns_load {
00600         unsigned int            magic;
00601         isc_mem_t               *mctx;
00602         dns_zone_t              *zone;
00603         dns_db_t                *db;
00604         isc_time_t              loadtime;
00605         dns_rdatacallbacks_t    callbacks;
00606 };
00607 
00608 /*%
00609  *      Hold forward state.
00610  */
00611 struct dns_forward {
00612         unsigned int            magic;
00613         isc_mem_t               *mctx;
00614         dns_zone_t              *zone;
00615         isc_buffer_t            *msgbuf;
00616         dns_request_t           *request;
00617         isc_uint32_t            which;
00618         isc_sockaddr_t          addr;
00619         dns_updatecallback_t    callback;
00620         void                    *callback_arg;
00621         unsigned int            options;
00622         ISC_LINK(dns_forward_t) link;
00623 };
00624 
00625 /*%
00626  *      Hold IO request state.
00627  */
00628 struct dns_io {
00629         unsigned int    magic;
00630         dns_zonemgr_t   *zmgr;
00631         isc_boolean_t   high;
00632         isc_task_t      *task;
00633         ISC_LINK(dns_io_t) link;
00634         isc_event_t     *event;
00635 };
00636 
00637 /*%
00638  *      Hold state for when we are signing a zone with a new
00639  *      DNSKEY as result of an update.
00640  */
00641 struct dns_signing {
00642         unsigned int            magic;
00643         dns_db_t                *db;
00644         dns_dbiterator_t        *dbiterator;
00645         dns_secalg_t            algorithm;
00646         isc_uint16_t            keyid;
00647         isc_boolean_t           delete;
00648         isc_boolean_t           done;
00649         ISC_LINK(dns_signing_t) link;
00650 };
00651 
00652 struct dns_nsec3chain {
00653         unsigned int                    magic;
00654         dns_db_t                        *db;
00655         dns_dbiterator_t                *dbiterator;
00656         dns_rdata_nsec3param_t          nsec3param;
00657         unsigned char                   salt[255];
00658         isc_boolean_t                   done;
00659         isc_boolean_t                   seen_nsec;
00660         isc_boolean_t                   delete_nsec;
00661         isc_boolean_t                   save_delete_nsec;
00662         ISC_LINK(dns_nsec3chain_t)      link;
00663 };
00664 /*%<
00665  * 'dbiterator' contains a iterator for the database.  If we are creating
00666  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
00667  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
00668  * iterated.
00669  *
00670  * 'nsec3param' contains the parameters of the NSEC3 chain being created
00671  * or removed.
00672  *
00673  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
00674  *
00675  * 'seen_nsec' will be set to true if, while iterating the zone to create a
00676  * NSEC3 chain, a NSEC record is seen.
00677  *
00678  * 'delete_nsec' will be set to true if, at the completion of the creation
00679  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
00680  * are in the process of deleting the NSEC chain.
00681  *
00682  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
00683  * so it can be recovered in the event of a error.
00684  */
00685 
00686 struct dns_keyfetch {
00687         dns_fixedname_t name;
00688         dns_rdataset_t keydataset;
00689         dns_rdataset_t dnskeyset;
00690         dns_rdataset_t dnskeysigset;
00691         dns_zone_t *zone;
00692         dns_db_t *db;
00693         dns_fetch_t *fetch;
00694 };
00695 
00696 /*%
00697  * Hold state for an asynchronous load
00698  */
00699 struct dns_asyncload {
00700         dns_zone_t *zone;
00701         dns_zt_zoneloaded_t loaded;
00702         void *loaded_arg;
00703 };
00704 
00705 /*%
00706  * Reference to an include file encountered during loading
00707  */
00708 struct dns_include {
00709         char *name;
00710         isc_time_t filetime;
00711         ISC_LINK(dns_include_t) link;
00712 };
00713 
00714 /*
00715  * These can be overridden by the -T mkeytimers option on the command
00716  * line, so that we can test with shorter periods than specified in
00717  * RFC 5011.
00718  */
00719 #define HOUR 3600
00720 #define DAY (24*HOUR)
00721 #define MONTH (30*DAY)
00722 unsigned int dns_zone_mkey_hour = HOUR;
00723 unsigned int dns_zone_mkey_day = DAY;
00724 unsigned int dns_zone_mkey_month = MONTH;
00725 
00726 #define SEND_BUFFER_SIZE 2048
00727 
00728 static void zone_settimer(dns_zone_t *, isc_time_t *);
00729 static void cancel_refresh(dns_zone_t *);
00730 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
00731                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
00732 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
00733      ISC_FORMAT_PRINTF(3, 4);
00734 static void queue_xfrin(dns_zone_t *zone);
00735 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
00736                                   dns_diff_t *diff, dns_diffop_t op,
00737                                   dns_name_t *name, dns_ttl_t ttl,
00738                                   dns_rdata_t *rdata);
00739 static void zone_unload(dns_zone_t *zone);
00740 static void zone_expire(dns_zone_t *zone);
00741 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
00742 static void zone_idetach(dns_zone_t **zonep);
00743 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
00744                                    isc_boolean_t dump);
00745 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
00746 static inline void zone_detachdb(dns_zone_t *zone);
00747 static isc_result_t default_journal(dns_zone_t *zone);
00748 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
00749 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
00750                                   isc_time_t loadtime, isc_result_t result);
00751 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
00752 static void zone_shutdown(isc_task_t *, isc_event_t *);
00753 static void zone_loaddone(void *arg, isc_result_t result);
00754 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
00755                                    isc_time_t loadtime);
00756 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
00757 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
00758 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
00759 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
00760 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
00761                                            isc_uint32_t serial);
00762 
00763 #if 0
00764 /* ondestroy example */
00765 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
00766 #endif
00767 
00768 static void refresh_callback(isc_task_t *, isc_event_t *);
00769 static void stub_callback(isc_task_t *, isc_event_t *);
00770 static void queue_soa_query(dns_zone_t *zone);
00771 static void soa_query(isc_task_t *, isc_event_t *);
00772 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
00773                      dns_stub_t *stub);
00774 static int message_count(dns_message_t *msg, dns_section_t section,
00775                          dns_rdatatype_t type);
00776 static void notify_cancel(dns_zone_t *zone);
00777 static void notify_find_address(dns_notify_t *notify);
00778 static void notify_send(dns_notify_t *notify);
00779 static isc_result_t notify_createmessage(dns_zone_t *zone,
00780                                          unsigned int flags,
00781                                          dns_message_t **messagep);
00782 static void notify_done(isc_task_t *task, isc_event_t *event);
00783 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
00784 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
00785 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
00786 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
00787                                              dns_zone_t *zone);
00788 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
00789 static void zonemgr_free(dns_zonemgr_t *zmgr);
00790 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
00791                                   isc_task_t *task, isc_taskaction_t action,
00792                                   void *arg, dns_io_t **iop);
00793 static void zonemgr_putio(dns_io_t **iop);
00794 static void zonemgr_cancelio(dns_io_t *io);
00795 
00796 static isc_result_t
00797 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
00798                  unsigned int *soacount, isc_uint32_t *serial,
00799                  isc_uint32_t *refresh, isc_uint32_t *retry,
00800                  isc_uint32_t *expire, isc_uint32_t *minimum,
00801                  unsigned int *errors);
00802 
00803 static void zone_freedbargs(dns_zone_t *zone);
00804 static void forward_callback(isc_task_t *task, isc_event_t *event);
00805 static void zone_saveunique(dns_zone_t *zone, const char *path,
00806                             const char *templat);
00807 static void zone_maintenance(dns_zone_t *zone);
00808 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
00809 static void dump_done(void *arg, isc_result_t result);
00810 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
00811                                      isc_uint16_t keyid, isc_boolean_t delete);
00812 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
00813                                 dns_dbnode_t *node, dns_name_t *name,
00814                                 dns_diff_t *diff);
00815 static void zone_rekey(dns_zone_t *zone);
00816 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
00817 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
00818                   unsigned int value);
00819 
00820 #define ENTER zone_debuglog(zone, me, 1, "enter")
00821 
00822 static const unsigned int dbargc_default = 1;
00823 static const char *dbargv_default[] = { "rbt" };
00824 
00825 #define DNS_ZONE_JITTER_ADD(a, b, c) \
00826         do { \
00827                 isc_interval_t _i; \
00828                 isc_uint32_t _j; \
00829                 _j = isc_random_jitter((b), (b)/4); \
00830                 isc_interval_set(&_i, _j, 0); \
00831                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
00832                         dns_zone_log(zone, ISC_LOG_WARNING, \
00833                                      "epoch approaching: upgrade required: " \
00834                                      "now + %s failed", #b); \
00835                         isc_interval_set(&_i, _j/2, 0); \
00836                         (void)isc_time_add((a), &_i, (c)); \
00837                 } \
00838         } while (0)
00839 
00840 #define DNS_ZONE_TIME_ADD(a, b, c) \
00841         do { \
00842                 isc_interval_t _i; \
00843                 isc_interval_set(&_i, (b), 0); \
00844                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
00845                         dns_zone_log(zone, ISC_LOG_WARNING, \
00846                                      "epoch approaching: upgrade required: " \
00847                                      "now + %s failed", #b); \
00848                         isc_interval_set(&_i, (b)/2, 0); \
00849                         (void)isc_time_add((a), &_i, (c)); \
00850                 } \
00851         } while (0)
00852 
00853 typedef struct nsec3param nsec3param_t;
00854 struct nsec3param {
00855         unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
00856         unsigned int length;
00857         isc_boolean_t nsec;
00858         isc_boolean_t replace;
00859         ISC_LINK(nsec3param_t)  link;
00860 };
00861 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
00862 struct np3event {
00863         isc_event_t event;
00864         nsec3param_t params;
00865 };
00866 
00867 struct ssevent {
00868         isc_event_t event;
00869         isc_uint32_t serial;
00870 };
00871 
00872 /*%
00873  * Increment resolver-related statistics counters.  Zone must be locked.
00874  */
00875 static inline void
00876 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
00877         if (zone->stats != NULL)
00878                 isc_stats_increment(zone->stats, counter);
00879 }
00880 
00881 /***
00882  ***    Public functions.
00883  ***/
00884 
00885 isc_result_t
00886 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
00887         isc_result_t result;
00888         dns_zone_t *zone;
00889         isc_time_t now;
00890 
00891         REQUIRE(zonep != NULL && *zonep == NULL);
00892         REQUIRE(mctx != NULL);
00893 
00894         TIME_NOW(&now);
00895         zone = isc_mem_get(mctx, sizeof(*zone));
00896         if (zone == NULL)
00897                 return (ISC_R_NOMEMORY);
00898 
00899         zone->mctx = NULL;
00900         isc_mem_attach(mctx, &zone->mctx);
00901 
00902         result = isc_mutex_init(&zone->lock);
00903         if (result != ISC_R_SUCCESS)
00904                 goto free_zone;
00905 
00906         result = ZONEDB_INITLOCK(&zone->dblock);
00907         if (result != ISC_R_SUCCESS)
00908                 goto free_mutex;
00909 
00910         /* XXX MPA check that all elements are initialised */
00911 #ifdef DNS_ZONE_CHECKLOCK
00912         zone->locked = ISC_FALSE;
00913 #endif
00914         zone->db = NULL;
00915         zone->zmgr = NULL;
00916         ISC_LINK_INIT(zone, link);
00917         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
00918         if (result != ISC_R_SUCCESS)
00919                 goto free_dblock;
00920         zone->irefs = 0;
00921         dns_name_init(&zone->origin, NULL);
00922         zone->strnamerd = NULL;
00923         zone->strname = NULL;
00924         zone->strrdclass = NULL;
00925         zone->strviewname = NULL;
00926         zone->masterfile = NULL;
00927         ISC_LIST_INIT(zone->includes);
00928         ISC_LIST_INIT(zone->newincludes);
00929         zone->nincludes = 0;
00930         zone->masterformat = dns_masterformat_none;
00931         zone->masterstyle = NULL;
00932         zone->keydirectory = NULL;
00933         zone->journalsize = -1;
00934         zone->journal = NULL;
00935         zone->rdclass = dns_rdataclass_none;
00936         zone->type = dns_zone_none;
00937         zone->flags = 0;
00938         zone->options = 0;
00939         zone->options2 = 0;
00940         zone->keyopts = 0;
00941         zone->db_argc = 0;
00942         zone->db_argv = NULL;
00943         isc_time_settoepoch(&zone->expiretime);
00944         isc_time_settoepoch(&zone->refreshtime);
00945         isc_time_settoepoch(&zone->dumptime);
00946         isc_time_settoepoch(&zone->loadtime);
00947         zone->notifytime = now;
00948         isc_time_settoepoch(&zone->resigntime);
00949         isc_time_settoepoch(&zone->keywarntime);
00950         isc_time_settoepoch(&zone->signingtime);
00951         isc_time_settoepoch(&zone->nsec3chaintime);
00952         isc_time_settoepoch(&zone->refreshkeytime);
00953         zone->refreshkeyinterval = 0;
00954         zone->refreshkeycount = 0;
00955         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
00956         zone->retry = DNS_ZONE_DEFAULTRETRY;
00957         zone->expire = 0;
00958         zone->minimum = 0;
00959         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
00960         zone->minrefresh = DNS_ZONE_MINREFRESH;
00961         zone->maxretry = DNS_ZONE_MAXRETRY;
00962         zone->minretry = DNS_ZONE_MINRETRY;
00963         zone->masters = NULL;
00964         zone->masterdscps = NULL;
00965         zone->masterkeynames = NULL;
00966         zone->mastersok = NULL;
00967         zone->masterscnt = 0;
00968         zone->curmaster = 0;
00969         zone->maxttl = 0;
00970         zone->notify = NULL;
00971         zone->notifykeynames = NULL;
00972         zone->notifydscp = NULL;
00973         zone->notifytype = dns_notifytype_yes;
00974         zone->notifycnt = 0;
00975         zone->task = NULL;
00976         zone->loadtask = NULL;
00977         zone->update_acl = NULL;
00978         zone->forward_acl = NULL;
00979         zone->notify_acl = NULL;
00980         zone->query_acl = NULL;
00981         zone->queryon_acl = NULL;
00982         zone->xfr_acl = NULL;
00983         zone->update_disabled = ISC_FALSE;
00984         zone->zero_no_soa_ttl = ISC_TRUE;
00985         zone->check_names = dns_severity_ignore;
00986         zone->request = NULL;
00987         zone->lctx = NULL;
00988         zone->readio = NULL;
00989         zone->dctx = NULL;
00990         zone->writeio = NULL;
00991         zone->timer = NULL;
00992         zone->idlein = DNS_DEFAULT_IDLEIN;
00993         zone->idleout = DNS_DEFAULT_IDLEOUT;
00994         zone->log_key_expired_timer = 0;
00995         ISC_LIST_INIT(zone->notifies);
00996         isc_sockaddr_any(&zone->notifysrc4);
00997         isc_sockaddr_any6(&zone->notifysrc6);
00998         isc_sockaddr_any(&zone->xfrsource4);
00999         isc_sockaddr_any6(&zone->xfrsource6);
01000         isc_sockaddr_any(&zone->altxfrsource4);
01001         isc_sockaddr_any6(&zone->altxfrsource6);
01002         zone->notifysrc4dscp = -1;
01003         zone->notifysrc6dscp = -1;
01004         zone->xfrsource4dscp = -1;
01005         zone->xfrsource6dscp = -1;
01006         zone->altxfrsource4dscp = -1;
01007         zone->altxfrsource6dscp = -1;
01008         zone->xfr = NULL;
01009         zone->tsigkey = NULL;
01010         zone->maxxfrin = MAX_XFER_TIME;
01011         zone->maxxfrout = MAX_XFER_TIME;
01012         zone->ssutable = NULL;
01013         zone->sigvalidityinterval = 30 * 24 * 3600;
01014         zone->sigresigninginterval = 7 * 24 * 3600;
01015         zone->view = NULL;
01016         zone->acache = NULL;
01017         zone->checkmx = NULL;
01018         zone->checksrv = NULL;
01019         zone->checkns = NULL;
01020         ISC_LINK_INIT(zone, statelink);
01021         zone->statelist = NULL;
01022         zone->stats = NULL;
01023         zone->requeststats_on = ISC_FALSE;
01024         zone->statlevel = dns_zonestat_none;
01025         zone->requeststats = NULL;
01026         zone->rcvquerystats = NULL;
01027         zone->notifydelay = 5;
01028         zone->isself = NULL;
01029         zone->isselfarg = NULL;
01030         ISC_LIST_INIT(zone->signing);
01031         ISC_LIST_INIT(zone->nsec3chain);
01032         zone->signatures = 10;
01033         zone->nodes = 100;
01034         zone->privatetype = (dns_rdatatype_t)0xffffU;
01035         zone->added = ISC_FALSE;
01036         zone->automatic = ISC_FALSE;
01037         zone->rpzs = NULL;
01038         zone->rpz_num = DNS_RPZ_INVALID_NUM;
01039         ISC_LIST_INIT(zone->forwards);
01040         zone->raw = NULL;
01041         zone->secure = NULL;
01042         zone->sourceserial = 0;
01043         zone->sourceserialset = ISC_FALSE;
01044         zone->requestixfr = ISC_TRUE;
01045         zone->requestexpire = ISC_TRUE;
01046         ISC_LIST_INIT(zone->rss_events);
01047         zone->rss_db = NULL;
01048         zone->rss_raw = NULL;
01049         zone->rss_newver = NULL;
01050         zone->rss_oldver = NULL;
01051         zone->rss_event = NULL;
01052         zone->rss_state = NULL;
01053         zone->updatemethod = dns_updatemethod_increment;
01054 
01055         zone->magic = ZONE_MAGIC;
01056 
01057         /* Must be after magic is set. */
01058         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
01059         if (result != ISC_R_SUCCESS)
01060                 goto free_erefs;
01061 
01062         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
01063                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
01064                        NULL, NULL);
01065         *zonep = zone;
01066         return (ISC_R_SUCCESS);
01067 
01068  free_erefs:
01069         isc_refcount_decrement(&zone->erefs, NULL);
01070         isc_refcount_destroy(&zone->erefs);
01071 
01072  free_dblock:
01073         ZONEDB_DESTROYLOCK(&zone->dblock);
01074 
01075  free_mutex:
01076         DESTROYLOCK(&zone->lock);
01077 
01078  free_zone:
01079         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
01080         return (result);
01081 }
01082 
01083 /*
01084  * Free a zone.  Because we require that there be no more
01085  * outstanding events or references, no locking is necessary.
01086  */
01087 static void
01088 zone_free(dns_zone_t *zone) {
01089         isc_mem_t *mctx = NULL;
01090         dns_signing_t *signing;
01091         dns_nsec3chain_t *nsec3chain;
01092         dns_include_t *include;
01093 
01094         REQUIRE(DNS_ZONE_VALID(zone));
01095         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
01096         REQUIRE(zone->irefs == 0);
01097         REQUIRE(!LOCKED_ZONE(zone));
01098         REQUIRE(zone->timer == NULL);
01099         REQUIRE(zone->zmgr == NULL);
01100 
01101         /*
01102          * Managed objects.  Order is important.
01103          */
01104         if (zone->request != NULL)
01105                 dns_request_destroy(&zone->request); /* XXXMPA */
01106         INSIST(zone->readio == NULL);
01107         INSIST(zone->statelist == NULL);
01108         INSIST(zone->writeio == NULL);
01109 
01110         if (zone->task != NULL)
01111                 isc_task_detach(&zone->task);
01112         if (zone->loadtask != NULL)
01113                 isc_task_detach(&zone->loadtask);
01114 
01115         /* Unmanaged objects */
01116         for (signing = ISC_LIST_HEAD(zone->signing);
01117              signing != NULL;
01118              signing = ISC_LIST_HEAD(zone->signing)) {
01119                 ISC_LIST_UNLINK(zone->signing, signing, link);
01120                 dns_db_detach(&signing->db);
01121                 dns_dbiterator_destroy(&signing->dbiterator);
01122                 isc_mem_put(zone->mctx, signing, sizeof *signing);
01123         }
01124         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
01125              nsec3chain != NULL;
01126              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
01127                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
01128                 dns_db_detach(&nsec3chain->db);
01129                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
01130                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
01131         }
01132         for (include = ISC_LIST_HEAD(zone->includes);
01133              include != NULL;
01134              include = ISC_LIST_HEAD(zone->includes)) {
01135                 ISC_LIST_UNLINK(zone->includes, include, link);
01136                 isc_mem_free(zone->mctx, include->name);
01137                 isc_mem_put(zone->mctx, include, sizeof *include);
01138         }
01139         for (include = ISC_LIST_HEAD(zone->newincludes);
01140              include != NULL;
01141              include = ISC_LIST_HEAD(zone->newincludes)) {
01142                 ISC_LIST_UNLINK(zone->newincludes, include, link);
01143                 isc_mem_free(zone->mctx, include->name);
01144                 isc_mem_put(zone->mctx, include, sizeof *include);
01145         }
01146         if (zone->masterfile != NULL)
01147                 isc_mem_free(zone->mctx, zone->masterfile);
01148         zone->masterfile = NULL;
01149         if (zone->keydirectory != NULL)
01150                 isc_mem_free(zone->mctx, zone->keydirectory);
01151         zone->keydirectory = NULL;
01152         zone->journalsize = -1;
01153         if (zone->journal != NULL)
01154                 isc_mem_free(zone->mctx, zone->journal);
01155         zone->journal = NULL;
01156         if (zone->stats != NULL)
01157                 isc_stats_detach(&zone->stats);
01158         if (zone->requeststats != NULL)
01159                 isc_stats_detach(&zone->requeststats);
01160         if (zone->rcvquerystats != NULL)
01161                 dns_stats_detach(&zone->rcvquerystats);
01162         if (zone->db != NULL)
01163                 zone_detachdb(zone);
01164         if (zone->acache != NULL)
01165                 dns_acache_detach(&zone->acache);
01166         if (zone->rpzs != NULL) {
01167                 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
01168                 dns_rpz_detach_rpzs(&zone->rpzs);
01169                 zone->rpz_num = DNS_RPZ_INVALID_NUM;
01170         }
01171         zone_freedbargs(zone);
01172         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
01173                       == ISC_R_SUCCESS);
01174         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
01175                       == ISC_R_SUCCESS);
01176         zone->check_names = dns_severity_ignore;
01177         if (zone->update_acl != NULL)
01178                 dns_acl_detach(&zone->update_acl);
01179         if (zone->forward_acl != NULL)
01180                 dns_acl_detach(&zone->forward_acl);
01181         if (zone->notify_acl != NULL)
01182                 dns_acl_detach(&zone->notify_acl);
01183         if (zone->query_acl != NULL)
01184                 dns_acl_detach(&zone->query_acl);
01185         if (zone->queryon_acl != NULL)
01186                 dns_acl_detach(&zone->queryon_acl);
01187         if (zone->xfr_acl != NULL)
01188                 dns_acl_detach(&zone->xfr_acl);
01189         if (dns_name_dynamic(&zone->origin))
01190                 dns_name_free(&zone->origin, zone->mctx);
01191         if (zone->strnamerd != NULL)
01192                 isc_mem_free(zone->mctx, zone->strnamerd);
01193         if (zone->strname != NULL)
01194                 isc_mem_free(zone->mctx, zone->strname);
01195         if (zone->strrdclass != NULL)
01196                 isc_mem_free(zone->mctx, zone->strrdclass);
01197         if (zone->strviewname != NULL)
01198                 isc_mem_free(zone->mctx, zone->strviewname);
01199         if (zone->ssutable != NULL)
01200                 dns_ssutable_detach(&zone->ssutable);
01201 
01202         /* last stuff */
01203         ZONEDB_DESTROYLOCK(&zone->dblock);
01204         DESTROYLOCK(&zone->lock);
01205         isc_refcount_destroy(&zone->erefs);
01206         zone->magic = 0;
01207         mctx = zone->mctx;
01208         isc_mem_put(mctx, zone, sizeof(*zone));
01209         isc_mem_detach(&mctx);
01210 }
01211 
01212 /*
01213  * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
01214  * Caller should hold zone lock.
01215  */
01216 static inline isc_boolean_t
01217 inline_secure(dns_zone_t *zone) {
01218         REQUIRE(DNS_ZONE_VALID(zone));
01219         if (zone->raw != NULL)
01220                 return (ISC_TRUE);
01221         return (ISC_FALSE);
01222 }
01223 
01224 /*
01225  * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
01226  * Caller should hold zone lock.
01227  */
01228 static inline isc_boolean_t
01229 inline_raw(dns_zone_t *zone) {
01230         REQUIRE(DNS_ZONE_VALID(zone));
01231         if (zone->secure != NULL)
01232                 return (ISC_TRUE);
01233         return (ISC_FALSE);
01234 }
01235 
01236 /*
01237  *      Single shot.
01238  */
01239 void
01240 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
01241         char namebuf[1024];
01242 
01243         REQUIRE(DNS_ZONE_VALID(zone));
01244         REQUIRE(rdclass != dns_rdataclass_none);
01245 
01246         /*
01247          * Test and set.
01248          */
01249         LOCK_ZONE(zone);
01250         INSIST(zone != zone->raw);
01251         REQUIRE(zone->rdclass == dns_rdataclass_none ||
01252                 zone->rdclass == rdclass);
01253         zone->rdclass = rdclass;
01254 
01255         if (zone->strnamerd != NULL)
01256                 isc_mem_free(zone->mctx, zone->strnamerd);
01257         if (zone->strrdclass != NULL)
01258                 isc_mem_free(zone->mctx, zone->strrdclass);
01259 
01260         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
01261         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
01262         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
01263         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
01264 
01265         if (inline_secure(zone))
01266                 dns_zone_setclass(zone->raw, rdclass);
01267         UNLOCK_ZONE(zone);
01268 }
01269 
01270 dns_rdataclass_t
01271 dns_zone_getclass(dns_zone_t *zone) {
01272         REQUIRE(DNS_ZONE_VALID(zone));
01273 
01274         return (zone->rdclass);
01275 }
01276 
01277 void
01278 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
01279         REQUIRE(DNS_ZONE_VALID(zone));
01280 
01281         LOCK_ZONE(zone);
01282         zone->notifytype = notifytype;
01283         UNLOCK_ZONE(zone);
01284 }
01285 
01286 isc_result_t
01287 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
01288         isc_result_t result;
01289         unsigned int soacount;
01290 
01291         REQUIRE(DNS_ZONE_VALID(zone));
01292         REQUIRE(serialp != NULL);
01293 
01294         LOCK_ZONE(zone);
01295         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
01296         if (zone->db != NULL) {
01297                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
01298                                           serialp, NULL, NULL, NULL, NULL,
01299                                           NULL);
01300                 if (result == ISC_R_SUCCESS && soacount == 0)
01301                         result = ISC_R_FAILURE;
01302         } else
01303                 result = DNS_R_NOTLOADED;
01304         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
01305         UNLOCK_ZONE(zone);
01306 
01307         return (result);
01308 }
01309 
01310 isc_uint32_t
01311 dns_zone_getserial(dns_zone_t *zone) {
01312         isc_result_t result;
01313         isc_uint32_t serial;
01314 
01315         result = dns_zone_getserial2(zone, &serial);
01316         if (result != ISC_R_SUCCESS)
01317                 serial = 0; /* XXX: not really correct, but no other choice */
01318 
01319         return (serial);
01320 }
01321 
01322 /*
01323  *      Single shot.
01324  */
01325 void
01326 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
01327         char namebuf[1024];
01328 
01329         REQUIRE(DNS_ZONE_VALID(zone));
01330         REQUIRE(type != dns_zone_none);
01331 
01332         /*
01333          * Test and set.
01334          */
01335         LOCK_ZONE(zone);
01336         REQUIRE(zone->type == dns_zone_none || zone->type == type);
01337         zone->type = type;
01338 
01339         if (zone->strnamerd != NULL)
01340                 isc_mem_free(zone->mctx, zone->strnamerd);
01341 
01342         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
01343         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
01344         UNLOCK_ZONE(zone);
01345 }
01346 
01347 static void
01348 zone_freedbargs(dns_zone_t *zone) {
01349         unsigned int i;
01350 
01351         /* Free the old database argument list. */
01352         if (zone->db_argv != NULL) {
01353                 for (i = 0; i < zone->db_argc; i++)
01354                         isc_mem_free(zone->mctx, zone->db_argv[i]);
01355                 isc_mem_put(zone->mctx, zone->db_argv,
01356                             zone->db_argc * sizeof(*zone->db_argv));
01357         }
01358         zone->db_argc = 0;
01359         zone->db_argv = NULL;
01360 }
01361 
01362 isc_result_t
01363 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
01364         size_t size = 0;
01365         unsigned int i;
01366         isc_result_t result = ISC_R_SUCCESS;
01367         void *mem;
01368         char **tmp, *tmp2;
01369 
01370         REQUIRE(DNS_ZONE_VALID(zone));
01371         REQUIRE(argv != NULL && *argv == NULL);
01372 
01373         LOCK_ZONE(zone);
01374         size = (zone->db_argc + 1) * sizeof(char *);
01375         for (i = 0; i < zone->db_argc; i++)
01376                 size += strlen(zone->db_argv[i]) + 1;
01377         mem = isc_mem_allocate(mctx, size);
01378         if (mem != NULL) {
01379                 tmp = mem;
01380                 tmp2 = mem;
01381                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
01382                 for (i = 0; i < zone->db_argc; i++) {
01383                         *tmp++ = tmp2;
01384                         strcpy(tmp2, zone->db_argv[i]);
01385                         tmp2 += strlen(tmp2) + 1;
01386                 }
01387                 *tmp = NULL;
01388         } else
01389                 result = ISC_R_NOMEMORY;
01390         UNLOCK_ZONE(zone);
01391         *argv = mem;
01392         return (result);
01393 }
01394 
01395 isc_result_t
01396 dns_zone_setdbtype(dns_zone_t *zone,
01397                    unsigned int dbargc, const char * const *dbargv) {
01398         isc_result_t result = ISC_R_SUCCESS;
01399         char **new = NULL;
01400         unsigned int i;
01401 
01402         REQUIRE(DNS_ZONE_VALID(zone));
01403         REQUIRE(dbargc >= 1);
01404         REQUIRE(dbargv != NULL);
01405 
01406         LOCK_ZONE(zone);
01407 
01408         /* Set up a new database argument list. */
01409         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
01410         if (new == NULL)
01411                 goto nomem;
01412         for (i = 0; i < dbargc; i++)
01413                 new[i] = NULL;
01414         for (i = 0; i < dbargc; i++) {
01415                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
01416                 if (new[i] == NULL)
01417                         goto nomem;
01418         }
01419 
01420         /* Free the old list. */
01421         zone_freedbargs(zone);
01422 
01423         zone->db_argc = dbargc;
01424         zone->db_argv = new;
01425         result = ISC_R_SUCCESS;
01426         goto unlock;
01427 
01428  nomem:
01429         if (new != NULL) {
01430                 for (i = 0; i < dbargc; i++)
01431                         if (new[i] != NULL)
01432                                 isc_mem_free(zone->mctx, new[i]);
01433                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
01434         }
01435         result = ISC_R_NOMEMORY;
01436 
01437  unlock:
01438         UNLOCK_ZONE(zone);
01439         return (result);
01440 }
01441 
01442 void
01443 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
01444         char namebuf[1024];
01445         REQUIRE(DNS_ZONE_VALID(zone));
01446 
01447         LOCK_ZONE(zone);
01448         INSIST(zone != zone->raw);
01449         if (zone->view != NULL)
01450                 dns_view_weakdetach(&zone->view);
01451         dns_view_weakattach(view, &zone->view);
01452 
01453         if (zone->strviewname != NULL)
01454                 isc_mem_free(zone->mctx, zone->strviewname);
01455         if (zone->strnamerd != NULL)
01456                 isc_mem_free(zone->mctx, zone->strnamerd);
01457 
01458         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
01459         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
01460         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
01461         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
01462 
01463         if (inline_secure(zone))
01464                 dns_zone_setview(zone->raw, view);
01465 
01466         UNLOCK_ZONE(zone);
01467 }
01468 
01469 dns_view_t *
01470 dns_zone_getview(dns_zone_t *zone) {
01471         REQUIRE(DNS_ZONE_VALID(zone));
01472 
01473         return (zone->view);
01474 }
01475 
01476 
01477 isc_result_t
01478 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
01479         isc_result_t result;
01480         char namebuf[1024];
01481 
01482         REQUIRE(DNS_ZONE_VALID(zone));
01483         REQUIRE(origin != NULL);
01484 
01485         LOCK_ZONE(zone);
01486         INSIST(zone != zone->raw);
01487         if (dns_name_dynamic(&zone->origin)) {
01488                 dns_name_free(&zone->origin, zone->mctx);
01489                 dns_name_init(&zone->origin, NULL);
01490         }
01491         result = dns_name_dup(origin, zone->mctx, &zone->origin);
01492 
01493         if (zone->strnamerd != NULL)
01494                 isc_mem_free(zone->mctx, zone->strnamerd);
01495         if (zone->strname != NULL)
01496                 isc_mem_free(zone->mctx, zone->strname);
01497 
01498         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
01499         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
01500         zone_name_tostr(zone, namebuf, sizeof namebuf);
01501         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
01502 
01503         if (result == ISC_R_SUCCESS && inline_secure(zone))
01504                 result = dns_zone_setorigin(zone->raw, origin);
01505         UNLOCK_ZONE(zone);
01506         return (result);
01507 }
01508 
01509 void
01510 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
01511         REQUIRE(DNS_ZONE_VALID(zone));
01512         REQUIRE(acache != NULL);
01513 
01514         LOCK_ZONE(zone);
01515         if (zone->acache != NULL)
01516                 dns_acache_detach(&zone->acache);
01517         dns_acache_attach(acache, &zone->acache);
01518         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
01519         if (zone->db != NULL) {
01520                 isc_result_t result;
01521 
01522                 /*
01523                  * If the zone reuses an existing DB, the DB needs to be
01524                  * set in the acache explicitly.  We can safely ignore the
01525                  * case where the DB is already set.  If other error happens,
01526                  * the acache will not work effectively.
01527                  */
01528                 result = dns_acache_setdb(acache, zone->db);
01529                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
01530                         UNEXPECTED_ERROR(__FILE__, __LINE__,
01531                                          "dns_acache_setdb() failed: %s",
01532                                          isc_result_totext(result));
01533                 }
01534         }
01535         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
01536         UNLOCK_ZONE(zone);
01537 }
01538 
01539 static isc_result_t
01540 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
01541         char *copy;
01542 
01543         if (value != NULL) {
01544                 copy = isc_mem_strdup(zone->mctx, value);
01545                 if (copy == NULL)
01546                         return (ISC_R_NOMEMORY);
01547         } else {
01548                 copy = NULL;
01549         }
01550 
01551         if (*field != NULL)
01552                 isc_mem_free(zone->mctx, *field);
01553 
01554         *field = copy;
01555         return (ISC_R_SUCCESS);
01556 }
01557 
01558 isc_result_t
01559 dns_zone_setfile(dns_zone_t *zone, const char *file) {
01560         return (dns_zone_setfile3(zone, file, dns_masterformat_text,
01561                                   &dns_master_style_default));
01562 }
01563 
01564 isc_result_t
01565 dns_zone_setfile2(dns_zone_t *zone, const char *file,
01566                   dns_masterformat_t format)
01567 {
01568         return (dns_zone_setfile3(zone, file, format,
01569                                   &dns_master_style_default));
01570 }
01571 
01572 isc_result_t
01573 dns_zone_setfile3(dns_zone_t *zone, const char *file,
01574                   dns_masterformat_t format,
01575                   const dns_master_style_t *style)
01576 {
01577         isc_result_t result = ISC_R_SUCCESS;
01578 
01579         REQUIRE(DNS_ZONE_VALID(zone));
01580 
01581         LOCK_ZONE(zone);
01582         result = dns_zone_setstring(zone, &zone->masterfile, file);
01583         if (result == ISC_R_SUCCESS) {
01584                 zone->masterformat = format;
01585                 if (format == dns_masterformat_text)
01586                         zone->masterstyle = style;
01587                 result = default_journal(zone);
01588         }
01589         UNLOCK_ZONE(zone);
01590 
01591         return (result);
01592 }
01593 
01594 const char *
01595 dns_zone_getfile(dns_zone_t *zone) {
01596         REQUIRE(DNS_ZONE_VALID(zone));
01597 
01598         return (zone->masterfile);
01599 }
01600 
01601 dns_ttl_t
01602 dns_zone_getmaxttl(dns_zone_t *zone) {
01603         REQUIRE(DNS_ZONE_VALID(zone));
01604 
01605         return (zone->maxttl);
01606 }
01607 
01608 void
01609 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
01610         REQUIRE(DNS_ZONE_VALID(zone));
01611 
01612         LOCK_ZONE(zone);
01613         if (maxttl != 0)
01614                 zone->options2 |= DNS_ZONEOPT2_CHECKTTL;
01615         else
01616                 zone->options2 &= ~DNS_ZONEOPT2_CHECKTTL;
01617         zone->maxttl = maxttl;
01618         UNLOCK_ZONE(zone);
01619 
01620         return;
01621 }
01622 
01623 static isc_result_t
01624 default_journal(dns_zone_t *zone) {
01625         isc_result_t result;
01626         char *journal;
01627 
01628         REQUIRE(DNS_ZONE_VALID(zone));
01629         REQUIRE(LOCKED_ZONE(zone));
01630 
01631         if (zone->masterfile != NULL) {
01632                 /* Calculate string length including '\0'. */
01633                 int len = strlen(zone->masterfile) + sizeof(".jnl");
01634                 journal = isc_mem_allocate(zone->mctx, len);
01635                 if (journal == NULL)
01636                         return (ISC_R_NOMEMORY);
01637                 strcpy(journal, zone->masterfile);
01638                 strcat(journal, ".jnl");
01639         } else {
01640                 journal = NULL;
01641         }
01642         result = dns_zone_setstring(zone, &zone->journal, journal);
01643         if (journal != NULL)
01644                 isc_mem_free(zone->mctx, journal);
01645         return (result);
01646 }
01647 
01648 isc_result_t
01649 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
01650         isc_result_t result = ISC_R_SUCCESS;
01651 
01652         REQUIRE(DNS_ZONE_VALID(zone));
01653 
01654         LOCK_ZONE(zone);
01655         result = dns_zone_setstring(zone, &zone->journal, myjournal);
01656         UNLOCK_ZONE(zone);
01657 
01658         return (result);
01659 }
01660 
01661 char *
01662 dns_zone_getjournal(dns_zone_t *zone) {
01663         REQUIRE(DNS_ZONE_VALID(zone));
01664 
01665         return (zone->journal);
01666 }
01667 
01668 /*
01669  * Return true iff the zone is "dynamic", in the sense that the zone's
01670  * master file (if any) is written by the server, rather than being
01671  * updated manually and read by the server.
01672  *
01673  * This is true for slave zones, stub zones, key zones, and zones that
01674  * allow dynamic updates either by having an update policy ("ssutable")
01675  * or an "allow-update" ACL with a value other than exactly "{ none; }".
01676  */
01677 isc_boolean_t
01678 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
01679         REQUIRE(DNS_ZONE_VALID(zone));
01680 
01681         if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
01682             zone->type == dns_zone_key ||
01683             (zone->type == dns_zone_redirect && zone->masters != NULL))
01684                 return (ISC_TRUE);
01685 
01686         /* If !ignore_freeze, we need check whether updates are disabled.  */
01687         if (zone->type == dns_zone_master &&
01688             (!zone->update_disabled || ignore_freeze) &&
01689             ((zone->ssutable != NULL) ||
01690              (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
01691                 return (ISC_TRUE);
01692 
01693         return (ISC_FALSE);
01694 
01695 }
01696 
01697 /*
01698  * Set the response policy index and information for a zone.
01699  */
01700 isc_result_t
01701 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
01702                     dns_rpz_num_t rpz_num)
01703 {
01704         /*
01705          * Only RBTDB zones can be used for response policy zones,
01706          * because only they have the code to load the create the summary data.
01707          * Only zones that are loaded instead of mmap()ed create the
01708          * summary data and so can be policy zones.
01709          */
01710         if (strcmp(zone->db_argv[0], "rbt") != 0 &&
01711             strcmp(zone->db_argv[0], "rbt64") != 0)
01712                 return (ISC_R_NOTIMPLEMENTED);
01713 
01714         /*
01715          * This must happen only once or be redundant.
01716          */
01717         LOCK_ZONE(zone);
01718         if (zone->rpzs != NULL) {
01719                 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
01720         } else {
01721                 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
01722                 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
01723                 zone->rpz_num = rpz_num;
01724         }
01725         rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
01726         UNLOCK_ZONE(zone);
01727 
01728         return (ISC_R_SUCCESS);
01729 }
01730 
01731 dns_rpz_num_t
01732 dns_zone_get_rpz_num(dns_zone_t *zone) {
01733         return (zone->rpz_num);
01734 }
01735 
01736 /*
01737  * If a zone is a response policy zone, mark its new database.
01738  */
01739 void
01740 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
01741         if (zone->rpz_num != DNS_RPZ_INVALID_NUM) {
01742                 REQUIRE(zone->rpzs != NULL);
01743                 dns_db_rpz_attach(db, zone->rpzs, zone->rpz_num);
01744         }
01745 }
01746 
01747 static isc_boolean_t
01748 zone_touched(dns_zone_t *zone) {
01749         isc_result_t result;
01750         isc_time_t modtime;
01751         dns_include_t *include;
01752 
01753         REQUIRE(DNS_ZONE_VALID(zone));
01754 
01755         result = isc_file_getmodtime(zone->masterfile, &modtime);
01756         if (result != ISC_R_SUCCESS ||
01757             isc_time_compare(&modtime, &zone->loadtime) > 0)
01758         {
01759                 zone->loadtime = modtime;
01760                 return (ISC_TRUE);
01761         }
01762 
01763         for (include = ISC_LIST_HEAD(zone->includes);
01764              include != NULL;
01765              include = ISC_LIST_NEXT(include, link))
01766         {
01767                 result = isc_file_getmodtime(include->name, &modtime);
01768                 if (result != ISC_R_SUCCESS ||
01769                     isc_time_compare(&modtime, &include->filetime) > 0)
01770                         return (ISC_TRUE);
01771         }
01772 
01773 
01774         return (ISC_FALSE);
01775 }
01776 
01777 static isc_result_t
01778 zone_load(dns_zone_t *zone, unsigned int flags, isc_boolean_t locked) {
01779         isc_result_t result;
01780         isc_time_t now;
01781         isc_time_t loadtime;
01782         dns_db_t *db = NULL;
01783         isc_boolean_t rbt, hasraw;
01784 
01785         REQUIRE(DNS_ZONE_VALID(zone));
01786 
01787         if (!locked)
01788                 LOCK_ZONE(zone);
01789 
01790         INSIST(zone != zone->raw);
01791         hasraw = inline_secure(zone);
01792         if (hasraw) {
01793                 result = zone_load(zone->raw, flags, ISC_FALSE);
01794                 if (result != ISC_R_SUCCESS) {
01795                         if (!locked)
01796                                 UNLOCK_ZONE(zone);
01797                         return(result);
01798                 }
01799                 LOCK_ZONE(zone->raw);
01800         }
01801 
01802         TIME_NOW(&now);
01803 
01804         INSIST(zone->type != dns_zone_none);
01805 
01806         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
01807                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
01808                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
01809                 result = DNS_R_CONTINUE;
01810                 goto cleanup;
01811         }
01812 
01813         INSIST(zone->db_argc >= 1);
01814 
01815         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
01816               strcmp(zone->db_argv[0], "rbt64") == 0;
01817 
01818         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
01819                 /*
01820                  * The zone has no master file configured.
01821                  */
01822                 result = ISC_R_SUCCESS;
01823                 goto cleanup;
01824         }
01825 
01826         if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
01827                 /*
01828                  * This is a slave, stub, or dynamically updated
01829                  * zone being reloaded.  Do nothing - the database
01830                  * we already have is guaranteed to be up-to-date.
01831                  */
01832                 if (zone->type == dns_zone_master)
01833                         result = DNS_R_DYNAMIC;
01834                 else
01835                         result = ISC_R_SUCCESS;
01836                 goto cleanup;
01837         }
01838 
01839         /*
01840          * Store the current time before the zone is loaded, so that if the
01841          * file changes between the time of the load and the time that
01842          * zone->loadtime is set, then the file will still be reloaded
01843          * the next time dns_zone_load is called.
01844          */
01845         TIME_NOW(&loadtime);
01846 
01847         /*
01848          * Don't do the load if the file that stores the zone is older
01849          * than the last time the zone was loaded.  If the zone has not
01850          * been loaded yet, zone->loadtime will be the epoch.
01851          */
01852         if (zone->masterfile != NULL) {
01853                 /*
01854                  * The file is already loaded.  If we are just doing a
01855                  * "rndc reconfig", we are done.
01856                  */
01857                 if (!isc_time_isepoch(&zone->loadtime) &&
01858                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
01859                         result = ISC_R_SUCCESS;
01860                         goto cleanup;
01861                 }
01862 
01863                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
01864                     !zone_touched(zone))
01865                 {
01866                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
01867                                      "skipping load: master file "
01868                                      "older than last load");
01869                         result = DNS_R_UPTODATE;
01870                         goto cleanup;
01871                 }
01872         }
01873 
01874         /*
01875          * Built in zones (with the exception of empty zones) don't need
01876          * to be reloaded.
01877          */
01878         if (zone->type == dns_zone_master &&
01879             strcmp(zone->db_argv[0], "_builtin") == 0 &&
01880             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
01881             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
01882                 result = ISC_R_SUCCESS;
01883                 goto cleanup;
01884         }
01885 
01886         /*
01887          * Zones associated with a DLZ don't need to be loaded either,
01888          * but we need to associate the database with the zone object.
01889          */
01890         if (strcmp(zone->db_argv[0], "dlz") == 0) {
01891                 dns_dlzdb_t *dlzdb;
01892                 dns_dlzfindzone_t findzone;
01893 
01894                 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
01895                      dlzdb != NULL;
01896                      dlzdb = ISC_LIST_NEXT(dlzdb, link))
01897                 {
01898                         INSIST(DNS_DLZ_VALID(dlzdb));
01899                         if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
01900                                 break;
01901                 }
01902 
01903                 if (dlzdb == NULL) {
01904                         dns_zone_log(zone, ISC_LOG_ERROR,
01905                                      "DLZ %s does not exist or is set "
01906                                      "to 'search yes;'", zone->db_argv[1]);
01907                         result = ISC_R_NOTFOUND;
01908                         goto cleanup;
01909                 }
01910 
01911                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
01912                 /* ask SDLZ driver if the zone is supported */
01913                 findzone = dlzdb->implementation->methods->findzone;
01914                 result = (*findzone)(dlzdb->implementation->driverarg,
01915                                      dlzdb->dbdata, dlzdb->mctx,
01916                                      zone->view->rdclass, &zone->origin,
01917                                      NULL, NULL, &db);
01918                 if (result != ISC_R_NOTFOUND) {
01919                         if (zone->db != NULL)
01920                                 zone_detachdb(zone);
01921                         zone_attachdb(zone, db);
01922                         dns_db_detach(&db);
01923                         result = ISC_R_SUCCESS;
01924                 }
01925                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
01926 
01927                 if (result == ISC_R_SUCCESS) {
01928                         if (dlzdb->configure_callback == NULL)
01929                                 goto cleanup;
01930 
01931                         result = (*dlzdb->configure_callback)(zone->view,
01932                                                               dlzdb, zone);
01933                         if (result != ISC_R_SUCCESS)
01934                                 dns_zone_log(zone, ISC_LOG_ERROR,
01935                                              "DLZ configuration callback: %s",
01936                                              isc_result_totext(result));
01937                 }
01938                 goto cleanup;
01939         }
01940 
01941         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
01942              (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
01943             rbt) {
01944                 if (zone->masterfile == NULL ||
01945                     !isc_file_exists(zone->masterfile)) {
01946                         if (zone->masterfile != NULL) {
01947                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
01948                                              "no master file");
01949                         }
01950                         zone->refreshtime = now;
01951                         if (zone->task != NULL)
01952                                 zone_settimer(zone, &now);
01953                         result = ISC_R_SUCCESS;
01954                         goto cleanup;
01955                 }
01956         }
01957 
01958         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
01959 
01960         result = dns_db_create(zone->mctx, zone->db_argv[0],
01961                                &zone->origin, (zone->type == dns_zone_stub) ?
01962                                dns_dbtype_stub : dns_dbtype_zone,
01963                                zone->rdclass,
01964                                zone->db_argc - 1, zone->db_argv + 1,
01965                                &db);
01966 
01967         if (result != ISC_R_SUCCESS) {
01968                 dns_zone_log(zone, ISC_LOG_ERROR,
01969                              "loading zone: creating database: %s",
01970                              isc_result_totext(result));
01971                 goto cleanup;
01972         }
01973         dns_db_settask(db, zone->task);
01974 
01975         if (! dns_db_ispersistent(db)) {
01976                 if (zone->masterfile != NULL) {
01977                         result = zone_startload(db, zone, loadtime);
01978                 } else {
01979                         result = DNS_R_NOMASTERFILE;
01980                         if (zone->type == dns_zone_master ||
01981                             (zone->type == dns_zone_redirect &&
01982                              zone->masters == NULL)) {
01983                                 dns_zone_log(zone, ISC_LOG_ERROR,
01984                                              "loading zone: "
01985                                              "no master file configured");
01986                                 goto cleanup;
01987                         }
01988                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
01989                                      "no master file configured: continuing");
01990                 }
01991         }
01992 
01993         if (result == DNS_R_CONTINUE) {
01994                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
01995                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
01996                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
01997                 goto cleanup;
01998         }
01999 
02000         result = zone_postload(zone, db, loadtime, result);
02001 
02002  cleanup:
02003         if (hasraw)
02004                 UNLOCK_ZONE(zone->raw);
02005         if (!locked)
02006                 UNLOCK_ZONE(zone);
02007         if (db != NULL)
02008                 dns_db_detach(&db);
02009         return (result);
02010 }
02011 
02012 isc_result_t
02013 dns_zone_load(dns_zone_t *zone) {
02014         return (zone_load(zone, 0, ISC_FALSE));
02015 }
02016 
02017 isc_result_t
02018 dns_zone_loadnew(dns_zone_t *zone) {
02019         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT, ISC_FALSE));
02020 }
02021 
02022 static void
02023 zone_asyncload(isc_task_t *task, isc_event_t *event) {
02024         dns_asyncload_t *asl = event->ev_arg;
02025         dns_zone_t *zone = asl->zone;
02026         isc_result_t result = ISC_R_SUCCESS;
02027         isc_boolean_t load_pending;
02028 
02029         UNUSED(task);
02030 
02031         REQUIRE(DNS_ZONE_VALID(zone));
02032 
02033         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
02034                 result = ISC_R_CANCELED;
02035         isc_event_free(&event);
02036 
02037         if (result == ISC_R_CANCELED)
02038                 goto cleanup;
02039 
02040         /* Make sure load is still pending */
02041         LOCK_ZONE(zone);
02042         load_pending = ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
02043 
02044         if (!load_pending) {
02045                 UNLOCK_ZONE(zone);
02046                 goto cleanup;
02047         }
02048 
02049         zone_load(zone, 0, ISC_TRUE);
02050 
02051         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
02052         UNLOCK_ZONE(zone);
02053 
02054         /* Inform the zone table we've finished loading */
02055         if (asl->loaded != NULL)
02056                 (asl->loaded)(asl->loaded_arg, zone, task);
02057 
02058  cleanup:
02059         isc_mem_put(zone->mctx, asl, sizeof (*asl));
02060         dns_zone_idetach(&zone);
02061 }
02062 
02063 isc_result_t
02064 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
02065         isc_event_t *e;
02066         dns_asyncload_t *asl = NULL;
02067         isc_result_t result = ISC_R_SUCCESS;
02068 
02069         REQUIRE(DNS_ZONE_VALID(zone));
02070 
02071         if (zone->zmgr == NULL)
02072                 return (ISC_R_FAILURE);
02073 
02074         /* If we already have a load pending, stop now */
02075         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
02076                 return (ISC_R_ALREADYRUNNING);
02077 
02078         asl = isc_mem_get(zone->mctx, sizeof (*asl));
02079         if (asl == NULL)
02080                 CHECK(ISC_R_NOMEMORY);
02081 
02082         asl->zone = NULL;
02083         asl->loaded = done;
02084         asl->loaded_arg = arg;
02085 
02086         e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
02087                                DNS_EVENT_ZONELOAD,
02088                                zone_asyncload, asl,
02089                                sizeof(isc_event_t));
02090         if (e == NULL)
02091                 CHECK(ISC_R_NOMEMORY);
02092 
02093         LOCK_ZONE(zone);
02094         zone_iattach(zone, &asl->zone);
02095         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
02096         isc_task_send(zone->loadtask, &e);
02097         UNLOCK_ZONE(zone);
02098 
02099         return (ISC_R_SUCCESS);
02100 
02101   failure:
02102         if (asl != NULL)
02103                 isc_mem_put(zone->mctx, asl, sizeof (*asl));
02104         return (result);
02105 }
02106 
02107 isc_boolean_t
02108 dns__zone_loadpending(dns_zone_t *zone) {
02109         REQUIRE(DNS_ZONE_VALID(zone));
02110 
02111         return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
02112 }
02113 
02114 isc_result_t
02115 dns_zone_loadandthaw(dns_zone_t *zone) {
02116         isc_result_t result;
02117 
02118         if (inline_raw(zone))
02119                 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
02120                                    ISC_FALSE);
02121         else
02122                 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, ISC_FALSE);
02123 
02124         switch (result) {
02125         case DNS_R_CONTINUE:
02126                 /* Deferred thaw. */
02127                 break;
02128         case DNS_R_UPTODATE:
02129         case ISC_R_SUCCESS:
02130         case DNS_R_SEENINCLUDE:
02131                 zone->update_disabled = ISC_FALSE;
02132                 break;
02133         case DNS_R_NOMASTERFILE:
02134                 zone->update_disabled = ISC_FALSE;
02135                 break;
02136         default:
02137                 /* Error, remain in disabled state. */
02138                 break;
02139         }
02140         return (result);
02141 }
02142 
02143 static unsigned int
02144 get_master_options(dns_zone_t *zone) {
02145         unsigned int options;
02146 
02147         options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
02148         if (zone->type == dns_zone_slave ||
02149             (zone->type == dns_zone_redirect && zone->masters == NULL))
02150                 options |= DNS_MASTER_SLAVE;
02151         if (zone->type == dns_zone_key)
02152                 options |= DNS_MASTER_KEY;
02153         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
02154                 options |= DNS_MASTER_CHECKNS;
02155         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
02156                 options |= DNS_MASTER_FATALNS;
02157         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
02158                 options |= DNS_MASTER_CHECKNAMES;
02159         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
02160                 options |= DNS_MASTER_CHECKNAMESFAIL;
02161         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
02162                 options |= DNS_MASTER_CHECKMX;
02163         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
02164                 options |= DNS_MASTER_CHECKMXFAIL;
02165         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
02166                 options |= DNS_MASTER_CHECKWILDCARD;
02167         if (DNS_ZONE_OPTION2(zone, DNS_ZONEOPT2_CHECKTTL))
02168                 options |= DNS_MASTER_CHECKTTL;
02169         return (options);
02170 }
02171 
02172 static void
02173 zone_registerinclude(const char *filename, void *arg) {
02174         isc_result_t result;
02175         dns_zone_t *zone = (dns_zone_t *) arg;
02176         dns_include_t *inc = NULL;
02177 
02178         REQUIRE(DNS_ZONE_VALID(zone));
02179 
02180         if (filename == NULL)
02181                 return;
02182 
02183         /*
02184          * Suppress duplicates.
02185          */
02186         for (inc = ISC_LIST_HEAD(zone->newincludes);
02187              inc != NULL;
02188              inc = ISC_LIST_NEXT(inc, link))
02189                 if (strcmp(filename, inc->name) == 0)
02190                         return;
02191 
02192         inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
02193         if (inc == NULL)
02194                 return;
02195         inc->name = isc_mem_strdup(zone->mctx, filename);
02196         if (inc->name == NULL) {
02197                 isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
02198                 return;
02199         }
02200         ISC_LINK_INIT(inc, link);
02201 
02202         result = isc_file_getmodtime(filename, &inc->filetime);
02203         if (result != ISC_R_SUCCESS)
02204                 isc_time_settoepoch(&inc->filetime);
02205 
02206         ISC_LIST_APPEND(zone->newincludes, inc, link);
02207 }
02208 
02209 static void
02210 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
02211         dns_load_t *load = event->ev_arg;
02212         isc_result_t result = ISC_R_SUCCESS;
02213         unsigned int options;
02214 
02215         REQUIRE(DNS_LOAD_VALID(load));
02216 
02217         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
02218                 result = ISC_R_CANCELED;
02219         isc_event_free(&event);
02220         if (result == ISC_R_CANCELED)
02221                 goto fail;
02222 
02223         options = get_master_options(load->zone);
02224 
02225         result = dns_master_loadfileinc5(load->zone->masterfile,
02226                                          dns_db_origin(load->db),
02227                                          dns_db_origin(load->db),
02228                                          load->zone->rdclass, options, 0,
02229                                          &load->callbacks, task,
02230                                          zone_loaddone, load,
02231                                          &load->zone->lctx,
02232                                          zone_registerinclude,
02233                                          load->zone, load->zone->mctx,
02234                                          load->zone->masterformat,
02235                                          load->zone->maxttl);
02236         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
02237             result != DNS_R_SEENINCLUDE)
02238                 goto fail;
02239         return;
02240 
02241  fail:
02242         zone_loaddone(load, result);
02243 }
02244 
02245 static void
02246 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
02247         isc_result_t result;
02248         unsigned int soacount;
02249 
02250         LOCK(&raw->lock);
02251         if (raw->db != NULL) {
02252                 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
02253                                           &rawdata->sourceserial,
02254                                           NULL, NULL, NULL, NULL,
02255                                           NULL);
02256                 if (result == ISC_R_SUCCESS && soacount > 0U)
02257                         rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
02258         }
02259         UNLOCK(&raw->lock);
02260 }
02261 
02262 static void
02263 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
02264         const char me[] = "zone_gotwritehandle";
02265         dns_zone_t *zone = event->ev_arg;
02266         isc_result_t result = ISC_R_SUCCESS;
02267         dns_dbversion_t *version = NULL;
02268         dns_masterrawheader_t rawdata;
02269 
02270         REQUIRE(DNS_ZONE_VALID(zone));
02271         INSIST(task == zone->task);
02272         ENTER;
02273 
02274         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
02275                 result = ISC_R_CANCELED;
02276         isc_event_free(&event);
02277         if (result == ISC_R_CANCELED)
02278                 goto fail;
02279 
02280         LOCK_ZONE(zone);
02281         INSIST(zone != zone->raw);
02282         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
02283         if (zone->db != NULL) {
02284                 const dns_master_style_t *output_style;
02285 
02286                 dns_db_currentversion(zone->db, &version);
02287                 dns_master_initrawheader(&rawdata);
02288                 if (inline_secure(zone))
02289                         get_raw_serial(zone->raw, &rawdata);
02290                 if (zone->type == dns_zone_key)
02291                         output_style = &dns_master_style_keyzone;
02292                 else if (zone->masterstyle != NULL)
02293                         output_style = zone->masterstyle;
02294                 else
02295                         output_style = &dns_master_style_default;
02296                 result = dns_master_dumpinc3(zone->mctx, zone->db, version,
02297                                              output_style, zone->masterfile,
02298                                              zone->task, dump_done, zone,                                                    &zone->dctx, zone->masterformat,
02299                                              &rawdata);
02300                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
02301         } else
02302                 result = ISC_R_CANCELED;
02303         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
02304         UNLOCK_ZONE(zone);
02305         if (result != DNS_R_CONTINUE)
02306                 goto fail;
02307         return;
02308 
02309  fail:
02310         dump_done(zone, result);
02311 }
02312 
02313 /*
02314  * Save the raw serial number for inline-signing zones.
02315  * (XXX: Other information from the header will be used
02316  * for other purposes in the future, but for now this is
02317  * all we're interested in.)
02318  */
02319 static void
02320 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
02321         if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
02322                 return;
02323 
02324         zone->sourceserial = header->sourceserial;
02325         zone->sourceserialset = ISC_TRUE;
02326 }
02327 
02328 void
02329 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
02330         if (zone == NULL)
02331                 return;
02332 
02333         LOCK_ZONE(zone);
02334         zone_setrawdata(zone, header);
02335         UNLOCK_ZONE(zone);
02336 }
02337 
02338 static isc_result_t
02339 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
02340         dns_load_t *load;
02341         isc_result_t result;
02342         isc_result_t tresult;
02343         unsigned int options;
02344 
02345         dns_zone_rpz_enable_db(zone, db);
02346         options = get_master_options(zone);
02347         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
02348                 options |= DNS_MASTER_MANYERRORS;
02349 
02350         if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
02351                 load = isc_mem_get(zone->mctx, sizeof(*load));
02352                 if (load == NULL)
02353                         return (ISC_R_NOMEMORY);
02354 
02355                 load->mctx = NULL;
02356                 load->zone = NULL;
02357                 load->db = NULL;
02358                 load->loadtime = loadtime;
02359                 load->magic = LOAD_MAGIC;
02360 
02361                 isc_mem_attach(zone->mctx, &load->mctx);
02362                 zone_iattach(zone, &load->zone);
02363                 dns_db_attach(db, &load->db);
02364                 dns_rdatacallbacks_init(&load->callbacks);
02365                 load->callbacks.rawdata = zone_setrawdata;
02366                 zone_iattach(zone, &load->callbacks.zone);
02367                 result = dns_db_beginload(db, &load->callbacks);
02368                 if (result != ISC_R_SUCCESS)
02369                         goto cleanup;
02370                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
02371                                        zone_gotreadhandle, load,
02372                                        &zone->readio);
02373                 if (result != ISC_R_SUCCESS) {
02374                         /*
02375                          * We can't report multiple errors so ignore
02376                          * the result of dns_db_endload().
02377                          */
02378                         (void)dns_db_endload(load->db, &load->callbacks);
02379                         goto cleanup;
02380                 } else
02381                         result = DNS_R_CONTINUE;
02382         } else {
02383                 dns_rdatacallbacks_t callbacks;
02384 
02385                 dns_rdatacallbacks_init(&callbacks);
02386                 callbacks.rawdata = zone_setrawdata;
02387                 zone_iattach(zone, &callbacks.zone);
02388                 result = dns_db_beginload(db, &callbacks);
02389                 if (result != ISC_R_SUCCESS) {
02390                         zone_idetach(&callbacks.zone);
02391                         return (result);
02392                 }
02393                 result = dns_master_loadfile5(zone->masterfile,
02394                                               &zone->origin, &zone->origin,
02395                                               zone->rdclass, options, 0,
02396                                               &callbacks,
02397                                               zone_registerinclude,
02398                                               zone, zone->mctx,
02399                                               zone->masterformat,
02400                                               zone->maxttl);
02401                 tresult = dns_db_endload(db, &callbacks);
02402                 if (result == ISC_R_SUCCESS)
02403                         result = tresult;
02404                 zone_idetach(&callbacks.zone);
02405         }
02406 
02407         return (result);
02408 
02409  cleanup:
02410         load->magic = 0;
02411         dns_db_detach(&load->db);
02412         zone_idetach(&load->zone);
02413         zone_idetach(&load->callbacks.zone);
02414         isc_mem_detach(&load->mctx);
02415         isc_mem_put(zone->mctx, load, sizeof(*load));
02416         return (result);
02417 }
02418 
02419 static isc_boolean_t
02420 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
02421               dns_name_t *owner)
02422 {
02423         isc_result_t result;
02424         char ownerbuf[DNS_NAME_FORMATSIZE];
02425         char namebuf[DNS_NAME_FORMATSIZE];
02426         char altbuf[DNS_NAME_FORMATSIZE];
02427         dns_fixedname_t fixed;
02428         dns_name_t *foundname;
02429         int level;
02430 
02431         /*
02432          * "." means the services does not exist.
02433          */
02434         if (dns_name_equal(name, dns_rootname))
02435                 return (ISC_TRUE);
02436 
02437         /*
02438          * Outside of zone.
02439          */
02440         if (!dns_name_issubdomain(name, &zone->origin)) {
02441                 if (zone->checkmx != NULL)
02442                         return ((zone->checkmx)(zone, name, owner));
02443                 return (ISC_TRUE);
02444         }
02445 
02446         if (zone->type == dns_zone_master)
02447                 level = ISC_LOG_ERROR;
02448         else
02449                 level = ISC_LOG_WARNING;
02450 
02451         dns_fixedname_init(&fixed);
02452         foundname = dns_fixedname_name(&fixed);
02453 
02454         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
02455                              0, 0, NULL, foundname, NULL, NULL);
02456         if (result == ISC_R_SUCCESS)
02457                 return (ISC_TRUE);
02458 
02459         if (result == DNS_R_NXRRSET) {
02460                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
02461                                      0, 0, NULL, foundname, NULL, NULL);
02462                 if (result == ISC_R_SUCCESS)
02463                         return (ISC_TRUE);
02464         }
02465 
02466         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
02467         dns_name_format(name, namebuf, sizeof namebuf);
02468         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
02469             result == DNS_R_EMPTYNAME) {
02470                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
02471                         level = ISC_LOG_WARNING;
02472                 dns_zone_log(zone, level,
02473                              "%s/MX '%s' has no address records (A or AAAA)",
02474                              ownerbuf, namebuf);
02475                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
02476         }
02477 
02478         if (result == DNS_R_CNAME) {
02479                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
02480                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
02481                         level = ISC_LOG_WARNING;
02482                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
02483                         dns_zone_log(zone, level,
02484                                      "%s/MX '%s' is a CNAME (illegal)",
02485                                      ownerbuf, namebuf);
02486                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
02487         }
02488 
02489         if (result == DNS_R_DNAME) {
02490                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
02491                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
02492                         level = ISC_LOG_WARNING;
02493                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
02494                         dns_name_format(foundname, altbuf, sizeof altbuf);
02495                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
02496                                      " '%s' (illegal)", ownerbuf, namebuf,
02497                                      altbuf);
02498                 }
02499                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
02500         }
02501 
02502         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
02503                 return ((zone->checkmx)(zone, name, owner));
02504 
02505         return (ISC_TRUE);
02506 }
02507 
02508 static isc_boolean_t
02509 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
02510                dns_name_t *owner)
02511 {
02512         isc_result_t result;
02513         char ownerbuf[DNS_NAME_FORMATSIZE];
02514         char namebuf[DNS_NAME_FORMATSIZE];
02515         char altbuf[DNS_NAME_FORMATSIZE];
02516         dns_fixedname_t fixed;
02517         dns_name_t *foundname;
02518         int level;
02519 
02520         /*
02521          * "." means the services does not exist.
02522          */
02523         if (dns_name_equal(name, dns_rootname))
02524                 return (ISC_TRUE);
02525 
02526         /*
02527          * Outside of zone.
02528          */
02529         if (!dns_name_issubdomain(name, &zone->origin)) {
02530                 if (zone->checksrv != NULL)
02531                         return ((zone->checksrv)(zone, name, owner));
02532                 return (ISC_TRUE);
02533         }
02534 
02535         if (zone->type == dns_zone_master)
02536                 level = ISC_LOG_ERROR;
02537         else
02538                 level = ISC_LOG_WARNING;
02539 
02540         dns_fixedname_init(&fixed);
02541         foundname = dns_fixedname_name(&fixed);
02542 
02543         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
02544                              0, 0, NULL, foundname, NULL, NULL);
02545         if (result == ISC_R_SUCCESS)
02546                 return (ISC_TRUE);
02547 
02548         if (result == DNS_R_NXRRSET) {
02549                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
02550                                      0, 0, NULL, foundname, NULL, NULL);
02551                 if (result == ISC_R_SUCCESS)
02552                         return (ISC_TRUE);
02553         }
02554 
02555         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
02556         dns_name_format(name, namebuf, sizeof namebuf);
02557         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
02558             result == DNS_R_EMPTYNAME) {
02559                 dns_zone_log(zone, level,
02560                              "%s/SRV '%s' has no address records (A or AAAA)",
02561                              ownerbuf, namebuf);
02562                 /* XXX950 make fatal for 9.5.0. */
02563                 return (ISC_TRUE);
02564         }
02565 
02566         if (result == DNS_R_CNAME) {
02567                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
02568                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
02569                         level = ISC_LOG_WARNING;
02570                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
02571                         dns_zone_log(zone, level,
02572                                      "%s/SRV '%s' is a CNAME (illegal)",
02573                                      ownerbuf, namebuf);
02574                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
02575         }
02576 
02577         if (result == DNS_R_DNAME) {
02578                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
02579                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
02580                         level = ISC_LOG_WARNING;
02581                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
02582                         dns_name_format(foundname, altbuf, sizeof altbuf);
02583                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
02584                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
02585                                      altbuf);
02586                 }
02587                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
02588         }
02589 
02590         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
02591                 return ((zone->checksrv)(zone, name, owner));
02592 
02593         return (ISC_TRUE);
02594 }
02595 
02596 static isc_boolean_t
02597 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
02598                 dns_name_t *owner)
02599 {
02600         isc_boolean_t answer = ISC_TRUE;
02601         isc_result_t result, tresult;
02602         char ownerbuf[DNS_NAME_FORMATSIZE];
02603         char namebuf[DNS_NAME_FORMATSIZE];
02604         char altbuf[DNS_NAME_FORMATSIZE];
02605         dns_fixedname_t fixed;
02606         dns_name_t *foundname;
02607         dns_rdataset_t a;
02608         dns_rdataset_t aaaa;
02609         int level;
02610 
02611         /*
02612          * Outside of zone.
02613          */
02614         if (!dns_name_issubdomain(name, &zone->origin)) {
02615                 if (zone->checkns != NULL)
02616                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
02617                 return (ISC_TRUE);
02618         }
02619 
02620         if (zone->type == dns_zone_master)
02621                 level = ISC_LOG_ERROR;
02622         else
02623                 level = ISC_LOG_WARNING;
02624 
02625         dns_fixedname_init(&fixed);
02626         foundname = dns_fixedname_name(&fixed);
02627         dns_rdataset_init(&a);
02628         dns_rdataset_init(&aaaa);
02629 
02630         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
02631                              DNS_DBFIND_GLUEOK, 0, NULL,
02632                              foundname, &a, NULL);
02633 
02634         if (result == ISC_R_SUCCESS) {
02635                 dns_rdataset_disassociate(&a);
02636                 return (ISC_TRUE);
02637         } else if (result == DNS_R_DELEGATION)
02638                 dns_rdataset_disassociate(&a);
02639 
02640         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
02641             result == DNS_R_GLUE) {
02642                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
02643                                      DNS_DBFIND_GLUEOK, 0, NULL,
02644                                      foundname, &aaaa, NULL);
02645                 if (tresult == ISC_R_SUCCESS) {
02646                         if (dns_rdataset_isassociated(&a))
02647                                 dns_rdataset_disassociate(&a);
02648                         dns_rdataset_disassociate(&aaaa);
02649                         return (ISC_TRUE);
02650                 }
02651                 if (tresult == DNS_R_DELEGATION)
02652                         dns_rdataset_disassociate(&aaaa);
02653                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
02654                         /*
02655                          * Check glue against child zone.
02656                          */
02657                         if (zone->checkns != NULL)
02658                                 answer = (zone->checkns)(zone, name, owner,
02659                                                          &a, &aaaa);
02660                         if (dns_rdataset_isassociated(&a))
02661                                 dns_rdataset_disassociate(&a);
02662                         if (dns_rdataset_isassociated(&aaaa))
02663                                 dns_rdataset_disassociate(&aaaa);
02664                         return (answer);
02665                 }
02666         }
02667 
02668         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
02669         dns_name_format(name, namebuf, sizeof namebuf);
02670         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
02671             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
02672                 const char *what;
02673                 isc_boolean_t required = ISC_FALSE;
02674                 if (dns_name_issubdomain(name, owner)) {
02675                         what = "REQUIRED GLUE ";
02676                         required = ISC_TRUE;
02677                  } else if (result == DNS_R_DELEGATION)
02678                         what = "SIBLING GLUE ";
02679                 else
02680                         what = "";
02681 
02682                 if (result != DNS_R_DELEGATION || required ||
02683                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
02684                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
02685                                      "address records (A or AAAA)",
02686                                      ownerbuf, namebuf, what);
02687                         /*
02688                          * Log missing address record.
02689                          */
02690                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
02691                                 (void)(zone->checkns)(zone, name, owner,
02692                                                       &a, &aaaa);
02693                         /* XXX950 make fatal for 9.5.0. */
02694                         /* answer = ISC_FALSE; */
02695                 }
02696         } else if (result == DNS_R_CNAME) {
02697                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
02698                              ownerbuf, namebuf);
02699                 /* XXX950 make fatal for 9.5.0. */
02700                 /* answer = ISC_FALSE; */
02701         } else if (result == DNS_R_DNAME) {
02702                 dns_name_format(foundname, altbuf, sizeof altbuf);
02703                 dns_zone_log(zone, level,
02704                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
02705                              ownerbuf, namebuf, altbuf);
02706                 /* XXX950 make fatal for 9.5.0. */
02707                 /* answer = ISC_FALSE; */
02708         }
02709 
02710         if (dns_rdataset_isassociated(&a))
02711                 dns_rdataset_disassociate(&a);
02712         if (dns_rdataset_isassociated(&aaaa))
02713                 dns_rdataset_disassociate(&aaaa);
02714         return (answer);
02715 }
02716 
02717 static isc_boolean_t
02718 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
02719                      dns_rdataset_t *rdataset)
02720 {
02721         dns_rdataset_t tmprdataset;
02722         isc_result_t result;
02723         isc_boolean_t answer = ISC_TRUE;
02724         isc_boolean_t format = ISC_TRUE;
02725         int level = ISC_LOG_WARNING;
02726         char ownerbuf[DNS_NAME_FORMATSIZE];
02727         char typebuf[DNS_RDATATYPE_FORMATSIZE];
02728         unsigned int count1 = 0;
02729 
02730         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
02731                 level = ISC_LOG_ERROR;
02732 
02733         dns_rdataset_init(&tmprdataset);
02734         for (result = dns_rdataset_first(rdataset);
02735              result == ISC_R_SUCCESS;
02736              result = dns_rdataset_next(rdataset)) {
02737                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
02738                 unsigned int count2 = 0;
02739 
02740                 count1++;
02741                 dns_rdataset_current(rdataset, &rdata1);
02742                 dns_rdataset_clone(rdataset, &tmprdataset);
02743                 for (result = dns_rdataset_first(&tmprdataset);
02744                      result == ISC_R_SUCCESS;
02745                      result = dns_rdataset_next(&tmprdataset)) {
02746                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
02747                         count2++;
02748                         if (count1 >= count2)
02749                                 continue;
02750                         dns_rdataset_current(&tmprdataset, &rdata2);
02751                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
02752                                 if (format) {
02753                                         dns_name_format(owner, ownerbuf,
02754                                                         sizeof ownerbuf);
02755                                         dns_rdatatype_format(rdata1.type,
02756                                                              typebuf,
02757                                                              sizeof(typebuf));
02758                                         format = ISC_FALSE;
02759                                 }
02760                                 dns_zone_log(zone, level, "%s/%s has "
02761                                              "semantically identical records",
02762                                              ownerbuf, typebuf);
02763                                 if (level == ISC_LOG_ERROR)
02764                                         answer = ISC_FALSE;
02765                                 break;
02766                         }
02767                 }
02768                 dns_rdataset_disassociate(&tmprdataset);
02769                 if (!format)
02770                         break;
02771         }
02772         return (answer);
02773 }
02774 
02775 static isc_boolean_t
02776 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
02777         dns_dbiterator_t *dbiterator = NULL;
02778         dns_dbnode_t *node = NULL;
02779         dns_fixedname_t fixed;
02780         dns_name_t *name;
02781         dns_rdataset_t rdataset;
02782         dns_rdatasetiter_t *rdsit = NULL;
02783         isc_boolean_t ok = ISC_TRUE;
02784         isc_result_t result;
02785 
02786         dns_fixedname_init(&fixed);
02787         name = dns_fixedname_name(&fixed);
02788         dns_rdataset_init(&rdataset);
02789 
02790         result = dns_db_createiterator(db, 0, &dbiterator);
02791         if (result != ISC_R_SUCCESS)
02792                 return (ISC_TRUE);
02793 
02794         for (result = dns_dbiterator_first(dbiterator);
02795              result == ISC_R_SUCCESS;
02796              result = dns_dbiterator_next(dbiterator)) {
02797                 result = dns_dbiterator_current(dbiterator, &node, name);
02798                 if (result != ISC_R_SUCCESS)
02799                         continue;
02800 
02801                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
02802                 if (result != ISC_R_SUCCESS)
02803                         continue;
02804 
02805                 for (result = dns_rdatasetiter_first(rdsit);
02806                      result == ISC_R_SUCCESS;
02807                      result = dns_rdatasetiter_next(rdsit)) {
02808                         dns_rdatasetiter_current(rdsit, &rdataset);
02809                         if (!zone_rrset_check_dup(zone, name, &rdataset))
02810                                 ok = ISC_FALSE;
02811                         dns_rdataset_disassociate(&rdataset);
02812                 }
02813                 dns_rdatasetiter_destroy(&rdsit);
02814                 dns_db_detachnode(db, &node);
02815         }
02816 
02817         if (node != NULL)
02818                 dns_db_detachnode(db, &node);
02819         dns_dbiterator_destroy(&dbiterator);
02820 
02821         return (ok);
02822 }
02823 
02824 static isc_boolean_t
02825 isspf(const dns_rdata_t *rdata) {
02826         char buf[1024];
02827         const unsigned char *data = rdata->data;
02828         unsigned int rdl = rdata->length, i = 0, tl, len;
02829 
02830         while (rdl > 0U) {
02831                 len = tl = *data;
02832                 ++data;
02833                 --rdl;
02834                 INSIST(tl <= rdl);
02835                 if (len > sizeof(buf) - i - 1)
02836                         len = sizeof(buf) - i - 1;
02837                 memmove(buf + i, data, len);
02838                 i += len;
02839                 data += tl;
02840                 rdl -= tl;
02841         }
02842 
02843         if (i < 6U)
02844                 return(ISC_FALSE);
02845 
02846         buf[i] = 0;
02847         if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
02848                 return (ISC_TRUE);
02849         return (ISC_FALSE);
02850 }
02851 
02852 static isc_boolean_t
02853 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
02854         dns_dbiterator_t *dbiterator = NULL;
02855         dns_dbnode_t *node = NULL;
02856         dns_rdataset_t rdataset;
02857         dns_fixedname_t fixed;
02858         dns_fixedname_t fixedbottom;
02859         dns_rdata_mx_t mx;
02860         dns_rdata_ns_t ns;
02861         dns_rdata_in_srv_t srv;
02862         dns_rdata_t rdata;
02863         dns_name_t *name;
02864         dns_name_t *bottom;
02865         isc_result_t result;
02866         isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
02867 
02868         dns_fixedname_init(&fixed);
02869         name = dns_fixedname_name(&fixed);
02870         dns_fixedname_init(&fixedbottom);
02871         bottom = dns_fixedname_name(&fixedbottom);
02872         dns_rdataset_init(&rdataset);
02873         dns_rdata_init(&rdata);
02874 
02875         result = dns_db_createiterator(db, 0, &dbiterator);
02876         if (result != ISC_R_SUCCESS)
02877                 return (ISC_TRUE);
02878 
02879         result = dns_dbiterator_first(dbiterator);
02880         while (result == ISC_R_SUCCESS) {
02881                 result = dns_dbiterator_current(dbiterator, &node, name);
02882                 if (result != ISC_R_SUCCESS)
02883                         goto cleanup;
02884 
02885                 /*
02886                  * Is this name visible in the zone?
02887                  */
02888                 if (!dns_name_issubdomain(name, &zone->origin) ||
02889                     (dns_name_countlabels(bottom) > 0 &&
02890                      dns_name_issubdomain(name, bottom)))
02891                         goto next;
02892 
02893                 /*
02894                  * Don't check the NS records at the origin.
02895                  */
02896                 if (dns_name_equal(name, &zone->origin))
02897                         goto checkmx;
02898 
02899                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
02900                                              0, 0, &rdataset, NULL);
02901                 if (result != ISC_R_SUCCESS)
02902                         goto checkmx;
02903                 /*
02904                  * Remember bottom of zone.
02905                  */
02906                 dns_name_copy(name, bottom, NULL);
02907 
02908                 result = dns_rdataset_first(&rdataset);
02909                 while (result == ISC_R_SUCCESS) {
02910                         dns_rdataset_current(&rdataset, &rdata);
02911                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
02912                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
02913                         if (!zone_check_glue(zone, db, &ns.name, name))
02914                                 ok = ISC_FALSE;
02915                         dns_rdata_reset(&rdata);
02916                         result = dns_rdataset_next(&rdataset);
02917                 }
02918                 dns_rdataset_disassociate(&rdataset);
02919                 goto next;
02920 
02921  checkmx:
02922                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
02923                                              0, 0, &rdataset, NULL);
02924                 if (result != ISC_R_SUCCESS)
02925                         goto checksrv;
02926                 result = dns_rdataset_first(&rdataset);
02927                 while (result == ISC_R_SUCCESS) {
02928                         dns_rdataset_current(&rdataset, &rdata);
02929                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
02930                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
02931                         if (!zone_check_mx(zone, db, &mx.mx, name))
02932                                 ok = ISC_FALSE;
02933                         dns_rdata_reset(&rdata);
02934                         result = dns_rdataset_next(&rdataset);
02935                 }
02936                 dns_rdataset_disassociate(&rdataset);
02937 
02938  checksrv:
02939                 if (zone->rdclass != dns_rdataclass_in)
02940                         goto next;
02941                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
02942                                              0, 0, &rdataset, NULL);
02943                 if (result != ISC_R_SUCCESS)
02944                         goto checkspf;
02945                 result = dns_rdataset_first(&rdataset);
02946                 while (result == ISC_R_SUCCESS) {
02947                         dns_rdataset_current(&rdataset, &rdata);
02948                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
02949                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
02950                         if (!zone_check_srv(zone, db, &srv.target, name))
02951                                 ok = ISC_FALSE;
02952                         dns_rdata_reset(&rdata);
02953                         result = dns_rdataset_next(&rdataset);
02954                 }
02955                 dns_rdataset_disassociate(&rdataset);
02956 
02957  checkspf:
02958                 /*
02959                  * Check if there is a type SPF record without an
02960                  * SPF-formatted type TXT record also being present.
02961                  */
02962                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
02963                         goto next;
02964                 if (zone->rdclass != dns_rdataclass_in)
02965                         goto next;
02966                 have_spf = have_txt = ISC_FALSE;
02967                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
02968                                              0, 0, &rdataset, NULL);
02969                 if (result == ISC_R_SUCCESS) {
02970                         dns_rdataset_disassociate(&rdataset);
02971                         have_spf = ISC_TRUE;
02972                 }
02973                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
02974                                              0, 0, &rdataset, NULL);
02975                 if (result != ISC_R_SUCCESS)
02976                         goto notxt;
02977                 result = dns_rdataset_first(&rdataset);
02978                 while (result == ISC_R_SUCCESS) {
02979                         dns_rdataset_current(&rdataset, &rdata);
02980                         have_txt = isspf(&rdata);
02981                         dns_rdata_reset(&rdata);
02982                         if (have_txt)
02983                                 break;
02984                         result = dns_rdataset_next(&rdataset);
02985                 }
02986                 dns_rdataset_disassociate(&rdataset);
02987 
02988  notxt:
02989                 if (have_spf && !have_txt) {
02990                         char namebuf[DNS_NAME_FORMATSIZE];
02991 
02992                         dns_name_format(name, namebuf, sizeof(namebuf));
02993                         dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
02994                                      "SPF record but no SPF TXT record found, "
02995                                      "add matching type TXT record", namebuf);
02996                 }
02997 
02998  next:
02999                 dns_db_detachnode(db, &node);
03000                 result = dns_dbiterator_next(dbiterator);
03001         }
03002 
03003  cleanup:
03004         if (node != NULL)
03005                 dns_db_detachnode(db, &node);
03006         dns_dbiterator_destroy(&dbiterator);
03007 
03008         return (ok);
03009 }
03010 
03011 /*
03012  * OpenSSL verification of RSA keys with exponent 3 is known to be
03013  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
03014  * if they are in use.
03015  */
03016 static void
03017 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
03018         dns_dbnode_t *node = NULL;
03019         dns_dbversion_t *version = NULL;
03020         dns_rdata_dnskey_t dnskey;
03021         dns_rdata_t rdata = DNS_RDATA_INIT;
03022         dns_rdataset_t rdataset;
03023         isc_result_t result;
03024         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
03025         const char *algorithm;
03026 
03027         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
03028         if (result != ISC_R_SUCCESS)
03029                 goto cleanup;
03030 
03031         dns_db_currentversion(db, &version);
03032         dns_rdataset_init(&rdataset);
03033         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
03034                                      dns_rdatatype_none, 0, &rdataset, NULL);
03035         if (result != ISC_R_SUCCESS)
03036                 goto cleanup;
03037 
03038         for (result = dns_rdataset_first(&rdataset);
03039              result == ISC_R_SUCCESS;
03040              result = dns_rdataset_next(&rdataset))
03041         {
03042                 dns_rdataset_current(&rdataset, &rdata);
03043                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
03044                 INSIST(result == ISC_R_SUCCESS);
03045 
03046                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
03047                      dnskey.algorithm == DST_ALG_RSAMD5) &&
03048                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
03049                      dnskey.data[1] == 3)
03050                 {
03051                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
03052                                 logit = !foundrsa;
03053                                 foundrsa = ISC_TRUE;
03054                                 algorithm = "RSASHA1";
03055                         } else {
03056                                 logit = !foundmd5;
03057                                 foundmd5 = ISC_TRUE;
03058                                 algorithm = "RSAMD5";
03059                         }
03060                         if (logit)
03061                                 dns_zone_log(zone, ISC_LOG_WARNING,
03062                                              "weak %s (%u) key found "
03063                                              "(exponent=3)", algorithm,
03064                                              dnskey.algorithm);
03065                         if (foundrsa && foundmd5)
03066                                 break;
03067                 }
03068                 dns_rdata_reset(&rdata);
03069         }
03070         dns_rdataset_disassociate(&rdataset);
03071 
03072  cleanup:
03073         if (node != NULL)
03074                 dns_db_detachnode(db, &node);
03075         if (version != NULL)
03076                 dns_db_closeversion(db, &version, ISC_FALSE);
03077 }
03078 
03079 static void
03080 resume_signingwithkey(dns_zone_t *zone) {
03081         dns_dbnode_t *node = NULL;
03082         dns_dbversion_t *version = NULL;
03083         dns_rdata_t rdata = DNS_RDATA_INIT;
03084         dns_rdataset_t rdataset;
03085         isc_result_t result;
03086         dns_db_t *db = NULL;
03087 
03088         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
03089         if (zone->db != NULL)
03090                 dns_db_attach(zone->db, &db);
03091         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
03092         if (db == NULL)
03093                 goto cleanup;
03094 
03095         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
03096         if (result != ISC_R_SUCCESS)
03097                 goto cleanup;
03098 
03099         dns_db_currentversion(db, &version);
03100         dns_rdataset_init(&rdataset);
03101         result = dns_db_findrdataset(db, node, version,
03102                                      zone->privatetype,
03103                                      dns_rdatatype_none, 0,
03104                                      &rdataset, NULL);
03105         if (result != ISC_R_SUCCESS) {
03106                 INSIST(!dns_rdataset_isassociated(&rdataset));
03107                 goto cleanup;
03108         }
03109 
03110         for (result = dns_rdataset_first(&rdataset);
03111              result == ISC_R_SUCCESS;
03112              result = dns_rdataset_next(&rdataset))
03113         {
03114                 dns_rdataset_current(&rdataset, &rdata);
03115                 if (rdata.length != 5 ||
03116                     rdata.data[0] == 0 || rdata.data[4] != 0) {
03117                         dns_rdata_reset(&rdata);
03118                         continue;
03119                 }
03120 
03121                 result = zone_signwithkey(zone, rdata.data[0],
03122                                           (rdata.data[1] << 8) | rdata.data[2],
03123                                           ISC_TF(rdata.data[3]));
03124                 if (result != ISC_R_SUCCESS) {
03125                         dns_zone_log(zone, ISC_LOG_ERROR,
03126                                      "zone_signwithkey failed: %s",
03127                                      dns_result_totext(result));
03128                 }
03129                 dns_rdata_reset(&rdata);
03130         }
03131         dns_rdataset_disassociate(&rdataset);
03132 
03133  cleanup:
03134         if (db != NULL) {
03135                 if (node != NULL)
03136                         dns_db_detachnode(db, &node);
03137                 if (version != NULL)
03138                         dns_db_closeversion(db, &version, ISC_FALSE);
03139                 dns_db_detach(&db);
03140         }
03141 }
03142 
03143 static isc_result_t
03144 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
03145         dns_nsec3chain_t *nsec3chain, *current;
03146         dns_dbversion_t *version = NULL;
03147         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
03148         isc_result_t result;
03149         isc_time_t now;
03150         unsigned int options = 0;
03151         char saltbuf[255*2+1];
03152         char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
03153         dns_db_t *db = NULL;
03154         int i;
03155 
03156         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
03157         if (zone->db != NULL)
03158                 dns_db_attach(zone->db, &db);
03159         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
03160 
03161         if (db == NULL) {
03162                 result = ISC_R_SUCCESS;
03163                 goto cleanup;
03164         }
03165 
03166         dns_db_currentversion(db, &version);
03167         result = dns_nsec_nseconly(db, version, &nseconly);
03168         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
03169         dns_db_closeversion(db, &version, ISC_FALSE);
03170         if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
03171                 result = ISC_R_SUCCESS;
03172                 goto cleanup;
03173         }
03174 
03175         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
03176         if (nsec3chain == NULL) {
03177                 result = ISC_R_NOMEMORY;
03178                 goto cleanup;
03179         }
03180 
03181         nsec3chain->magic = 0;
03182         nsec3chain->done = ISC_FALSE;
03183         nsec3chain->db = NULL;
03184         nsec3chain->dbiterator = NULL;
03185         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
03186         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
03187         nsec3chain->nsec3param.hash = nsec3param->hash;
03188         nsec3chain->nsec3param.iterations = nsec3param->iterations;
03189         nsec3chain->nsec3param.flags = nsec3param->flags;
03190         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
03191         memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
03192         nsec3chain->nsec3param.salt = nsec3chain->salt;
03193         nsec3chain->seen_nsec = ISC_FALSE;
03194         nsec3chain->delete_nsec = ISC_FALSE;
03195         nsec3chain->save_delete_nsec = ISC_FALSE;
03196 
03197         if (nsec3param->flags == 0)
03198                 strlcpy(flags, "NONE", sizeof(flags));
03199         else {
03200                 flags[0] = '\0';
03201                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
03202                         strlcat(flags, "REMOVE", sizeof(flags));
03203                 if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
03204                         if (flags[0] == '\0')
03205                                 strlcpy(flags, "INITIAL", sizeof(flags));
03206                         else
03207                                 strlcat(flags, "|INITIAL", sizeof(flags));
03208                 }
03209                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
03210                         if (flags[0] == '\0')
03211                                 strlcpy(flags, "CREATE", sizeof(flags));
03212                         else
03213                                 strlcat(flags, "|CREATE", sizeof(flags));
03214                 }
03215                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
03216                         if (flags[0] == '\0')
03217                                 strlcpy(flags, "NONSEC", sizeof(flags));
03218                         else
03219                                 strlcat(flags, "|NONSEC", sizeof(flags));
03220                 }
03221                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
03222                         if (flags[0] == '\0')
03223                                 strlcpy(flags, "OPTOUT", sizeof(flags));
03224                         else
03225                                 strlcat(flags, "|OPTOUT", sizeof(flags));
03226                 }
03227         }
03228         if (nsec3param->salt_length == 0)
03229                 strlcpy(saltbuf, "-", sizeof(saltbuf));
03230         else
03231                 for (i = 0; i < nsec3param->salt_length; i++)
03232                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
03233         dns_zone_log(zone, ISC_LOG_INFO,
03234                      "zone_addnsec3chain(%u,%s,%u,%s)",
03235                       nsec3param->hash, flags, nsec3param->iterations,
03236                       saltbuf);
03237 
03238         for (current = ISC_LIST_HEAD(zone->nsec3chain);
03239              current != NULL;
03240              current = ISC_LIST_NEXT(current, link)) {
03241                 if (current->db == db &&
03242                     current->nsec3param.hash == nsec3param->hash &&
03243                     current->nsec3param.iterations == nsec3param->iterations &&
03244                     current->nsec3param.salt_length == nsec3param->salt_length
03245                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
03246                                nsec3param->salt_length))
03247                         current->done = ISC_TRUE;
03248         }
03249 
03250         dns_db_attach(db, &nsec3chain->db);
03251         if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
03252                 options = DNS_DB_NONSEC3;
03253         result = dns_db_createiterator(nsec3chain->db, options,
03254                                        &nsec3chain->dbiterator);
03255         if (result == ISC_R_SUCCESS)
03256                 dns_dbiterator_first(nsec3chain->dbiterator);
03257         if (result == ISC_R_SUCCESS) {
03258                 dns_dbiterator_pause(nsec3chain->dbiterator);
03259                 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
03260                                        nsec3chain, link);
03261                 nsec3chain = NULL;
03262                 if (isc_time_isepoch(&zone->nsec3chaintime)) {
03263                         TIME_NOW(&now);
03264                         zone->nsec3chaintime = now;
03265                         if (zone->task != NULL)
03266                                 zone_settimer(zone, &now);
03267                 }
03268         }
03269 
03270         if (nsec3chain != NULL) {
03271                 if (nsec3chain->db != NULL)
03272                         dns_db_detach(&nsec3chain->db);
03273                 if (nsec3chain->dbiterator != NULL)
03274                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
03275                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
03276         }
03277 
03278  cleanup:
03279         if (db != NULL)
03280                 dns_db_detach(&db);
03281         return (result);
03282 }
03283 
03284 static void
03285 resume_addnsec3chain(dns_zone_t *zone) {
03286         dns_dbnode_t *node = NULL;
03287         dns_dbversion_t *version = NULL;
03288         dns_rdataset_t rdataset;
03289         isc_result_t result;
03290         dns_rdata_nsec3param_t nsec3param;
03291         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
03292         dns_db_t *db = NULL;
03293 
03294         if (zone->privatetype == 0)
03295                 return;
03296 
03297         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
03298         if (zone->db != NULL)
03299                 dns_db_attach(zone->db, &db);
03300         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
03301         if (db == NULL)
03302                 goto cleanup;
03303 
03304         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
03305         if (result != ISC_R_SUCCESS)
03306                 goto cleanup;
03307 
03308         dns_db_currentversion(db, &version);
03309 
03310         result = dns_nsec_nseconly(db, version, &nseconly);
03311         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
03312 
03313         dns_rdataset_init(&rdataset);
03314         result = dns_db_findrdataset(db, node, version,
03315                                      zone->privatetype, dns_rdatatype_none,
03316                                      0, &rdataset, NULL);
03317         if (result != ISC_R_SUCCESS) {
03318                 INSIST(!dns_rdataset_isassociated(&rdataset));
03319                 goto cleanup;
03320         }
03321 
03322         for (result = dns_rdataset_first(&rdataset);
03323              result == ISC_R_SUCCESS;
03324              result = dns_rdataset_next(&rdataset))
03325         {
03326                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
03327                 dns_rdata_t rdata = DNS_RDATA_INIT;
03328                 dns_rdata_t private = DNS_RDATA_INIT;
03329 
03330                 dns_rdataset_current(&rdataset, &private);
03331                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
03332                                                 sizeof(buf)))
03333                         continue;
03334                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
03335                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03336                 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
03337                     ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
03338                 {
03339                         result = zone_addnsec3chain(zone, &nsec3param);
03340                         if (result != ISC_R_SUCCESS) {
03341                                 dns_zone_log(zone, ISC_LOG_ERROR,
03342                                              "zone_addnsec3chain failed: %s",
03343                                              dns_result_totext(result));
03344                         }
03345                 }
03346         }
03347         dns_rdataset_disassociate(&rdataset);
03348  cleanup:
03349         if (db != NULL) {
03350                 if (node != NULL)
03351                         dns_db_detachnode(db, &node);
03352                 if (version != NULL)
03353                         dns_db_closeversion(db, &version, ISC_FALSE);
03354                 dns_db_detach(&db);
03355         }
03356 }
03357 
03358 static void
03359 set_resigntime(dns_zone_t *zone) {
03360         dns_rdataset_t rdataset;
03361         dns_fixedname_t fixed;
03362         unsigned int resign;
03363         isc_result_t result;
03364         isc_uint32_t nanosecs;
03365         dns_db_t *db = NULL;
03366 
03367         /* We only re-sign zones that can be dynamically updated */
03368         if (zone->update_disabled)
03369                 return;
03370 
03371         if (!inline_secure(zone) && (zone->type != dns_zone_master ||
03372             (zone->ssutable == NULL &&
03373              (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
03374                 return;
03375 
03376         dns_rdataset_init(&rdataset);
03377         dns_fixedname_init(&fixed);
03378 
03379         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
03380         if (zone->db != NULL)
03381                 dns_db_attach(zone->db, &db);
03382         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
03383         if (db == NULL) {
03384                 isc_time_settoepoch(&zone->resigntime);
03385                 return;
03386         }
03387 
03388         result = dns_db_getsigningtime(db, &rdataset,
03389                                        dns_fixedname_name(&fixed));
03390         if (result != ISC_R_SUCCESS) {
03391                 isc_time_settoepoch(&zone->resigntime);
03392                 goto cleanup;
03393         }
03394 
03395         resign = rdataset.resign - zone->sigresigninginterval;
03396         dns_rdataset_disassociate(&rdataset);
03397         isc_random_get(&nanosecs);
03398         nanosecs %= 1000000000;
03399         isc_time_set(&zone->resigntime, resign, nanosecs);
03400  cleanup:
03401         dns_db_detach(&db);
03402         return;
03403 }
03404 
03405 static isc_result_t
03406 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
03407         dns_dbnode_t *node = NULL;
03408         dns_rdataset_t rdataset;
03409         dns_dbversion_t *version = NULL;
03410         dns_rdata_nsec3param_t nsec3param;
03411         isc_boolean_t ok = ISC_FALSE;
03412         isc_result_t result;
03413         dns_rdata_t rdata = DNS_RDATA_INIT;
03414         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
03415                                 dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
03416 
03417         dns_rdataset_init(&rdataset);
03418         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
03419         if (result != ISC_R_SUCCESS) {
03420                 dns_zone_log(zone, ISC_LOG_ERROR,
03421                              "nsec3param lookup failure: %s",
03422                              dns_result_totext(result));
03423                 return (result);
03424         }
03425         dns_db_currentversion(db, &version);
03426 
03427         result = dns_db_findrdataset(db, node, version,
03428                                      dns_rdatatype_nsec3param,
03429                                      dns_rdatatype_none, 0, &rdataset, NULL);
03430         if (result == ISC_R_NOTFOUND) {
03431                 INSIST(!dns_rdataset_isassociated(&rdataset));
03432                 result = ISC_R_SUCCESS;
03433                 goto cleanup;
03434         }
03435         if (result != ISC_R_SUCCESS) {
03436                 INSIST(!dns_rdataset_isassociated(&rdataset));
03437                 dns_zone_log(zone, ISC_LOG_ERROR,
03438                              "nsec3param lookup failure: %s",
03439                              dns_result_totext(result));
03440                 goto cleanup;
03441         }
03442 
03443         /*
03444          * For dynamic zones we must support every algorithm so we can
03445          * regenerate all the NSEC3 chains.
03446          * For non-dynamic zones we only need to find a supported algorithm.
03447          */
03448         for (result = dns_rdataset_first(&rdataset);
03449              result == ISC_R_SUCCESS;
03450              result = dns_rdataset_next(&rdataset))
03451         {
03452                 dns_rdataset_current(&rdataset, &rdata);
03453                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
03454                 dns_rdata_reset(&rdata);
03455                 INSIST(result == ISC_R_SUCCESS);
03456                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
03457                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
03458                 {
03459                         dns_zone_log(zone, ISC_LOG_WARNING,
03460                              "nsec3 test \"unknown\" hash algorithm found: %u",
03461                                      nsec3param.hash);
03462                         ok = ISC_TRUE;
03463                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
03464                         if (dynamic) {
03465                                 dns_zone_log(zone, ISC_LOG_ERROR,
03466                                              "unsupported nsec3 hash algorithm"
03467                                              " in dynamic zone: %u",
03468                                              nsec3param.hash);
03469                                 result = DNS_R_BADZONE;
03470                                 /* Stop second error message. */
03471                                 ok = ISC_TRUE;
03472                                 break;
03473                         } else
03474                                 dns_zone_log(zone, ISC_LOG_WARNING,
03475                                      "unsupported nsec3 hash algorithm: %u",
03476                                              nsec3param.hash);
03477                 } else
03478                         ok = ISC_TRUE;
03479         }
03480         if (result == ISC_R_NOMORE)
03481                 result = ISC_R_SUCCESS;
03482 
03483         if (!ok) {
03484                 result = DNS_R_BADZONE;
03485                 dns_zone_log(zone, ISC_LOG_ERROR,
03486                              "no supported nsec3 hash algorithm");
03487         }
03488 
03489  cleanup:
03490         if (dns_rdataset_isassociated(&rdataset))
03491                 dns_rdataset_disassociate(&rdataset);
03492         dns_db_closeversion(db, &version, ISC_FALSE);
03493         dns_db_detachnode(db, &node);
03494         return (result);
03495 }
03496 
03497 /*
03498  * Set the timer for refreshing the key zone to the soonest future time
03499  * of the set (current timer, keydata->refresh, keydata->addhd,
03500  * keydata->removehd).
03501  */
03502 static void
03503 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
03504                     isc_stdtime_t now, isc_boolean_t force)
03505 {
03506         const char me[] = "set_refreshkeytimer";
03507         isc_stdtime_t then;
03508         isc_time_t timenow, timethen;
03509         char timebuf[80];
03510 
03511         ENTER;
03512         then = key->refresh;
03513         if (force)
03514                 then = now;
03515         if (key->addhd > now && key->addhd < then)
03516                 then = key->addhd;
03517         if (key->removehd > now && key->removehd < then)
03518                 then = key->removehd;
03519 
03520         TIME_NOW(&timenow);
03521         if (then > now)
03522                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
03523         else
03524                 timethen = timenow;
03525         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
03526             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
03527                 zone->refreshkeytime = timethen;
03528 
03529         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
03530         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
03531         zone_settimer(zone, &timenow);
03532 }
03533 
03534 /*
03535  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
03536  * If the key zone is changed, set '*changed' to ISC_TRUE.
03537  */
03538 static isc_result_t
03539 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
03540                dns_diff_t *diff, dns_keytable_t *keytable,
03541                dns_keynode_t **keynodep, isc_boolean_t *changed)
03542 {
03543         const char me[] = "create_keydata";
03544         isc_result_t result = ISC_R_SUCCESS;
03545         isc_buffer_t keyb, dstb;
03546         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
03547         dns_rdata_keydata_t keydata;
03548         dns_rdata_dnskey_t dnskey;
03549         dns_rdata_t rdata = DNS_RDATA_INIT;
03550         dns_keynode_t *keynode;
03551         isc_stdtime_t now;
03552         isc_region_t r;
03553         dst_key_t *key;
03554 
03555         REQUIRE(keynodep != NULL);
03556         keynode = *keynodep;
03557 
03558         ENTER;
03559         isc_stdtime_get(&now);
03560 
03561         /* Loop in case there's more than one key. */
03562         while (result == ISC_R_SUCCESS) {
03563                 dns_keynode_t *nextnode = NULL;
03564 
03565                 key = dns_keynode_key(keynode);
03566                 if (key == NULL)
03567                         goto skip;
03568 
03569                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
03570                 CHECK(dst_key_todns(key, &dstb));
03571 
03572                 /* Convert DST key to DNSKEY. */
03573                 dns_rdata_reset(&rdata);
03574                 isc_buffer_usedregion(&dstb, &r);
03575                 dns_rdata_fromregion(&rdata, dst_key_class(key),
03576                                      dns_rdatatype_dnskey, &r);
03577 
03578                 /* DSTKEY to KEYDATA. */
03579                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
03580                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
03581                                              NULL));
03582 
03583                 /* KEYDATA to rdata. */
03584                 dns_rdata_reset(&rdata);
03585                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
03586                 CHECK(dns_rdata_fromstruct(&rdata,
03587                                            zone->rdclass, dns_rdatatype_keydata,
03588                                            &keydata, &keyb));
03589 
03590                 /* Add rdata to zone. */
03591                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
03592                                     dst_key_name(key), 0, &rdata));
03593                 *changed = ISC_TRUE;
03594 
03595                 /* Refresh new keys from the zone apex as soon as possible. */
03596                 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
03597 
03598  skip:
03599                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
03600                 if (result != ISC_R_NOTFOUND) {
03601                         dns_keytable_detachkeynode(keytable, &keynode);
03602                         keynode = nextnode;
03603                 }
03604         }
03605 
03606         if (keynode != NULL)
03607                 dns_keytable_detachkeynode(keytable, &keynode);
03608         *keynodep = NULL;
03609 
03610         return (ISC_R_SUCCESS);
03611 
03612   failure:
03613         return (result);
03614 }
03615 
03616 /*
03617  * Remove from the key zone all the KEYDATA records found in rdataset.
03618  */
03619 static isc_result_t
03620 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
03621                dns_name_t *name, dns_rdataset_t *rdataset)
03622 {
03623         dns_rdata_t rdata = DNS_RDATA_INIT;
03624         isc_result_t result, uresult;
03625 
03626         for (result = dns_rdataset_first(rdataset);
03627              result == ISC_R_SUCCESS;
03628              result = dns_rdataset_next(rdataset)) {
03629                 dns_rdata_reset(&rdata);
03630                 dns_rdataset_current(rdataset, &rdata);
03631                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
03632                                         name, 0, &rdata);
03633                 if (uresult != ISC_R_SUCCESS)
03634                         return (uresult);
03635         }
03636         if (result == ISC_R_NOMORE)
03637                 result = ISC_R_SUCCESS;
03638         return (result);
03639 }
03640 
03641 /*
03642  * Compute the DNSSEC key ID for a DNSKEY record.
03643  */
03644 static isc_result_t
03645 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
03646             dns_keytag_t *tag)
03647 {
03648         isc_result_t result;
03649         dns_rdata_t rdata = DNS_RDATA_INIT;
03650         unsigned char data[4096];
03651         isc_buffer_t buffer;
03652         dst_key_t *dstkey = NULL;
03653 
03654         isc_buffer_init(&buffer, data, sizeof(data));
03655         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
03656                              dns_rdatatype_dnskey, dnskey, &buffer);
03657 
03658         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
03659         if (result == ISC_R_SUCCESS)
03660                 *tag = dst_key_id(dstkey);
03661         dst_key_free(&dstkey);
03662 
03663         return (result);
03664 }
03665 
03666 /*
03667  * Add key to the security roots.
03668  */
03669 static void
03670 trust_key(dns_zone_t *zone, dns_name_t *keyname,
03671           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
03672         isc_result_t result;
03673         dns_rdata_t rdata = DNS_RDATA_INIT;
03674         unsigned char data[4096];
03675         isc_buffer_t buffer;
03676         dns_keytable_t *sr = NULL;
03677         dst_key_t *dstkey = NULL;
03678 
03679         /* Convert dnskey to DST key. */
03680         isc_buffer_init(&buffer, data, sizeof(data));
03681         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
03682                              dns_rdatatype_dnskey, dnskey, &buffer);
03683 
03684         result = dns_view_getsecroots(zone->view, &sr);
03685         if (result != ISC_R_SUCCESS)
03686                 goto failure;
03687 
03688         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
03689         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
03690         dns_keytable_detach(&sr);
03691 
03692   failure:
03693         if (dstkey != NULL)
03694                 dst_key_free(&dstkey);
03695         if (sr != NULL)
03696                 dns_keytable_detach(&sr);
03697         return;
03698 }
03699 
03700 /*
03701  * Add a null key to the security roots for so that all queries
03702  * to the zone will fail.
03703  */
03704 static void
03705 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
03706         isc_result_t result;
03707         dns_keytable_t *sr = NULL;
03708 
03709         result = dns_view_getsecroots(zone->view, &sr);
03710         if (result == ISC_R_SUCCESS) {
03711                 dns_keytable_marksecure(sr, keyname);
03712                 dns_keytable_detach(&sr);
03713         }
03714 }
03715 
03716 /*
03717  * Scan a set of KEYDATA records from the key zone.  The ones that are
03718  * valid (i.e., the add holddown timer has expired) become trusted keys.
03719  */
03720 static void
03721 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
03722         isc_result_t result;
03723         dns_rdata_t rdata = DNS_RDATA_INIT;
03724         dns_rdata_keydata_t keydata;
03725         dns_rdata_dnskey_t dnskey;
03726         isc_mem_t *mctx = zone->mctx;
03727         int trusted = 0, revoked = 0, pending = 0;
03728         isc_stdtime_t now;
03729         dns_keytable_t *sr = NULL;
03730 
03731         isc_stdtime_get(&now);
03732 
03733         result = dns_view_getsecroots(zone->view, &sr);
03734         if (result == ISC_R_SUCCESS) {
03735                 dns_keytable_delete(sr, name);
03736                 dns_keytable_detach(&sr);
03737         }
03738 
03739         /* Now insert all the accepted trust anchors from this keydata set. */
03740         for (result = dns_rdataset_first(rdataset);
03741              result == ISC_R_SUCCESS;
03742              result = dns_rdataset_next(rdataset)) {
03743                 dns_rdata_reset(&rdata);
03744                 dns_rdataset_current(rdataset, &rdata);
03745 
03746                 /* Convert rdata to keydata. */
03747                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
03748                 if (result == ISC_R_UNEXPECTEDEND)
03749                         continue;
03750                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03751 
03752                 /* Set the key refresh timer to force a fast refresh. */
03753                 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
03754 
03755                 /* If the removal timer is nonzero, this key was revoked. */
03756                 if (keydata.removehd != 0) {
03757                         revoked++;
03758                         continue;
03759                 }
03760 
03761                 /*
03762                  * If the add timer is still pending, this key is not
03763                  * trusted yet.
03764                  */
03765                 if (now < keydata.addhd) {
03766                         pending++;
03767                         continue;
03768                 }
03769 
03770                 /* Convert keydata to dnskey. */
03771                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
03772 
03773                 /* Add to keytables. */
03774                 trusted++;
03775                 trust_key(zone, name, &dnskey, mctx);
03776         }
03777 
03778         if (trusted == 0 && pending != 0) {
03779                 char namebuf[DNS_NAME_FORMATSIZE];
03780                 dns_name_format(name, namebuf, sizeof namebuf);
03781                 dns_zone_log(zone, ISC_LOG_ERROR,
03782                              "No valid trust anchors for '%s'!", namebuf);
03783                 dns_zone_log(zone, ISC_LOG_ERROR,
03784                              "%d key(s) revoked, %d still pending",
03785                              revoked, pending);
03786                 dns_zone_log(zone, ISC_LOG_ERROR,
03787                              "All queries to '%s' will fail", namebuf);
03788                 fail_secure(zone, name);
03789         }
03790 }
03791 
03792 static isc_result_t
03793 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
03794              dns_diff_t *diff)
03795 {
03796         dns_diff_t temp_diff;
03797         isc_result_t result;
03798 
03799         /*
03800          * Create a singleton diff.
03801          */
03802         dns_diff_init(diff->mctx, &temp_diff);
03803         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
03804 
03805         /*
03806          * Apply it to the database.
03807          */
03808         result = dns_diff_apply(&temp_diff, db, ver);
03809         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
03810         if (result != ISC_R_SUCCESS) {
03811                 dns_difftuple_free(tuple);
03812                 return (result);
03813         }
03814 
03815         /*
03816          * Merge it into the current pending journal entry.
03817          */
03818         dns_diff_appendminimal(diff, tuple);
03819 
03820         /*
03821          * Do not clear temp_diff.
03822          */
03823         return (ISC_R_SUCCESS);
03824 }
03825 
03826 static isc_result_t
03827 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
03828               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
03829               dns_rdata_t *rdata)
03830 {
03831         dns_difftuple_t *tuple = NULL;
03832         isc_result_t result;
03833         result = dns_difftuple_create(diff->mctx, op,
03834                                       name, ttl, rdata, &tuple);
03835         if (result != ISC_R_SUCCESS)
03836                 return (result);
03837         return (do_one_tuple(&tuple, db, ver, diff));
03838 }
03839 
03840 static isc_result_t
03841 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
03842                   isc_mem_t *mctx, dns_updatemethod_t method) {
03843         dns_difftuple_t *deltuple = NULL;
03844         dns_difftuple_t *addtuple = NULL;
03845         isc_uint32_t serial;
03846         isc_result_t result;
03847 
03848         INSIST(method != dns_updatemethod_none);
03849 
03850         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
03851         CHECK(dns_difftuple_copy(deltuple, &addtuple));
03852         addtuple->op = DNS_DIFFOP_ADD;
03853 
03854         serial = dns_soa_getserial(&addtuple->rdata);
03855         serial = dns_update_soaserial(serial, method);
03856         dns_soa_setserial(serial, &addtuple->rdata);
03857         CHECK(do_one_tuple(&deltuple, db, ver, diff));
03858         CHECK(do_one_tuple(&addtuple, db, ver, diff));
03859         result = ISC_R_SUCCESS;
03860 
03861         failure:
03862         if (addtuple != NULL)
03863                 dns_difftuple_free(&addtuple);
03864         if (deltuple != NULL)
03865                 dns_difftuple_free(&deltuple);
03866         return (result);
03867 }
03868 
03869 /*
03870  * Write all transactions in 'diff' to the zone journal file.
03871  */
03872 static isc_result_t
03873 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
03874              const char *caller)
03875 {
03876         const char me[] = "zone_journal";
03877         const char *journalfile;
03878         isc_result_t result = ISC_R_SUCCESS;
03879         dns_journal_t *journal = NULL;
03880         unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
03881 
03882         ENTER;
03883         journalfile = dns_zone_getjournal(zone);
03884         if (journalfile != NULL) {
03885                 result = dns_journal_open(zone->mctx, journalfile, mode,
03886                                           &journal);
03887                 if (result != ISC_R_SUCCESS) {
03888                         dns_zone_log(zone, ISC_LOG_ERROR,
03889                                      "%s:dns_journal_open -> %s",
03890                                      caller, dns_result_totext(result));
03891                         return (result);
03892                 }
03893 
03894                 if (sourceserial != NULL)
03895                         dns_journal_set_sourceserial(journal, *sourceserial);
03896 
03897                 result = dns_journal_write_transaction(journal, diff);
03898                 if (result != ISC_R_SUCCESS) {
03899                         dns_zone_log(zone, ISC_LOG_ERROR,
03900                                      "%s:dns_journal_write_transaction -> %s",
03901                                      caller, dns_result_totext(result));
03902                 }
03903                 dns_journal_destroy(&journal);
03904         }
03905 
03906         return (result);
03907 }
03908 
03909 /*
03910  * Create an SOA record for a newly-created zone
03911  */
03912 static isc_result_t
03913 add_soa(dns_zone_t *zone, dns_db_t *db) {
03914         isc_result_t result;
03915         dns_rdata_t rdata = DNS_RDATA_INIT;
03916         unsigned char buf[DNS_SOA_BUFFERSIZE];
03917         dns_dbversion_t *ver = NULL;
03918         dns_diff_t diff;
03919 
03920         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
03921 
03922         dns_diff_init(zone->mctx, &diff);
03923         result = dns_db_newversion(db, &ver);
03924         if (result != ISC_R_SUCCESS) {
03925                 dns_zone_log(zone, ISC_LOG_ERROR,
03926                              "add_soa:dns_db_newversion -> %s",
03927                              dns_result_totext(result));
03928                 goto failure;
03929         }
03930 
03931         /* Build SOA record */
03932         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
03933                                     0, 0, 0, 0, 0, buf, &rdata);
03934         if (result != ISC_R_SUCCESS) {
03935                 dns_zone_log(zone, ISC_LOG_ERROR,
03936                              "add_soa:dns_soa_buildrdata -> %s",
03937                              dns_result_totext(result));
03938                 goto failure;
03939         }
03940 
03941         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
03942                                &zone->origin, 0, &rdata);
03943 
03944 failure:
03945         dns_diff_clear(&diff);
03946         if (ver != NULL)
03947                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
03948 
03949         INSIST(ver == NULL);
03950 
03951         return (result);
03952 }
03953 
03954 /*
03955  * Synchronize the set of initializing keys found in managed-keys {}
03956  * statements with the set of trust anchors found in the managed-keys.bind
03957  * zone.  If a domain is no longer named in managed-keys, delete all keys
03958  * from that domain from the key zone.  If a domain is mentioned in in
03959  * managed-keys but there are no references to it in the key zone, load
03960  * the key zone with the initializing key(s) for that domain.
03961  */
03962 static isc_result_t
03963 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
03964         isc_result_t result = ISC_R_SUCCESS;
03965         isc_boolean_t changed = ISC_FALSE;
03966         isc_boolean_t commit = ISC_FALSE;
03967         dns_rbtnodechain_t chain;
03968         dns_fixedname_t fn;
03969         dns_name_t foundname, *origin;
03970         dns_keynode_t *keynode = NULL;
03971         dns_view_t *view = zone->view;
03972         dns_keytable_t *sr = NULL;
03973         dns_dbversion_t *ver = NULL;
03974         dns_diff_t diff;
03975         dns_rriterator_t rrit;
03976 
03977         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
03978 
03979         dns_name_init(&foundname, NULL);
03980         dns_fixedname_init(&fn);
03981         origin = dns_fixedname_name(&fn);
03982 
03983         dns_diff_init(zone->mctx, &diff);
03984 
03985         CHECK(dns_view_getsecroots(view, &sr));
03986 
03987         result = dns_db_newversion(db, &ver);
03988         if (result != ISC_R_SUCCESS) {
03989                 dns_zone_log(zone, ISC_LOG_ERROR,
03990                              "sync_keyzone:dns_db_newversion -> %s",
03991                              dns_result_totext(result));
03992                 goto failure;
03993         }
03994 
03995         /*
03996          * Walk the zone DB.  If we find any keys whose names are no longer
03997          * in managed-keys (or *are* in trusted-keys, meaning they are
03998          * permanent and not RFC5011-maintained), delete them from the
03999          * zone.  Otherwise call load_secroots(), which loads keys into
04000          * secroots as appropriate.
04001          */
04002         dns_rriterator_init(&rrit, db, ver, 0);
04003         for (result = dns_rriterator_first(&rrit);
04004              result == ISC_R_SUCCESS;
04005              result = dns_rriterator_nextrrset(&rrit)) {
04006                 dns_rdataset_t *rdataset = NULL;
04007                 dns_name_t *rrname = NULL;
04008                 isc_uint32_t ttl;
04009 
04010                 dns_rriterator_current(&rrit, &rrname, &ttl,
04011                                        &rdataset, NULL);
04012                 if (!dns_rdataset_isassociated(rdataset)) {
04013                         dns_rriterator_destroy(&rrit);
04014                         goto failure;
04015                 }
04016 
04017                 if (rdataset->type != dns_rdatatype_keydata)
04018                         continue;
04019 
04020                 result = dns_keytable_find(sr, rrname, &keynode);
04021                 if ((result != ISC_R_SUCCESS &&
04022                      result != DNS_R_PARTIALMATCH) ||
04023                     dns_keynode_managed(keynode) == ISC_FALSE)
04024                 {
04025                         CHECK(delete_keydata(db, ver, &diff,
04026                                              rrname, rdataset));
04027                         changed = ISC_TRUE;
04028                 } else {
04029                         load_secroots(zone, rrname, rdataset);
04030                 }
04031 
04032                 if (keynode != NULL)
04033                         dns_keytable_detachkeynode(sr, &keynode);
04034         }
04035         dns_rriterator_destroy(&rrit);
04036 
04037         /*
04038          * Now walk secroots to find any managed keys that aren't
04039          * in the zone.  If we find any, we add them to the zone.
04040          */
04041         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
04042         dns_rbtnodechain_init(&chain, zone->mctx);
04043         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
04044         if (result == ISC_R_NOTFOUND)
04045                 result = ISC_R_NOMORE;
04046         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
04047                 dns_rbtnode_t *rbtnode = NULL;
04048 
04049                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
04050                 if (rbtnode->data == NULL)
04051                         goto skip;
04052 
04053                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
04054                 if (dns_keynode_managed(keynode)) {
04055                         dns_fixedname_t fname;
04056                         dns_name_t *keyname;
04057                         dst_key_t *key;
04058 
04059                         key = dns_keynode_key(keynode);
04060                         dns_fixedname_init(&fname);
04061 
04062                         if (key == NULL)   /* fail_secure() was called. */
04063                                 goto skip;
04064 
04065                         keyname = dst_key_name(key);
04066                         result = dns_db_find(db, keyname, ver,
04067                                              dns_rdatatype_keydata,
04068                                              DNS_DBFIND_NOWILD, 0, NULL,
04069                                              dns_fixedname_name(&fname),
04070                                              NULL, NULL);
04071                         if (result != ISC_R_SUCCESS)
04072                                 result = create_keydata(zone, db, ver, &diff,
04073                                                         sr, &keynode, &changed);
04074                         if (result != ISC_R_SUCCESS)
04075                                 break;
04076                 }
04077   skip:
04078                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
04079                 if (keynode != NULL)
04080                         dns_keytable_detachkeynode(sr, &keynode);
04081         }
04082         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
04083 
04084         if (result == ISC_R_NOMORE)
04085                 result = ISC_R_SUCCESS;
04086 
04087         if (changed) {
04088                 /* Write changes to journal file. */
04089                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
04090                                         zone->updatemethod));
04091                 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
04092 
04093                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
04094                 zone_needdump(zone, 30);
04095                 commit = ISC_TRUE;
04096         }
04097 
04098  failure:
04099         if (result != ISC_R_SUCCESS &&
04100             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
04101                 dns_zone_log(zone, ISC_LOG_ERROR,
04102                              "unable to synchronize managed keys: %s",
04103                              dns_result_totext(result));
04104                 isc_time_settoepoch(&zone->refreshkeytime);
04105         }
04106         if (keynode != NULL)
04107                 dns_keytable_detachkeynode(sr, &keynode);
04108         if (sr != NULL)
04109                 dns_keytable_detach(&sr);
04110         if (ver != NULL)
04111                 dns_db_closeversion(db, &ver, commit);
04112         dns_diff_clear(&diff);
04113 
04114         INSIST(ver == NULL);
04115 
04116         return (result);
04117 }
04118 
04119 isc_result_t
04120 dns_zone_synckeyzone(dns_zone_t *zone) {
04121         isc_result_t result;
04122         dns_db_t *db = NULL;
04123 
04124         if (zone->type != dns_zone_key)
04125                 return (DNS_R_BADZONE);
04126 
04127         CHECK(dns_zone_getdb(zone, &db));
04128 
04129         LOCK_ZONE(zone);
04130         result = sync_keyzone(zone, db);
04131         UNLOCK_ZONE(zone);
04132 
04133  failure:
04134         if (db != NULL)
04135                 dns_db_detach(&db);
04136         return (result);
04137 }
04138 
04139 static void
04140 maybe_send_secure(dns_zone_t *zone) {
04141         isc_result_t result;
04142 
04143         /*
04144          * We've finished loading, or else failed to load, an inline-signing
04145          * 'secure' zone.  We now need information about the status of the
04146          * 'raw' zone.  If we failed to load, then we need it to send a
04147          * copy of its database; if we succeeded, we need it to send its
04148          * serial number so that we can sync with it.  If it has not yet
04149          * loaded, we set a flag so that it will send the necessary
04150          * information when it has finished loading.
04151          */
04152         if (zone->raw->db != NULL) {
04153                 if (zone->db != NULL) {
04154                         isc_uint32_t serial;
04155                         unsigned int soacount;
04156 
04157                         result = zone_get_from_db(zone->raw, zone->raw->db,
04158                                                   NULL, &soacount, &serial, NULL,
04159                                                   NULL, NULL, NULL, NULL);
04160                         if (result == ISC_R_SUCCESS && soacount > 0U)
04161                                 zone_send_secureserial(zone->raw, serial);
04162                 } else
04163                         zone_send_securedb(zone->raw, zone->raw->db);
04164 
04165         } else
04166                 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
04167 }
04168 
04169 static isc_boolean_t
04170 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
04171         isc_result_t result;
04172         isc_boolean_t answer = ISC_FALSE;
04173         dns_diff_t diff;
04174 
04175         dns_diff_init(mctx, &diff);
04176         result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
04177         if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
04178                 answer = ISC_TRUE;
04179         dns_diff_clear(&diff);
04180         return (answer);
04181 }
04182 
04183 /*
04184  * The zone is presumed to be locked.
04185  * If this is a inline_raw zone the secure version is also locked.
04186  */
04187 static isc_result_t
04188 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
04189               isc_result_t result)
04190 {
04191         unsigned int soacount = 0;
04192         unsigned int nscount = 0;
04193         unsigned int errors = 0;
04194         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
04195         isc_time_t now;
04196         isc_boolean_t needdump = ISC_FALSE;
04197         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
04198         isc_boolean_t nomaster = ISC_FALSE;
04199         unsigned int options;
04200         dns_include_t *inc;
04201 
04202         INSIST(LOCKED_ZONE(zone));
04203         if (inline_raw(zone))
04204                 INSIST(LOCKED_ZONE(zone->secure));
04205 
04206         TIME_NOW(&now);
04207 
04208         /*
04209          * Initiate zone transfer?  We may need a error code that
04210          * indicates that the "permanent" form does not exist.
04211          * XXX better error feedback to log.
04212          */
04213         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
04214                 if (zone->type == dns_zone_slave ||
04215                     zone->type == dns_zone_stub ||
04216                     (zone->type == dns_zone_redirect &&
04217                      zone->masters == NULL)) {
04218                         if (result == ISC_R_FILENOTFOUND)
04219                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
04220                                              "no master file");
04221                         else if (result != DNS_R_NOMASTERFILE)
04222                                 dns_zone_log(zone, ISC_LOG_ERROR,
04223                                              "loading from master file %s "
04224                                              "failed: %s",
04225                                              zone->masterfile,
04226                                              dns_result_totext(result));
04227                 } else if (zone->type == dns_zone_master &&
04228                            inline_secure(zone) && result == ISC_R_FILENOTFOUND)
04229                 {
04230                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
04231                                      "no master file, requesting db");
04232                         maybe_send_secure(zone);
04233                 } else {
04234                         int level = ISC_LOG_ERROR;
04235                         if (zone->type == dns_zone_key &&
04236                             result == ISC_R_FILENOTFOUND)
04237                                 level = ISC_LOG_DEBUG(1);
04238                         dns_zone_log(zone, level,
04239                                      "loading from master file %s failed: %s",
04240                                      zone->masterfile,
04241                                      dns_result_totext(result));
04242                         nomaster = ISC_TRUE;
04243                 }
04244 
04245                 if (zone->type != dns_zone_key)
04246                         goto cleanup;
04247         }
04248 
04249         dns_zone_log(zone, ISC_LOG_DEBUG(2),
04250                      "number of nodes in database: %u",
04251                      dns_db_nodecount(db));
04252 
04253         if (result == DNS_R_SEENINCLUDE)
04254                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
04255         else
04256                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
04257 
04258         /*
04259          * If there's no master file for a key zone, then the zone is new:
04260          * create an SOA record.  (We do this now, instead of later, so that
04261          * if there happens to be a journal file, we can roll forward from
04262          * a sane starting point.)
04263          */
04264         if (nomaster && zone->type == dns_zone_key) {
04265                 result = add_soa(zone, db);
04266                 if (result != ISC_R_SUCCESS)
04267                         goto cleanup;
04268         }
04269 
04270         /*
04271          * Apply update log, if any, on initial load.
04272          */
04273         if (zone->journal != NULL &&
04274             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
04275             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
04276         {
04277                 if (zone->type == dns_zone_master &&
04278                     (zone->update_acl != NULL || zone->ssutable != NULL))
04279                         options = DNS_JOURNALOPT_RESIGN;
04280                 else
04281                         options = 0;
04282                 result = dns_journal_rollforward(zone->mctx, db, options,
04283                                                  zone->journal);
04284                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
04285                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
04286                     result != ISC_R_RANGE) {
04287                         dns_zone_log(zone, ISC_LOG_ERROR,
04288                                      "journal rollforward failed: %s",
04289                                      dns_result_totext(result));
04290                         goto cleanup;
04291 
04292 
04293                 }
04294                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
04295                         dns_zone_log(zone, ISC_LOG_ERROR,
04296                                      "journal rollforward failed: "
04297                                      "journal out of sync with zone");
04298                         goto cleanup;
04299                 }
04300                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
04301                              "journal rollforward completed "
04302                              "successfully: %s",
04303                              dns_result_totext(result));
04304                 if (result == ISC_R_SUCCESS)
04305                         needdump = ISC_TRUE;
04306         }
04307 
04308         /*
04309          * Obtain ns, soa and cname counts for top of zone.
04310          */
04311         INSIST(db != NULL);
04312         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
04313                                   &refresh, &retry, &expire, &minimum,
04314                                   &errors);
04315         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
04316                 dns_zone_log(zone, ISC_LOG_ERROR,
04317                              "could not find NS and/or SOA records");
04318         }
04319 
04320         /*
04321          * Check to make sure the journal is up to date, and remove the
04322          * journal file if it isn't, as we wouldn't be able to apply
04323          * updates otherwise.
04324          */
04325         if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
04326             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
04327                 isc_uint32_t jserial;
04328                 dns_journal_t *journal = NULL;
04329 
04330                 result = dns_journal_open(zone->mctx, zone->journal,
04331                                           DNS_JOURNAL_READ, &journal);
04332                 if (result == ISC_R_SUCCESS) {
04333                         jserial = dns_journal_last_serial(journal);
04334                         dns_journal_destroy(&journal);
04335                 } else {
04336                         jserial = serial;
04337                         result = ISC_R_SUCCESS;
04338                 }
04339 
04340                 if (jserial != serial) {
04341                         dns_zone_log(zone, ISC_LOG_INFO,
04342                                      "journal file is out of date: "
04343                                      "removing journal file");
04344                         if (remove(zone->journal) < 0 && errno != ENOENT) {
04345                                 char strbuf[ISC_STRERRORSIZE];
04346                                 isc__strerror(errno, strbuf, sizeof(strbuf));
04347                                 isc_log_write(dns_lctx,
04348                                               DNS_LOGCATEGORY_GENERAL,
04349                                               DNS_LOGMODULE_ZONE,
04350                                               ISC_LOG_WARNING,
04351                                               "unable to remove journal "
04352                                               "'%s': '%s'",
04353                                               zone->journal, strbuf);
04354                         }
04355                 }
04356         }
04357 
04358         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
04359 
04360         /*
04361          * Master / Slave / Stub zones require both NS and SOA records at
04362          * the top of the zone.
04363          */
04364 
04365         switch (zone->type) {
04366         case dns_zone_dlz:
04367         case dns_zone_master:
04368         case dns_zone_slave:
04369         case dns_zone_stub:
04370         case dns_zone_redirect:
04371                 if (soacount != 1) {
04372                         dns_zone_log(zone, ISC_LOG_ERROR,
04373                                      "has %d SOA records", soacount);
04374                         result = DNS_R_BADZONE;
04375                 }
04376                 if (nscount == 0) {
04377                         dns_zone_log(zone, ISC_LOG_ERROR,
04378                                      "has no NS records");
04379                         result = DNS_R_BADZONE;
04380                 }
04381                 if (result != ISC_R_SUCCESS)
04382                         goto cleanup;
04383                 if (zone->type == dns_zone_master && errors != 0) {
04384                         result = DNS_R_BADZONE;
04385                         goto cleanup;
04386                 }
04387                 if (zone->type != dns_zone_stub &&
04388                     zone->type != dns_zone_redirect) {
04389                         result = check_nsec3param(zone, db);
04390                         if (result != ISC_R_SUCCESS)
04391                                 goto cleanup;
04392                 }
04393                 if (zone->type == dns_zone_master &&
04394                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
04395                     !integrity_checks(zone, db)) {
04396                         result = DNS_R_BADZONE;
04397                         goto cleanup;
04398                 }
04399                 if (zone->type == dns_zone_master &&
04400                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
04401                     !zone_check_dup(zone, db)) {
04402                         result = DNS_R_BADZONE;
04403                         goto cleanup;
04404                 }
04405 
04406                 if (zone->db != NULL) {
04407                         unsigned int oldsoacount;
04408 
04409                         /*
04410                          * This is checked in zone_replacedb() for slave zones
04411                          * as they don't reload from disk.
04412                          */
04413                         result = zone_get_from_db(zone, zone->db, NULL,
04414                                                   &oldsoacount, &oldserial,
04415                                                   NULL, NULL, NULL, NULL,
04416                                                   NULL);
04417                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
04418                         RUNTIME_CHECK(soacount > 0U);
04419                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
04420                             !isc_serial_gt(serial, oldserial)) {
04421                                 isc_uint32_t serialmin, serialmax;
04422 
04423                                 INSIST(zone->type == dns_zone_master);
04424 
04425                                 if (serial == oldserial &&
04426                                     zone_unchanged(zone->db, db, zone->mctx)) {
04427                                         dns_zone_log(zone, ISC_LOG_INFO,
04428                                                      "ixfr-from-differences: "
04429                                                      "unchanged");
04430                                         return(ISC_R_SUCCESS);
04431                                 }
04432 
04433                                 serialmin = (oldserial + 1) & 0xffffffffU;
04434                                 serialmax = (oldserial + 0x7fffffffU) &
04435                                              0xffffffffU;
04436                                 dns_zone_log(zone, ISC_LOG_ERROR,
04437                                              "ixfr-from-differences: "
04438                                              "new serial (%u) out of range "
04439                                              "[%u - %u]", serial, serialmin,
04440                                              serialmax);
04441                                 result = DNS_R_BADZONE;
04442                                 goto cleanup;
04443                         } else if (!isc_serial_ge(serial, oldserial))
04444                                 dns_zone_log(zone, ISC_LOG_ERROR,
04445                                              "zone serial (%u/%u) has gone "
04446                                              "backwards", serial, oldserial);
04447                         else if (serial == oldserial && !hasinclude &&
04448                                  strcmp(zone->db_argv[0], "_builtin") != 0)
04449                                 dns_zone_log(zone, ISC_LOG_ERROR,
04450                                              "zone serial (%u) unchanged. "
04451                                              "zone may fail to transfer "
04452                                              "to slaves.", serial);
04453                 }
04454 
04455                 if (zone->type == dns_zone_master &&
04456                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
04457                     zone->sigresigninginterval < (3 * refresh) &&
04458                     dns_db_issecure(db))
04459                 {
04460                         dns_zone_log(zone, ISC_LOG_WARNING,
04461                                      "sig-re-signing-interval less than "
04462                                      "3 * refresh.");
04463                 }
04464 
04465                 zone->refresh = RANGE(refresh,
04466                                       zone->minrefresh, zone->maxrefresh);
04467                 zone->retry = RANGE(retry,
04468                                     zone->minretry, zone->maxretry);
04469                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
04470                                      DNS_MAX_EXPIRE);
04471                 zone->minimum = minimum;
04472                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
04473 
04474                 if (zone->type == dns_zone_slave ||
04475                     zone->type == dns_zone_stub ||
04476                     (zone->type == dns_zone_redirect &&
04477                      zone->masters != NULL)) {
04478                         isc_time_t t;
04479                         isc_uint32_t delay;
04480 
04481                         result = isc_file_getmodtime(zone->journal, &t);
04482                         if (result != ISC_R_SUCCESS)
04483                                 result = isc_file_getmodtime(zone->masterfile,
04484                                                              &t);
04485                         if (result == ISC_R_SUCCESS)
04486                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
04487                                                   &zone->expiretime);
04488                         else
04489                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
04490                                                   &zone->expiretime);
04491 
04492                         delay = isc_random_jitter(zone->retry,
04493                                                   (zone->retry * 3) / 4);
04494                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
04495                         if (isc_time_compare(&zone->refreshtime,
04496                                              &zone->expiretime) >= 0)
04497                                 zone->refreshtime = now;
04498                 }
04499 
04500                 break;
04501 
04502         case dns_zone_key:
04503                 result = sync_keyzone(zone, db);
04504                 if (result != ISC_R_SUCCESS)
04505                         goto cleanup;
04506                 break;
04507 
04508         default:
04509                 UNEXPECTED_ERROR(__FILE__, __LINE__,
04510                                  "unexpected zone type %d", zone->type);
04511                 result = ISC_R_UNEXPECTED;
04512                 goto cleanup;
04513         }
04514 
04515         /*
04516          * Check for weak DNSKEY's.
04517          */
04518         if (zone->type == dns_zone_master)
04519                 zone_check_dnskeys(zone, db);
04520 
04521         /*
04522          * Schedule DNSSEC key refresh.
04523          */
04524         if (zone->type == dns_zone_master &&
04525             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
04526                 zone->refreshkeytime = now;
04527 
04528 #if 0
04529         /* destroy notification example. */
04530         {
04531                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
04532                                                     DNS_EVENT_DBDESTROYED,
04533                                                     dns_zonemgr_dbdestroyed,
04534                                                     zone,
04535                                                     sizeof(isc_event_t));
04536                 dns_db_ondestroy(db, zone->task, &e);
04537         }
04538 #endif
04539 
04540         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
04541         if (zone->db != NULL) {
04542                 result = zone_replacedb(zone, db, ISC_FALSE);
04543                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
04544                 if (result != ISC_R_SUCCESS)
04545                         goto cleanup;
04546         } else {
04547                 result = dns_db_rpz_ready(db);
04548                 if (result != ISC_R_SUCCESS)
04549                         goto cleanup;
04550                 zone_attachdb(zone, db);
04551                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
04552                 DNS_ZONE_SETFLAG(zone,
04553                                  DNS_ZONEFLG_LOADED|
04554                                  DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
04555                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
04556                     inline_raw(zone))
04557                 {
04558                         if (zone->secure->db == NULL)
04559                                 zone_send_securedb(zone, db);
04560                         else
04561                                 zone_send_secureserial(zone, serial);
04562                 }
04563         }
04564 
04565         /*
04566          * Finished loading inline-signing zone; need to get status
04567          * from the raw side now.
04568          */
04569         if (zone->type == dns_zone_master && inline_secure(zone))
04570                 maybe_send_secure(zone);
04571 
04572 
04573         result = ISC_R_SUCCESS;
04574 
04575         if (needdump) {
04576                 if (zone->type == dns_zone_key)
04577                         zone_needdump(zone, 30);
04578                 else
04579                         zone_needdump(zone, DNS_DUMP_DELAY);
04580         }
04581 
04582         if (zone->task != NULL) {
04583                 if (zone->type == dns_zone_master) {
04584                         set_resigntime(zone);
04585                         resume_signingwithkey(zone);
04586                         resume_addnsec3chain(zone);
04587                 }
04588 
04589                 if (zone->type == dns_zone_master &&
04590                     !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
04591                     dns_zone_isdynamic(zone, ISC_FALSE) &&
04592                     dns_db_issecure(db)) {
04593                         dns_name_t *name;
04594                         dns_fixedname_t fixed;
04595                         dns_rdataset_t next;
04596 
04597                         dns_rdataset_init(&next);
04598                         dns_fixedname_init(&fixed);
04599                         name = dns_fixedname_name(&fixed);
04600 
04601                         result = dns_db_getsigningtime(db, &next, name);
04602                         if (result == ISC_R_SUCCESS) {
04603                                 isc_stdtime_t timenow;
04604                                 char namebuf[DNS_NAME_FORMATSIZE];
04605                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
04606 
04607                                 isc_stdtime_get(&timenow);
04608                                 dns_name_format(name, namebuf, sizeof(namebuf));
04609                                 dns_rdatatype_format(next.covers,
04610                                                      typebuf, sizeof(typebuf));
04611                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
04612                                              "next resign: %s/%s in %d seconds",
04613                                              namebuf, typebuf,
04614                                              next.resign - timenow -
04615                                              zone->sigresigninginterval);
04616                                 dns_rdataset_disassociate(&next);
04617                         } else
04618                                 dns_zone_log(zone, ISC_LOG_WARNING,
04619                                              "signed dynamic zone has no "
04620                                              "resign event scheduled");
04621                 }
04622 
04623                 zone_settimer(zone, &now);
04624         }
04625 
04626         /*
04627          * Clear old include list.
04628          */
04629         for (inc = ISC_LIST_HEAD(zone->includes);
04630              inc != NULL;
04631              inc = ISC_LIST_HEAD(zone->includes)) {
04632                 ISC_LIST_UNLINK(zone->includes, inc, link);
04633                 isc_mem_free(zone->mctx, inc->name);
04634                 isc_mem_put(zone->mctx, inc, sizeof(*inc));
04635         }
04636         zone->nincludes = 0;
04637 
04638         /*
04639          * Transfer new include list.
04640          */
04641         for (inc = ISC_LIST_HEAD(zone->newincludes);
04642              inc != NULL;
04643              inc = ISC_LIST_HEAD(zone->newincludes)) {
04644                 ISC_LIST_UNLINK(zone->newincludes, inc, link);
04645                 ISC_LIST_APPEND(zone->includes, inc, link);
04646                 zone->nincludes++;
04647         }
04648 
04649         if (! dns_db_ispersistent(db))
04650                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
04651                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
04652 
04653         zone->loadtime = loadtime;
04654         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
04655         return (result);
04656 
04657  cleanup:
04658         for (inc = ISC_LIST_HEAD(zone->newincludes);
04659              inc != NULL;
04660              inc = ISC_LIST_HEAD(zone->newincludes)) {
04661                 ISC_LIST_UNLINK(zone->newincludes, inc, link);
04662                 isc_mem_free(zone->mctx, inc->name);
04663                 isc_mem_put(zone->mctx, inc, sizeof(*inc));
04664         }
04665         if (zone->type == dns_zone_slave ||
04666             zone->type == dns_zone_stub ||
04667             zone->type == dns_zone_key ||
04668             (zone->type == dns_zone_redirect && zone->masters != NULL)) {
04669                 if (zone->journal != NULL)
04670                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
04671                 if (zone->masterfile != NULL)
04672                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
04673 
04674                 /* Mark the zone for immediate refresh. */
04675                 zone->refreshtime = now;
04676                 if (zone->task != NULL)
04677                         zone_settimer(zone, &now);
04678                 result = ISC_R_SUCCESS;
04679         } else if (zone->type == dns_zone_master ||
04680                    zone->type == dns_zone_redirect) {
04681                 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
04682                         dns_zone_log(zone, ISC_LOG_ERROR,
04683                                      "not loaded due to errors.");
04684                 else if (zone->type == dns_zone_master)
04685                         result = ISC_R_SUCCESS;
04686         }
04687 
04688         return (result);
04689 }
04690 
04691 static isc_boolean_t
04692 exit_check(dns_zone_t *zone) {
04693         REQUIRE(LOCKED_ZONE(zone));
04694 
04695         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
04696                 /*
04697                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
04698                  */
04699                 INSIST(isc_refcount_current(&zone->erefs) == 0);
04700                 return (ISC_TRUE);
04701         }
04702         return (ISC_FALSE);
04703 }
04704 
04705 static isc_boolean_t
04706 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
04707               dns_name_t *name, isc_boolean_t logit)
04708 {
04709         isc_result_t result;
04710         char namebuf[DNS_NAME_FORMATSIZE];
04711         char altbuf[DNS_NAME_FORMATSIZE];
04712         dns_fixedname_t fixed;
04713         dns_name_t *foundname;
04714         int level;
04715 
04716         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
04717                 return (ISC_TRUE);
04718 
04719         if (zone->type == dns_zone_master)
04720                 level = ISC_LOG_ERROR;
04721         else
04722                 level = ISC_LOG_WARNING;
04723 
04724         dns_fixedname_init(&fixed);
04725         foundname = dns_fixedname_name(&fixed);
04726 
04727         result = dns_db_find(db, name, version, dns_rdatatype_a,
04728                              0, 0, NULL, foundname, NULL, NULL);
04729         if (result == ISC_R_SUCCESS)
04730                 return (ISC_TRUE);
04731 
04732         if (result == DNS_R_NXRRSET) {
04733                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
04734                                      0, 0, NULL, foundname, NULL, NULL);
04735                 if (result == ISC_R_SUCCESS)
04736                         return (ISC_TRUE);
04737         }
04738 
04739         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
04740             result == DNS_R_EMPTYNAME) {
04741                 if (logit) {
04742                         dns_name_format(name, namebuf, sizeof namebuf);
04743                         dns_zone_log(zone, level, "NS '%s' has no address "
04744                                      "records (A or AAAA)", namebuf);
04745                 }
04746                 return (ISC_FALSE);
04747         }
04748 
04749         if (result == DNS_R_CNAME) {
04750                 if (logit) {
04751                         dns_name_format(name, namebuf, sizeof namebuf);
04752                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
04753                                      "(illegal)", namebuf);
04754                 }
04755                 return (ISC_FALSE);
04756         }
04757 
04758         if (result == DNS_R_DNAME) {
04759                 if (logit) {
04760                         dns_name_format(name, namebuf, sizeof namebuf);
04761                         dns_name_format(foundname, altbuf, sizeof altbuf);
04762                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
04763                                      "'%s' (illegal)", namebuf, altbuf);
04764                 }
04765                 return (ISC_FALSE);
04766         }
04767 
04768         return (ISC_TRUE);
04769 }
04770 
04771 static isc_result_t
04772 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
04773                  dns_dbversion_t *version, unsigned int *nscount,
04774                  unsigned int *errors, isc_boolean_t logit)
04775 {
04776         isc_result_t result;
04777         unsigned int count = 0;
04778         unsigned int ecount = 0;
04779         dns_rdataset_t rdataset;
04780         dns_rdata_t rdata;
04781         dns_rdata_ns_t ns;
04782 
04783         dns_rdataset_init(&rdataset);
04784         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
04785                                      dns_rdatatype_none, 0, &rdataset, NULL);
04786         if (result == ISC_R_NOTFOUND) {
04787                 INSIST(!dns_rdataset_isassociated(&rdataset));
04788                 goto success;
04789         }
04790         if (result != ISC_R_SUCCESS) {
04791                 INSIST(!dns_rdataset_isassociated(&rdataset));
04792                 goto invalidate_rdataset;
04793         }
04794 
04795         result = dns_rdataset_first(&rdataset);
04796         while (result == ISC_R_SUCCESS) {
04797                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
04798                     (zone->type == dns_zone_master ||
04799                      zone->type == dns_zone_slave)) {
04800                         dns_rdata_init(&rdata);
04801                         dns_rdataset_current(&rdataset, &rdata);
04802                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
04803                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
04804                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
04805                             !zone_check_ns(zone, db, version, &ns.name, logit))
04806                                 ecount++;
04807                 }
04808                 count++;
04809                 result = dns_rdataset_next(&rdataset);
04810         }
04811         dns_rdataset_disassociate(&rdataset);
04812 
04813  success:
04814         if (nscount != NULL)
04815                 *nscount = count;
04816         if (errors != NULL)
04817                 *errors = ecount;
04818 
04819         result = ISC_R_SUCCESS;
04820 
04821  invalidate_rdataset:
04822         dns_rdataset_invalidate(&rdataset);
04823 
04824         return (result);
04825 }
04826 
04827 static isc_result_t
04828 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
04829                  unsigned int *soacount,
04830                  isc_uint32_t *serial, isc_uint32_t *refresh,
04831                  isc_uint32_t *retry, isc_uint32_t *expire,
04832                  isc_uint32_t *minimum)
04833 {
04834         isc_result_t result;
04835         unsigned int count;
04836         dns_rdataset_t rdataset;
04837         dns_rdata_t rdata = DNS_RDATA_INIT;
04838         dns_rdata_soa_t soa;
04839 
04840         dns_rdataset_init(&rdataset);
04841         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
04842                                      dns_rdatatype_none, 0, &rdataset, NULL);
04843         if (result == ISC_R_NOTFOUND) {
04844                 INSIST(!dns_rdataset_isassociated(&rdataset));
04845                 if (soacount != NULL)
04846                         *soacount = 0;
04847                 if (serial != NULL)
04848                         *serial = 0;
04849                 if (refresh != NULL)
04850                         *refresh = 0;
04851                 if (retry != NULL)
04852                         *retry = 0;
04853                 if (expire != NULL)
04854                         *expire = 0;
04855                 if (minimum != NULL)
04856                         *minimum = 0;
04857                 result = ISC_R_SUCCESS;
04858                 goto invalidate_rdataset;
04859         }
04860         if (result != ISC_R_SUCCESS) {
04861                 INSIST(!dns_rdataset_isassociated(&rdataset));
04862                 goto invalidate_rdataset;
04863         }
04864 
04865         count = 0;
04866         result = dns_rdataset_first(&rdataset);
04867         while (result == ISC_R_SUCCESS) {
04868                 dns_rdata_init(&rdata);
04869                 dns_rdataset_current(&rdataset, &rdata);
04870                 count++;
04871                 if (count == 1) {
04872                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
04873                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
04874                 }
04875 
04876                 result = dns_rdataset_next(&rdataset);
04877                 dns_rdata_reset(&rdata);
04878         }
04879         dns_rdataset_disassociate(&rdataset);
04880 
04881         if (soacount != NULL)
04882                 *soacount = count;
04883 
04884         if (count > 0) {
04885                 if (serial != NULL)
04886                         *serial = soa.serial;
04887                 if (refresh != NULL)
04888                         *refresh = soa.refresh;
04889                 if (retry != NULL)
04890                         *retry = soa.retry;
04891                 if (expire != NULL)
04892                         *expire = soa.expire;
04893                 if (minimum != NULL)
04894                         *minimum = soa.minimum;
04895         } else {
04896                 if (soacount != NULL)
04897                         *soacount = 0;
04898                 if (serial != NULL)
04899                         *serial = 0;
04900                 if (refresh != NULL)
04901                         *refresh = 0;
04902                 if (retry != NULL)
04903                         *retry = 0;
04904                 if (expire != NULL)
04905                         *expire = 0;
04906                 if (minimum != NULL)
04907                         *minimum = 0;
04908         }
04909 
04910         result = ISC_R_SUCCESS;
04911 
04912  invalidate_rdataset:
04913         dns_rdataset_invalidate(&rdataset);
04914 
04915         return (result);
04916 }
04917 
04918 /*
04919  * zone must be locked.
04920  */
04921 static isc_result_t
04922 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
04923                  unsigned int *soacount, isc_uint32_t *serial,
04924                  isc_uint32_t *refresh, isc_uint32_t *retry,
04925                  isc_uint32_t *expire, isc_uint32_t *minimum,
04926                  unsigned int *errors)
04927 {
04928         isc_result_t result;
04929         isc_result_t answer = ISC_R_SUCCESS;
04930         dns_dbversion_t *version = NULL;
04931         dns_dbnode_t *node;
04932 
04933         REQUIRE(db != NULL);
04934         REQUIRE(zone != NULL);
04935 
04936         dns_db_currentversion(db, &version);
04937 
04938         if (nscount != NULL)
04939                 *nscount = 0;
04940         if (soacount != NULL)
04941                 *soacount = 0;
04942         if (serial != NULL)
04943                 *serial = 0;
04944         if (refresh != NULL)
04945                 *refresh = 0;
04946         if (retry != NULL)
04947                 *retry = 0;
04948         if (expire != NULL)
04949                 *expire = 0;
04950         if (errors != NULL)
04951                 *errors = 0;
04952 
04953         node = NULL;
04954         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
04955         if (result != ISC_R_SUCCESS) {
04956                 answer = result;
04957                 goto closeversion;
04958         }
04959 
04960         if (nscount != NULL || errors != NULL) {
04961                 result = zone_count_ns_rr(zone, db, node, version,
04962                                           nscount, errors, ISC_TRUE);
04963                 if (result != ISC_R_SUCCESS)
04964                         answer = result;
04965         }
04966 
04967         if (soacount != NULL || serial != NULL || refresh != NULL
04968             || retry != NULL || expire != NULL || minimum != NULL) {
04969                 result = zone_load_soa_rr(db, node, version, soacount,
04970                                           serial, refresh, retry, expire,
04971                                           minimum);
04972                 if (result != ISC_R_SUCCESS)
04973                         answer = result;
04974         }
04975 
04976         dns_db_detachnode(db, &node);
04977  closeversion:
04978         dns_db_closeversion(db, &version, ISC_FALSE);
04979 
04980         return (answer);
04981 }
04982 
04983 void
04984 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
04985         REQUIRE(DNS_ZONE_VALID(source));
04986         REQUIRE(target != NULL && *target == NULL);
04987         isc_refcount_increment(&source->erefs, NULL);
04988         *target = source;
04989 }
04990 
04991 void
04992 dns_zone_detach(dns_zone_t **zonep) {
04993         dns_zone_t *zone;
04994         dns_zone_t *raw = NULL;
04995         dns_zone_t *secure = NULL;
04996         unsigned int refs;
04997         isc_boolean_t free_now = ISC_FALSE;
04998 
04999         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
05000 
05001         zone = *zonep;
05002 
05003         isc_refcount_decrement(&zone->erefs, &refs);
05004 
05005         if (refs == 0) {
05006                 LOCK_ZONE(zone);
05007                 INSIST(zone != zone->raw);
05008                 /*
05009                  * We just detached the last external reference.
05010                  */
05011                 if (zone->task != NULL) {
05012                         /*
05013                          * This zone is being managed.  Post
05014                          * its control event and let it clean
05015                          * up synchronously in the context of
05016                          * its task.
05017                          */
05018                         isc_event_t *ev = &zone->ctlevent;
05019                         isc_task_send(zone->task, &ev);
05020                 } else {
05021                         /*
05022                          * This zone is not being managed; it has
05023                          * no task and can have no outstanding
05024                          * events.  Free it immediately.
05025                          */
05026                         /*
05027                          * Unmanaged zones should not have non-null views;
05028                          * we have no way of detaching from the view here
05029                          * without causing deadlock because this code is called
05030                          * with the view already locked.
05031                          */
05032                         INSIST(zone->view == NULL);
05033                         free_now = ISC_TRUE;
05034                         raw = zone->raw;
05035                         zone->raw = NULL;
05036                         secure = zone->secure;
05037                         zone->secure = NULL;
05038                 }
05039                 UNLOCK_ZONE(zone);
05040         }
05041         *zonep = NULL;
05042         if (free_now) {
05043                 if (raw != NULL)
05044                         dns_zone_detach(&raw);
05045                 if (secure != NULL)
05046                         dns_zone_idetach(&secure);
05047                 zone_free(zone);
05048         }
05049 }
05050 
05051 void
05052 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
05053         REQUIRE(DNS_ZONE_VALID(source));
05054         REQUIRE(target != NULL && *target == NULL);
05055         LOCK_ZONE(source);
05056         zone_iattach(source, target);
05057         UNLOCK_ZONE(source);
05058 }
05059 
05060 static void
05061 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
05062 
05063         /*
05064          * 'source' locked by caller.
05065          */
05066         REQUIRE(LOCKED_ZONE(source));
05067         REQUIRE(DNS_ZONE_VALID(source));
05068         REQUIRE(target != NULL && *target == NULL);
05069         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
05070         source->irefs++;
05071         INSIST(source->irefs != 0);
05072         *target = source;
05073 }
05074 
05075 static void
05076 zone_idetach(dns_zone_t **zonep) {
05077         dns_zone_t *zone;
05078 
05079         /*
05080          * 'zone' locked by caller.
05081          */
05082         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
05083         zone = *zonep;
05084         REQUIRE(LOCKED_ZONE(*zonep));
05085         *zonep = NULL;
05086 
05087         INSIST(zone->irefs > 0);
05088         zone->irefs--;
05089         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
05090 }
05091 
05092 void
05093 dns_zone_idetach(dns_zone_t **zonep) {
05094         dns_zone_t *zone;
05095         isc_boolean_t free_needed;
05096 
05097         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
05098         zone = *zonep;
05099         *zonep = NULL;
05100 
05101         LOCK_ZONE(zone);
05102         INSIST(zone->irefs > 0);
05103         zone->irefs--;
05104         free_needed = exit_check(zone);
05105         UNLOCK_ZONE(zone);
05106         if (free_needed)
05107                 zone_free(zone);
05108 }
05109 
05110 isc_mem_t *
05111 dns_zone_getmctx(dns_zone_t *zone) {
05112         REQUIRE(DNS_ZONE_VALID(zone));
05113 
05114         return (zone->mctx);
05115 }
05116 
05117 dns_zonemgr_t *
05118 dns_zone_getmgr(dns_zone_t *zone) {
05119         REQUIRE(DNS_ZONE_VALID(zone));
05120 
05121         return (zone->zmgr);
05122 }
05123 
05124 void
05125 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
05126         REQUIRE(DNS_ZONE_VALID(zone));
05127 
05128         LOCK_ZONE(zone);
05129         if (value)
05130                 DNS_ZONE_SETFLAG(zone, flags);
05131         else
05132                 DNS_ZONE_CLRFLAG(zone, flags);
05133         UNLOCK_ZONE(zone);
05134 }
05135 
05136 void
05137 dns_zone_setoption(dns_zone_t *zone, unsigned int option,
05138                    isc_boolean_t value)
05139 {
05140         REQUIRE(DNS_ZONE_VALID(zone));
05141 
05142         LOCK_ZONE(zone);
05143         if (value)
05144                 zone->options |= option;
05145         else
05146                 zone->options &= ~option;
05147         UNLOCK_ZONE(zone);
05148 }
05149 
05150 void
05151 dns_zone_setoption2(dns_zone_t *zone, unsigned int option,
05152                     isc_boolean_t value)
05153 {
05154         REQUIRE(DNS_ZONE_VALID(zone));
05155 
05156         LOCK_ZONE(zone);
05157         if (value)
05158                 zone->options2 |= option;
05159         else
05160                 zone->options2 &= ~option;
05161         UNLOCK_ZONE(zone);
05162 }
05163 
05164 unsigned int
05165 dns_zone_getoptions(dns_zone_t *zone) {
05166         REQUIRE(DNS_ZONE_VALID(zone));
05167 
05168         return (zone->options);
05169 }
05170 
05171 unsigned int
05172 dns_zone_getoptions2(dns_zone_t *zone) {
05173         REQUIRE(DNS_ZONE_VALID(zone));
05174 
05175         return (zone->options2);
05176 }
05177 
05178 void
05179 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
05180 {
05181         REQUIRE(DNS_ZONE_VALID(zone));
05182 
05183         LOCK_ZONE(zone);
05184         if (value)
05185                 zone->keyopts |= keyopt;
05186         else
05187                 zone->keyopts &= ~keyopt;
05188         UNLOCK_ZONE(zone);
05189 }
05190 
05191 unsigned int
05192 dns_zone_getkeyopts(dns_zone_t *zone) {
05193 
05194         REQUIRE(DNS_ZONE_VALID(zone));
05195 
05196         return (zone->keyopts);
05197 }
05198 
05199 isc_result_t
05200 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
05201         REQUIRE(DNS_ZONE_VALID(zone));
05202 
05203         LOCK_ZONE(zone);
05204         zone->xfrsource4 = *xfrsource;
05205         UNLOCK_ZONE(zone);
05206 
05207         return (ISC_R_SUCCESS);
05208 }
05209 
05210 isc_sockaddr_t *
05211 dns_zone_getxfrsource4(dns_zone_t *zone) {
05212         REQUIRE(DNS_ZONE_VALID(zone));
05213         return (&zone->xfrsource4);
05214 }
05215 
05216 isc_result_t
05217 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
05218         REQUIRE(DNS_ZONE_VALID(zone));
05219 
05220         LOCK_ZONE(zone);
05221         zone->xfrsource4dscp = dscp;
05222         UNLOCK_ZONE(zone);
05223 
05224         return (ISC_R_SUCCESS);
05225 }
05226 
05227 isc_dscp_t
05228 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
05229         REQUIRE(DNS_ZONE_VALID(zone));
05230         return (zone->xfrsource4dscp);
05231 }
05232 
05233 isc_result_t
05234 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
05235         REQUIRE(DNS_ZONE_VALID(zone));
05236 
05237         LOCK_ZONE(zone);
05238         zone->xfrsource6 = *xfrsource;
05239         UNLOCK_ZONE(zone);
05240 
05241         return (ISC_R_SUCCESS);
05242 }
05243 
05244 isc_sockaddr_t *
05245 dns_zone_getxfrsource6(dns_zone_t *zone) {
05246         REQUIRE(DNS_ZONE_VALID(zone));
05247         return (&zone->xfrsource6);
05248 }
05249 
05250 isc_dscp_t
05251 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
05252         REQUIRE(DNS_ZONE_VALID(zone));
05253         return (zone->xfrsource6dscp);
05254 }
05255 
05256 isc_result_t
05257 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
05258         REQUIRE(DNS_ZONE_VALID(zone));
05259 
05260         LOCK_ZONE(zone);
05261         zone->xfrsource6dscp = dscp;
05262         UNLOCK_ZONE(zone);
05263 
05264         return (ISC_R_SUCCESS);
05265 }
05266 
05267 isc_result_t
05268 dns_zone_setaltxfrsource4(dns_zone_t *zone,
05269                           const isc_sockaddr_t *altxfrsource)
05270 {
05271         REQUIRE(DNS_ZONE_VALID(zone));
05272 
05273         LOCK_ZONE(zone);
05274         zone->altxfrsource4 = *altxfrsource;
05275         UNLOCK_ZONE(zone);
05276 
05277         return (ISC_R_SUCCESS);
05278 }
05279 
05280 isc_sockaddr_t *
05281 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
05282         REQUIRE(DNS_ZONE_VALID(zone));
05283         return (&zone->altxfrsource4);
05284 }
05285 
05286 isc_result_t
05287 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
05288         REQUIRE(DNS_ZONE_VALID(zone));
05289 
05290         LOCK_ZONE(zone);
05291         zone->altxfrsource4dscp = dscp;
05292         UNLOCK_ZONE(zone);
05293 
05294         return (ISC_R_SUCCESS);
05295 }
05296 
05297 isc_dscp_t
05298 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
05299         REQUIRE(DNS_ZONE_VALID(zone));
05300         return (zone->altxfrsource4dscp);
05301 }
05302 
05303 isc_result_t
05304 dns_zone_setaltxfrsource6(dns_zone_t *zone,
05305                           const isc_sockaddr_t *altxfrsource)
05306 {
05307         REQUIRE(DNS_ZONE_VALID(zone));
05308 
05309         LOCK_ZONE(zone);
05310         zone->altxfrsource6 = *altxfrsource;
05311         UNLOCK_ZONE(zone);
05312 
05313         return (ISC_R_SUCCESS);
05314 }
05315 
05316 isc_sockaddr_t *
05317 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
05318         REQUIRE(DNS_ZONE_VALID(zone));
05319         return (&zone->altxfrsource6);
05320 }
05321 
05322 isc_result_t
05323 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
05324         REQUIRE(DNS_ZONE_VALID(zone));
05325 
05326         LOCK_ZONE(zone);
05327         zone->altxfrsource6dscp = dscp;
05328         UNLOCK_ZONE(zone);
05329 
05330         return (ISC_R_SUCCESS);
05331 }
05332 
05333 isc_dscp_t
05334 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
05335         REQUIRE(DNS_ZONE_VALID(zone));
05336         return (zone->altxfrsource6dscp);
05337 }
05338 
05339 isc_result_t
05340 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
05341         REQUIRE(DNS_ZONE_VALID(zone));
05342 
05343         LOCK_ZONE(zone);
05344         zone->notifysrc4 = *notifysrc;
05345         UNLOCK_ZONE(zone);
05346 
05347         return (ISC_R_SUCCESS);
05348 }
05349 
05350 isc_sockaddr_t *
05351 dns_zone_getnotifysrc4(dns_zone_t *zone) {
05352         REQUIRE(DNS_ZONE_VALID(zone));
05353         return (&zone->notifysrc4);
05354 }
05355 
05356 isc_result_t
05357 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
05358         REQUIRE(DNS_ZONE_VALID(zone));
05359 
05360         LOCK_ZONE(zone);
05361         zone->notifysrc4dscp = dscp;
05362         UNLOCK_ZONE(zone);
05363 
05364         return (ISC_R_SUCCESS);
05365 }
05366 
05367 isc_dscp_t
05368 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
05369         REQUIRE(DNS_ZONE_VALID(zone));
05370         return (zone->notifysrc4dscp);
05371 }
05372 
05373 isc_result_t
05374 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
05375         REQUIRE(DNS_ZONE_VALID(zone));
05376 
05377         LOCK_ZONE(zone);
05378         zone->notifysrc6 = *notifysrc;
05379         UNLOCK_ZONE(zone);
05380 
05381         return (ISC_R_SUCCESS);
05382 }
05383 
05384 isc_sockaddr_t *
05385 dns_zone_getnotifysrc6(dns_zone_t *zone) {
05386         REQUIRE(DNS_ZONE_VALID(zone));
05387         return (&zone->notifysrc6);
05388 }
05389 
05390 static isc_boolean_t
05391 same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
05392              isc_uint32_t count)
05393 {
05394         unsigned int i;
05395 
05396         for (i = 0; i < count; i++)
05397                 if (!isc_sockaddr_equal(&old[i], &new[i]))
05398                         return (ISC_FALSE);
05399         return (ISC_TRUE);
05400 }
05401 
05402 static isc_boolean_t
05403 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
05404         unsigned int i;
05405 
05406         if (old == NULL && new == NULL)
05407                 return (ISC_TRUE);
05408         if (old == NULL || new == NULL)
05409                 return (ISC_FALSE);
05410 
05411         for (i = 0; i < count; i++) {
05412                 if (old[i] == NULL && new[i] == NULL)
05413                         continue;
05414                 if (old[i] == NULL || new[i] == NULL ||
05415                      !dns_name_equal(old[i], new[i]))
05416                         return (ISC_FALSE);
05417         }
05418         return (ISC_TRUE);
05419 }
05420 
05421 static void
05422 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
05423                      dns_name_t ***keynamesp, unsigned int *countp,
05424                      isc_mem_t *mctx)
05425 {
05426         unsigned int count;
05427         isc_sockaddr_t *addrs;
05428         isc_dscp_t *dscps;
05429         dns_name_t **keynames;
05430 
05431         REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
05432                 keynamesp != NULL);
05433 
05434         count = *countp;
05435         *countp = 0;
05436         addrs = *addrsp;
05437         *addrsp = NULL;
05438         dscps = *dscpsp;
05439         *dscpsp = NULL;
05440         keynames = *keynamesp;
05441         *keynamesp = NULL;
05442 
05443         if (addrs != NULL)
05444                 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
05445 
05446         if (dscps != NULL)
05447                 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
05448 
05449         if (keynames != NULL) {
05450                 unsigned int i;
05451                 for (i = 0; i < count; i++) {
05452                         if (keynames[i] != NULL) {
05453                                 dns_name_free(keynames[i], mctx);
05454                                 isc_mem_put(mctx, keynames[i],
05455                                             sizeof(dns_name_t));
05456                                 keynames[i] = NULL;
05457                         }
05458                 }
05459                 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
05460         }
05461 }
05462 
05463 static isc_result_t
05464 set_addrkeylist(unsigned int count,
05465                 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
05466                 const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
05467                 dns_name_t **names, dns_name_t ***newnamesp,
05468                 isc_mem_t *mctx)
05469 {
05470         isc_result_t result;
05471         isc_sockaddr_t *newaddrs = NULL;
05472         isc_dscp_t *newdscp = NULL;
05473         dns_name_t **newnames = NULL;
05474         unsigned int i;
05475 
05476         REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
05477         REQUIRE(newdscpp != NULL && *newdscpp == NULL);
05478         REQUIRE(newnamesp != NULL && *newnamesp == NULL);
05479 
05480         newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
05481         if (newaddrs == NULL)
05482                 return (ISC_R_NOMEMORY);
05483         memmove(newaddrs, addrs, count * sizeof(*newaddrs));
05484 
05485         if (dscp != NULL) {
05486                 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
05487                 if (newdscp == NULL) {
05488                         isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
05489                         return (ISC_R_NOMEMORY);
05490                 }
05491                 memmove(newdscp, dscp, count * sizeof(*newdscp));
05492         } else
05493                 newdscp = NULL;
05494 
05495         if (names != NULL) {
05496                 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
05497                 if (newnames == NULL) {
05498                         if (newdscp != NULL)
05499                                 isc_mem_put(mctx, newdscp,
05500                                             count * sizeof(*newdscp));
05501                         isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
05502                         return (ISC_R_NOMEMORY);
05503                 }
05504                 for (i = 0; i < count; i++)
05505                         newnames[i] = NULL;
05506                 for (i = 0; i < count; i++) {
05507                         if (names[i] != NULL) {
05508                                 newnames[i] = isc_mem_get(mctx,
05509                                                          sizeof(dns_name_t));
05510                                 if (newnames[i] == NULL)
05511                                         goto allocfail;
05512                                 dns_name_init(newnames[i], NULL);
05513                                 result = dns_name_dup(names[i], mctx,
05514                                                       newnames[i]);
05515                                 if (result != ISC_R_SUCCESS) {
05516                                 allocfail:
05517                                         for (i = 0; i < count; i++)
05518                                                 if (newnames[i] != NULL)
05519                                                         dns_name_free(
05520                                                                newnames[i],
05521                                                                mctx);
05522                                         isc_mem_put(mctx, newaddrs,
05523                                                     count * sizeof(*newaddrs));
05524                                         isc_mem_put(mctx, newdscp,
05525                                                     count * sizeof(*newdscp));
05526                                         isc_mem_put(mctx, newnames,
05527                                                     count * sizeof(*newnames));
05528                                         return (ISC_R_NOMEMORY);
05529                                 }
05530                         }
05531                 }
05532         } else
05533                 newnames = NULL;
05534 
05535         *newdscpp = newdscp;
05536         *newaddrsp = newaddrs;
05537         *newnamesp = newnames;
05538         return (ISC_R_SUCCESS);
05539 }
05540 
05541 isc_result_t
05542 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
05543         REQUIRE(DNS_ZONE_VALID(zone));
05544 
05545         LOCK_ZONE(zone);
05546         zone->notifysrc6dscp = dscp;
05547         UNLOCK_ZONE(zone);
05548 
05549         return (ISC_R_SUCCESS);
05550 }
05551 
05552 isc_dscp_t
05553 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
05554         REQUIRE(DNS_ZONE_VALID(zone));
05555         return (zone->notifysrc6dscp);
05556 }
05557 
05558 isc_result_t
05559 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
05560                        isc_uint32_t count)
05561 {
05562         return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
05563                                                count));
05564 }
05565 
05566 isc_result_t
05567 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
05568                                dns_name_t **keynames, isc_uint32_t count)
05569 {
05570         return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
05571                                                count));
05572 }
05573 
05574 isc_result_t
05575 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
05576                                const isc_dscp_t *dscps, dns_name_t **keynames,
05577                                isc_uint32_t count)
05578 {
05579         isc_result_t result;
05580         isc_sockaddr_t *newaddrs = NULL;
05581         isc_dscp_t *newdscps = NULL;
05582         dns_name_t **newnames = NULL;
05583 
05584         REQUIRE(DNS_ZONE_VALID(zone));
05585         REQUIRE(count == 0 || notify != NULL);
05586         if (keynames != NULL)
05587                 REQUIRE(count != 0);
05588 
05589         LOCK_ZONE(zone);
05590 
05591         if (count == zone->notifycnt &&
05592             same_addrs(zone->notify, notify, count) &&
05593             same_keynames(zone->notifykeynames, keynames, count))
05594                 goto unlock;
05595 
05596         clear_addresskeylist(&zone->notify, &zone->notifydscp,
05597                              &zone->notifykeynames, &zone->notifycnt,
05598                              zone->mctx);
05599 
05600         if (count == 0)
05601                 goto unlock;
05602 
05603         /*
05604          * Set up the notify and notifykey lists
05605          */
05606         result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
05607                                  keynames, &newnames, zone->mctx);
05608         if (result != ISC_R_SUCCESS)
05609                 goto unlock;
05610 
05611         /*
05612          * Everything is ok so attach to the zone.
05613          */
05614         zone->notify = newaddrs;
05615         zone->notifydscp = newdscps;
05616         zone->notifykeynames = newnames;
05617         zone->notifycnt = count;
05618  unlock:
05619         UNLOCK_ZONE(zone);
05620         return (ISC_R_SUCCESS);
05621 }
05622 
05623 isc_result_t
05624 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
05625                     isc_uint32_t count)
05626 {
05627         isc_result_t result;
05628 
05629         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
05630         return (result);
05631 }
05632 
05633 isc_result_t
05634 dns_zone_setmasterswithkeys(dns_zone_t *zone,
05635                             const isc_sockaddr_t *masters,
05636                             dns_name_t **keynames,
05637                             isc_uint32_t count)
05638 {
05639         isc_result_t result = ISC_R_SUCCESS;
05640         isc_sockaddr_t *newaddrs = NULL;
05641         isc_dscp_t *newdscps = NULL;
05642         dns_name_t **newnames = NULL;
05643         isc_boolean_t *newok;
05644         unsigned int i;
05645 
05646         REQUIRE(DNS_ZONE_VALID(zone));
05647         REQUIRE(count == 0 || masters != NULL);
05648         if (keynames != NULL) {
05649                 REQUIRE(count != 0);
05650         }
05651 
05652         LOCK_ZONE(zone);
05653         /*
05654          * The refresh code assumes that 'masters' wouldn't change under it.
05655          * If it will change then kill off any current refresh in progress
05656          * and update the masters info.  If it won't change then we can just
05657          * unlock and exit.
05658          */
05659         if (count != zone->masterscnt ||
05660             !same_addrs(zone->masters, masters, count) ||
05661             !same_keynames(zone->masterkeynames, keynames, count)) {
05662                 if (zone->request != NULL)
05663                         dns_request_cancel(zone->request);
05664         } else
05665                 goto unlock;
05666 
05667         /*
05668          * This needs to happen before clear_addresskeylist() sets
05669          * zone->masterscnt to 0:
05670          */
05671         if (zone->mastersok != NULL) {
05672                 isc_mem_put(zone->mctx, zone->mastersok,
05673                             zone->masterscnt * sizeof(isc_boolean_t));
05674                 zone->mastersok = NULL;
05675         }
05676         clear_addresskeylist(&zone->masters, &zone->masterdscps,
05677                              &zone->masterkeynames, &zone->masterscnt,
05678                              zone->mctx);
05679         /*
05680          * If count == 0, don't allocate any space for masters, mastersok or
05681          * keynames so internally, those pointers are NULL if count == 0
05682          */
05683         if (count == 0)
05684                 goto unlock;
05685 
05686         /*
05687          * mastersok must contain count elements
05688          */
05689         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
05690         if (newok == NULL) {
05691                 result = ISC_R_NOMEMORY;
05692                 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
05693                 goto unlock;
05694         };
05695         for (i = 0; i < count; i++)
05696                 newok[i] = ISC_FALSE;
05697 
05698         /*
05699          * Now set up the masters and masterkey lists
05700          */
05701         result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
05702                                  keynames, &newnames, zone->mctx);
05703         INSIST(newdscps == NULL);
05704         if (result != ISC_R_SUCCESS) {
05705                 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
05706                 goto unlock;
05707         }
05708 
05709         /*
05710          * Everything is ok so attach to the zone.
05711          */
05712         zone->curmaster = 0;
05713         zone->mastersok = newok;
05714         zone->masters = newaddrs;
05715         zone->masterdscps = newdscps;
05716         zone->masterkeynames = newnames;
05717         zone->masterscnt = count;
05718         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
05719 
05720  unlock:
05721         UNLOCK_ZONE(zone);
05722         return (result);
05723 }
05724 
05725 isc_result_t
05726 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
05727         isc_result_t result = ISC_R_SUCCESS;
05728 
05729         REQUIRE(DNS_ZONE_VALID(zone));
05730 
05731         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
05732         if (zone->db == NULL)
05733                 result = DNS_R_NOTLOADED;
05734         else
05735                 dns_db_attach(zone->db, dpb);
05736         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
05737 
05738         return (result);
05739 }
05740 
05741 void
05742 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
05743         REQUIRE(DNS_ZONE_VALID(zone));
05744         REQUIRE(zone->type == dns_zone_staticstub);
05745 
05746         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
05747         REQUIRE(zone->db == NULL);
05748         dns_db_attach(db, &zone->db);
05749         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
05750 }
05751 
05752 /*
05753  * Co-ordinates the starting of routine jobs.
05754  */
05755 
05756 void
05757 dns_zone_maintenance(dns_zone_t *zone) {
05758         const char me[] = "dns_zone_maintenance";
05759         isc_time_t now;
05760 
05761         REQUIRE(DNS_ZONE_VALID(zone));
05762         ENTER;
05763 
05764         LOCK_ZONE(zone);
05765         TIME_NOW(&now);
05766         zone_settimer(zone, &now);
05767         UNLOCK_ZONE(zone);
05768 }
05769 
05770 static inline isc_boolean_t
05771 was_dumping(dns_zone_t *zone) {
05772         isc_boolean_t dumping;
05773 
05774         REQUIRE(LOCKED_ZONE(zone));
05775 
05776         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
05777         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
05778         if (!dumping) {
05779                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
05780                 isc_time_settoepoch(&zone->dumptime);
05781         }
05782         return (dumping);
05783 }
05784 
05785 static isc_result_t
05786 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
05787                isc_mem_t *mctx, unsigned int maxkeys,
05788                dst_key_t **keys, unsigned int *nkeys)
05789 {
05790         isc_result_t result;
05791         dns_dbnode_t *node = NULL;
05792         const char *directory = dns_zone_getkeydirectory(zone);
05793 
05794         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
05795         memset(keys, 0, sizeof(*keys) * maxkeys);
05796         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
05797                                           directory, mctx, maxkeys, keys,
05798                                           nkeys);
05799         if (result == ISC_R_NOTFOUND)
05800                 result = ISC_R_SUCCESS;
05801  failure:
05802         if (node != NULL)
05803                 dns_db_detachnode(db, &node);
05804         return (result);
05805 }
05806 
05807 static isc_result_t
05808 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
05809         dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
05810 {
05811         isc_result_t result;
05812 
05813         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
05814                 return (ISC_R_SUCCESS);
05815         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
05816                                name, ttl, rdata);
05817         if (result != ISC_R_SUCCESS)
05818                 return (result);
05819         rdata->flags |= DNS_RDATA_OFFLINE;
05820         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
05821                                name, ttl, rdata);
05822         zonediff->offline = ISC_TRUE;
05823         return (result);
05824 }
05825 
05826 static void
05827 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
05828 {
05829         unsigned int delta;
05830         char timebuf[80];
05831 
05832         zone->key_expiry = when;
05833         if (when <= now) {
05834                 dns_zone_log(zone, ISC_LOG_ERROR,
05835                              "DNSKEY RRSIG(s) have expired");
05836                 isc_time_settoepoch(&zone->keywarntime);
05837         } else if (when < now + 7 * 24 * 3600) {
05838                 isc_time_t t;
05839                 isc_time_set(&t, when, 0);
05840                 isc_time_formattimestamp(&t, timebuf, 80);
05841                 dns_zone_log(zone, ISC_LOG_WARNING,
05842                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
05843                              timebuf);
05844                 delta = when - now;
05845                 delta--;                /* loop prevention */
05846                 delta /= 24 * 3600;     /* to whole days */
05847                 delta *= 24 * 3600;     /* to seconds */
05848                 isc_time_set(&zone->keywarntime, when - delta, 0);
05849         }  else {
05850                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
05851                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
05852                 dns_zone_log(zone, ISC_LOG_NOTICE,
05853                              "setting keywarntime to %s", timebuf);
05854         }
05855 }
05856 
05857 /*
05858  * Helper function to del_sigs(). We don't want to delete RRSIGs that
05859  * have no new key.
05860  */
05861 static isc_boolean_t
05862 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
05863           isc_boolean_t *warn)
05864 {
05865         unsigned int i = 0;
05866         isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
05867         isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
05868 
05869         for (i = 0; i < nkeys; i++) {
05870                 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
05871                         continue;
05872                 if (dst_key_isprivate(keys[i])) {
05873                         if (KSK(keys[i]))
05874                                 have_ksk = have_pksk = ISC_TRUE;
05875                         else
05876                                 have_zsk = have_pzsk = ISC_TRUE;
05877                 } else {
05878                         if (KSK(keys[i]))
05879                                 have_ksk = ISC_TRUE;
05880                         else
05881                                 have_zsk = ISC_TRUE;
05882                 }
05883         }
05884 
05885         if (have_zsk && have_ksk && !have_pzsk)
05886                 *warn = ISC_TRUE;
05887 
05888         /*
05889          * It's okay to delete a signature if there is an active key
05890          * with the same algorithm to replace it.
05891          */
05892         if (have_pksk || have_pzsk)
05893                 return (ISC_TRUE);
05894 
05895         /*
05896          * Failing that, it is *not* okay to delete a signature
05897          * if the associated public key is still in the DNSKEY RRset
05898          */
05899         for (i = 0; i < nkeys; i++) {
05900                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
05901                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
05902                         return (ISC_FALSE);
05903         }
05904 
05905         /*
05906          * But if the key is gone, then go ahead.
05907          */
05908         return (ISC_TRUE);
05909 }
05910 
05911 /*
05912  * Delete expired RRsigs and any RRsigs we are about to re-sign.
05913  * See also update.c:del_keysigs().
05914  */
05915 static isc_result_t
05916 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
05917          dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
05918          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
05919 {
05920         isc_result_t result;
05921         dns_dbnode_t *node = NULL;
05922         dns_rdataset_t rdataset;
05923         unsigned int i;
05924         dns_rdata_rrsig_t rrsig;
05925         isc_boolean_t found;
05926         isc_int64_t timewarn = 0, timemaybe = 0;
05927 
05928         dns_rdataset_init(&rdataset);
05929 
05930         if (type == dns_rdatatype_nsec3)
05931                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
05932         else
05933                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
05934         if (result == ISC_R_NOTFOUND)
05935                 return (ISC_R_SUCCESS);
05936         if (result != ISC_R_SUCCESS)
05937                 goto failure;
05938         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
05939                                      (isc_stdtime_t) 0, &rdataset, NULL);
05940         dns_db_detachnode(db, &node);
05941 
05942         if (result == ISC_R_NOTFOUND) {
05943                 INSIST(!dns_rdataset_isassociated(&rdataset));
05944                 return (ISC_R_SUCCESS);
05945         }
05946         if (result != ISC_R_SUCCESS) {
05947                 INSIST(!dns_rdataset_isassociated(&rdataset));
05948                 goto failure;
05949         }
05950 
05951         for (result = dns_rdataset_first(&rdataset);
05952              result == ISC_R_SUCCESS;
05953              result = dns_rdataset_next(&rdataset)) {
05954                 dns_rdata_t rdata = DNS_RDATA_INIT;
05955 
05956                 dns_rdataset_current(&rdataset, &rdata);
05957                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
05958                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
05959 
05960                 if (type != dns_rdatatype_dnskey) {
05961                         isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
05962                         if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
05963                                 result = update_one_rr(db, ver, zonediff->diff,
05964                                                DNS_DIFFOP_DELRESIGN, name,
05965                                                rdataset.ttl, &rdata);
05966                                 if (result != ISC_R_SUCCESS)
05967                                         break;
05968                                 deleted = ISC_TRUE;
05969                         }
05970                         if (warn) {
05971                                 /*
05972                                  * At this point, we've got an RRSIG,
05973                                  * which is signed by an inactive key.
05974                                  * An administrator needs to provide a new
05975                                  * key/alg, but until that time, we want to
05976                                  * keep the old RRSIG.  Marking the key as
05977                                  * offline will prevent us spinning waiting
05978                                  * for the private part.
05979                                  */
05980                                 if (incremental && !deleted) {
05981                                         result = offline(db, ver, zonediff,
05982                                                          name, rdataset.ttl,
05983                                                          &rdata);
05984                                         if (result != ISC_R_SUCCESS)
05985                                                 break;
05986                                 }
05987 
05988                                 /*
05989                                  * Log the key id and algorithm of
05990                                  * the inactive key with no replacement
05991                                  */
05992                                 if (zone->log_key_expired_timer <= now) {
05993                                         char origin[DNS_NAME_FORMATSIZE];
05994                                         char algbuf[DNS_NAME_FORMATSIZE];
05995                                         dns_name_format(&zone->origin, origin,
05996                                                         sizeof(origin));
05997                                         dns_secalg_format(rrsig.algorithm,
05998                                                           algbuf,
05999                                                           sizeof(algbuf));
06000                                         dns_zone_log(zone, ISC_LOG_WARNING,
06001                                                      "Key %s/%s/%d "
06002                                                      "missing or inactive "
06003                                                      "and has no replacement: "
06004                                                      "retaining signatures.",
06005                                                      origin, algbuf,
06006                                                      rrsig.keyid);
06007                                         zone->log_key_expired_timer = now +
06008                                                                         3600;
06009                                 }
06010                         }
06011                         continue;
06012                 }
06013 
06014                 /*
06015                  * RRSIG(DNSKEY) requires special processing.
06016                  */
06017                 found = ISC_FALSE;
06018                 for (i = 0; i < nkeys; i++) {
06019                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
06020                             rrsig.keyid == dst_key_id(keys[i])) {
06021                                 found = ISC_TRUE;
06022                                 /*
06023                                  * Mark offline RRSIG(DNSKEY).
06024                                  * We want the earliest offline expire time
06025                                  * iff there is a new offline signature.
06026                                  */
06027                                 if (!dst_key_inactive(keys[i]) &&
06028                                     !dst_key_isprivate(keys[i]))
06029                                 {
06030                                         isc_int64_t timeexpire =
06031                                            dns_time64_from32(rrsig.timeexpire);
06032                                         if (timewarn != 0 &&
06033                                             timewarn > timeexpire)
06034                                                 timewarn = timeexpire;
06035                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
06036                                                 if (timemaybe == 0 ||
06037                                                     timemaybe > timeexpire)
06038                                                         timemaybe = timeexpire;
06039                                                 break;
06040                                         }
06041                                         if (timewarn == 0)
06042                                                 timewarn = timemaybe;
06043                                         if (timewarn == 0 ||
06044                                             timewarn > timeexpire)
06045                                                 timewarn = timeexpire;
06046                                         result = offline(db, ver, zonediff,
06047                                                          name, rdataset.ttl,
06048                                                          &rdata);
06049                                         break;
06050                                 }
06051                                 result = update_one_rr(db, ver, zonediff->diff,
06052                                                        DNS_DIFFOP_DELRESIGN,
06053                                                        name, rdataset.ttl,
06054                                                        &rdata);
06055                                 break;
06056                         }
06057                 }
06058 
06059                 /*
06060                  * If there is not a matching DNSKEY then
06061                  * delete the RRSIG.
06062                  */
06063                 if (!found)
06064                         result = update_one_rr(db, ver, zonediff->diff,
06065                                                DNS_DIFFOP_DELRESIGN, name,
06066                                                rdataset.ttl, &rdata);
06067                 if (result != ISC_R_SUCCESS)
06068                         break;
06069         }
06070 
06071         dns_rdataset_disassociate(&rdataset);
06072         if (result == ISC_R_NOMORE)
06073                 result = ISC_R_SUCCESS;
06074         if (timewarn > 0) {
06075 #if defined(STDTIME_ON_32BITS)
06076                 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
06077                 if (timewarn == stdwarn)
06078 #endif
06079                         set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
06080                                                now);
06081 #if defined(STDTIME_ON_32BITS)
06082                 else
06083                         dns_zone_log(zone, ISC_LOG_ERROR,
06084                                      "key expiry warning time out of range");
06085 #endif
06086         }
06087  failure:
06088         if (node != NULL)
06089                 dns_db_detachnode(db, &node);
06090         return (result);
06091 }
06092 
06093 static isc_result_t
06094 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
06095          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
06096          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
06097          isc_stdtime_t expire, isc_boolean_t check_ksk,
06098          isc_boolean_t keyset_kskonly)
06099 {
06100         isc_result_t result;
06101         dns_dbnode_t *node = NULL;
06102         dns_rdataset_t rdataset;
06103         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
06104         unsigned char data[1024]; /* XXX */
06105         isc_buffer_t buffer;
06106         unsigned int i, j;
06107 
06108         dns_rdataset_init(&rdataset);
06109         isc_buffer_init(&buffer, data, sizeof(data));
06110 
06111         if (type == dns_rdatatype_nsec3)
06112                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
06113         else
06114                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
06115         if (result == ISC_R_NOTFOUND)
06116                 return (ISC_R_SUCCESS);
06117         if (result != ISC_R_SUCCESS)
06118                 goto failure;
06119         result = dns_db_findrdataset(db, node, ver, type, 0,
06120                                      (isc_stdtime_t) 0, &rdataset, NULL);
06121         dns_db_detachnode(db, &node);
06122         if (result == ISC_R_NOTFOUND) {
06123                 INSIST(!dns_rdataset_isassociated(&rdataset));
06124                 return (ISC_R_SUCCESS);
06125         }
06126         if (result != ISC_R_SUCCESS) {
06127                 INSIST(!dns_rdataset_isassociated(&rdataset));
06128                 goto failure;
06129         }
06130 
06131         for (i = 0; i < nkeys; i++) {
06132                 isc_boolean_t both = ISC_FALSE;
06133 
06134                 if (!dst_key_isprivate(keys[i]))
06135                         continue;
06136 
06137                 if (check_ksk && !REVOKE(keys[i])) {
06138                         isc_boolean_t have_ksk, have_nonksk;
06139                         if (KSK(keys[i])) {
06140                                 have_ksk = ISC_TRUE;
06141                                 have_nonksk = ISC_FALSE;
06142                         } else {
06143                                 have_ksk = ISC_FALSE;
06144                                 have_nonksk = ISC_TRUE;
06145                         }
06146                         for (j = 0; j < nkeys; j++) {
06147                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
06148                                         continue;
06149                                 if (REVOKE(keys[j]))
06150                                         continue;
06151                                 if (KSK(keys[j]))
06152                                         have_ksk = ISC_TRUE;
06153                                 else
06154                                         have_nonksk = ISC_TRUE;
06155                                 both = have_ksk && have_nonksk;
06156                                 if (both)
06157                                         break;
06158                         }
06159                 }
06160                 if (both) {
06161                         if (type == dns_rdatatype_dnskey) {
06162                                 if (!KSK(keys[i]) && keyset_kskonly)
06163                                         continue;
06164                         } else if (KSK(keys[i]))
06165                                 continue;
06166                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
06167                                 continue;
06168 
06169                 /* Calculate the signature, creating a RRSIG RDATA. */
06170                 isc_buffer_clear(&buffer);
06171                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
06172                                       &inception, &expire,
06173                                       mctx, &buffer, &sig_rdata));
06174                 /* Update the database and journal with the RRSIG. */
06175                 /* XXX inefficient - will cause dataset merging */
06176                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
06177                                     name, rdataset.ttl, &sig_rdata));
06178                 dns_rdata_reset(&sig_rdata);
06179                 isc_buffer_init(&buffer, data, sizeof(data));
06180         }
06181 
06182  failure:
06183         if (dns_rdataset_isassociated(&rdataset))
06184                 dns_rdataset_disassociate(&rdataset);
06185         if (node != NULL)
06186                 dns_db_detachnode(db, &node);
06187         return (result);
06188 }
06189 
06190 static void
06191 zone_resigninc(dns_zone_t *zone) {
06192         const char *me = "zone_resigninc";
06193         dns_db_t *db = NULL;
06194         dns_dbversion_t *version = NULL;
06195         dns_diff_t _sig_diff;
06196         zonediff_t zonediff;
06197         dns_fixedname_t fixed;
06198         dns_name_t *name;
06199         dns_rdataset_t rdataset;
06200         dns_rdatatype_t covers;
06201         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
06202         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
06203         isc_result_t result;
06204         isc_stdtime_t now, inception, soaexpire, expire, stop;
06205         isc_uint32_t jitter;
06206         unsigned int i;
06207         unsigned int nkeys = 0;
06208         unsigned int resign;
06209 
06210         ENTER;
06211 
06212         dns_rdataset_init(&rdataset);
06213         dns_fixedname_init(&fixed);
06214         dns_diff_init(zone->mctx, &_sig_diff);
06215         zonediff_init(&zonediff, &_sig_diff);
06216 
06217         /*
06218          * Zone is frozen or automatic resigning is disabled.
06219          * Pause for 5 minutes.
06220          */
06221         if (zone->update_disabled ||
06222             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
06223         {
06224                 result = ISC_R_FAILURE;
06225                 goto failure;
06226         }
06227 
06228         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
06229         dns_db_attach(zone->db, &db);
06230         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
06231 
06232         result = dns_db_newversion(db, &version);
06233         if (result != ISC_R_SUCCESS) {
06234                 dns_zone_log(zone, ISC_LOG_ERROR,
06235                              "zone_resigninc:dns_db_newversion -> %s",
06236                              dns_result_totext(result));
06237                 goto failure;
06238         }
06239 
06240         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
06241                                 zone_keys, &nkeys);
06242         if (result != ISC_R_SUCCESS) {
06243                 dns_zone_log(zone, ISC_LOG_ERROR,
06244                              "zone_resigninc:find_zone_keys -> %s",
06245                              dns_result_totext(result));
06246                 goto failure;
06247         }
06248 
06249         isc_stdtime_get(&now);
06250         inception = now - 3600; /* Allow for clock skew. */
06251         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
06252         /*
06253          * Spread out signatures over time if they happen to be
06254          * clumped.  We don't do this for each add_sigs() call as
06255          * we still want some clustering to occur.
06256          */
06257         isc_random_get(&jitter);
06258         expire = soaexpire - jitter % 3600;
06259         stop = now + 5;
06260 
06261         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
06262         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
06263 
06264         name = dns_fixedname_name(&fixed);
06265         result = dns_db_getsigningtime(db, &rdataset, name);
06266         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
06267                 dns_zone_log(zone, ISC_LOG_ERROR,
06268                              "zone_resigninc:dns_db_getsigningtime -> %s",
06269                              dns_result_totext(result));
06270         }
06271 
06272         i = 0;
06273         while (result == ISC_R_SUCCESS) {
06274                 resign = rdataset.resign - zone->sigresigninginterval;
06275                 covers = rdataset.covers;
06276                 dns_rdataset_disassociate(&rdataset);
06277 
06278                 /*
06279                  * Stop if we hit the SOA as that means we have walked the
06280                  * entire zone.  The SOA record should always be the most
06281                  * recent signature.
06282                  */
06283                 /* XXXMPA increase number of RRsets signed pre call */
06284                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
06285                     resign > stop)
06286                         break;
06287 
06288                 result = del_sigs(zone, db, version, name, covers, &zonediff,
06289                                   zone_keys, nkeys, now, ISC_TRUE);
06290                 if (result != ISC_R_SUCCESS) {
06291                         dns_zone_log(zone, ISC_LOG_ERROR,
06292                                      "zone_resigninc:del_sigs -> %s",
06293                                      dns_result_totext(result));
06294                         break;
06295                 }
06296 
06297                 result = add_sigs(db, version, name, covers, zonediff.diff,
06298                                   zone_keys, nkeys, zone->mctx, inception,
06299                                   expire, check_ksk, keyset_kskonly);
06300                 if (result != ISC_R_SUCCESS) {
06301                         dns_zone_log(zone, ISC_LOG_ERROR,
06302                                      "zone_resigninc:add_sigs -> %s",
06303                                      dns_result_totext(result));
06304                         break;
06305                 }
06306                 result  = dns_db_getsigningtime(db, &rdataset, name);
06307                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
06308                         result = ISC_R_SUCCESS;
06309                         break;
06310                 }
06311                 if (result != ISC_R_SUCCESS)
06312                         dns_zone_log(zone, ISC_LOG_ERROR,
06313                              "zone_resigninc:dns_db_getsigningtime -> %s",
06314                                      dns_result_totext(result));
06315         }
06316 
06317         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
06318                 goto failure;
06319 
06320         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
06321                           &zonediff, zone_keys, nkeys, now, ISC_TRUE);
06322         if (result != ISC_R_SUCCESS) {
06323                 dns_zone_log(zone, ISC_LOG_ERROR,
06324                              "zone_resigninc:del_sigs -> %s",
06325                              dns_result_totext(result));
06326                 goto failure;
06327         }
06328 
06329         /*
06330          * Did we change anything in the zone?
06331          */
06332         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
06333                 /*
06334                  * Commit the changes if any key has been marked as offline.                     */
06335                 if (zonediff.offline)
06336                         dns_db_closeversion(db, &version, ISC_TRUE);
06337                 goto failure;
06338         }
06339 
06340         /* Increment SOA serial if we have made changes */
06341         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
06342                                    zone->updatemethod);
06343         if (result != ISC_R_SUCCESS) {
06344                 dns_zone_log(zone, ISC_LOG_ERROR,
06345                              "zone_resigninc:update_soa_serial -> %s",
06346                              dns_result_totext(result));
06347                 goto failure;
06348         }
06349 
06350         /*
06351          * Generate maximum life time signatures so that the above loop
06352          * termination is sensible.
06353          */
06354         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
06355                           zonediff.diff, zone_keys, nkeys, zone->mctx,
06356                           inception, soaexpire, check_ksk, keyset_kskonly);
06357         if (result != ISC_R_SUCCESS) {
06358                 dns_zone_log(zone, ISC_LOG_ERROR,
06359                              "zone_resigninc:add_sigs -> %s",
06360                              dns_result_totext(result));
06361                 goto failure;
06362         }
06363 
06364         /* Write changes to journal file. */
06365         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
06366 
06367         /* Everything has succeeded. Commit the changes. */
06368         dns_db_closeversion(db, &version, ISC_TRUE);
06369 
06370  failure:
06371         dns_diff_clear(&_sig_diff);
06372         for (i = 0; i < nkeys; i++)
06373                 dst_key_free(&zone_keys[i]);
06374         if (version != NULL) {
06375                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
06376                 dns_db_detach(&db);
06377         } else if (db != NULL)
06378                 dns_db_detach(&db);
06379         if (result == ISC_R_SUCCESS) {
06380                 set_resigntime(zone);
06381                 LOCK_ZONE(zone);
06382                 zone_needdump(zone, DNS_DUMP_DELAY);
06383                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
06384                 UNLOCK_ZONE(zone);
06385         } else {
06386                 /*
06387                  * Something failed.  Retry in 5 minutes.
06388                  */
06389                 isc_interval_t ival;
06390                 isc_interval_set(&ival, 300, 0);
06391                 isc_time_nowplusinterval(&zone->resigntime, &ival);
06392         }
06393 
06394         INSIST(version == NULL);
06395 }
06396 
06397 static isc_result_t
06398 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
06399             dns_name_t *newname, isc_boolean_t bottom)
06400 {
06401         isc_result_t result;
06402         dns_dbiterator_t *dbit = NULL;
06403         dns_rdatasetiter_t *rdsit = NULL;
06404         dns_dbnode_t *node = NULL;
06405 
06406         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
06407         CHECK(dns_dbiterator_seek(dbit, oldname));
06408         do {
06409                 result = dns_dbiterator_next(dbit);
06410                 if (result == ISC_R_NOMORE)
06411                         CHECK(dns_dbiterator_first(dbit));
06412                 CHECK(dns_dbiterator_current(dbit, &node, newname));
06413                 if (bottom && dns_name_issubdomain(newname, oldname) &&
06414                     !dns_name_equal(newname, oldname)) {
06415                         dns_db_detachnode(db, &node);
06416                         continue;
06417                 }
06418                 /*
06419                  * Is this node empty?
06420                  */
06421                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
06422                 result = dns_rdatasetiter_first(rdsit);
06423                 dns_db_detachnode(db, &node);
06424                 dns_rdatasetiter_destroy(&rdsit);
06425                 if (result != ISC_R_NOMORE)
06426                         break;
06427         } while (1);
06428  failure:
06429         if (node != NULL)
06430                 dns_db_detachnode(db, &node);
06431         if (dbit != NULL)
06432                 dns_dbiterator_destroy(&dbit);
06433         return (result);
06434 }
06435 
06436 static isc_boolean_t
06437 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
06438                 dns_rdatatype_t type, dst_key_t *key)
06439 {
06440         isc_result_t result;
06441         dns_rdataset_t rdataset;
06442         dns_rdata_t rdata = DNS_RDATA_INIT;
06443         dns_rdata_rrsig_t rrsig;
06444 
06445         dns_rdataset_init(&rdataset);
06446         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
06447                                      type, 0, &rdataset, NULL);
06448         if (result != ISC_R_SUCCESS) {
06449                 INSIST(!dns_rdataset_isassociated(&rdataset));
06450                 return (ISC_FALSE);
06451         }
06452         for (result = dns_rdataset_first(&rdataset);
06453              result == ISC_R_SUCCESS;
06454              result = dns_rdataset_next(&rdataset)) {
06455                 dns_rdataset_current(&rdataset, &rdata);
06456                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
06457                 INSIST(result == ISC_R_SUCCESS);
06458                 if (rrsig.algorithm == dst_key_alg(key) &&
06459                     rrsig.keyid == dst_key_id(key)) {
06460                         dns_rdataset_disassociate(&rdataset);
06461                         return (ISC_TRUE);
06462                 }
06463                 dns_rdata_reset(&rdata);
06464         }
06465         dns_rdataset_disassociate(&rdataset);
06466         return (ISC_FALSE);
06467 }
06468 
06469 static isc_result_t
06470 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
06471          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
06472          dns_diff_t *diff)
06473 {
06474         dns_fixedname_t fixed;
06475         dns_name_t *next;
06476         dns_rdata_t rdata = DNS_RDATA_INIT;
06477         isc_result_t result;
06478         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
06479 
06480         dns_fixedname_init(&fixed);
06481         next = dns_fixedname_name(&fixed);
06482 
06483         CHECK(next_active(db, version, name, next, bottom));
06484         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
06485                                   &rdata));
06486         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
06487                             &rdata));
06488  failure:
06489         return (result);
06490 }
06491 
06492 static isc_result_t
06493 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
06494             dns_dbversion_t *version, isc_boolean_t build_nsec3,
06495             isc_boolean_t build_nsec, dst_key_t *key,
06496             isc_stdtime_t inception, isc_stdtime_t expire,
06497             unsigned int minimum, isc_boolean_t is_ksk,
06498             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
06499             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
06500 {
06501         isc_result_t result;
06502         dns_rdatasetiter_t *iterator = NULL;
06503         dns_rdataset_t rdataset;
06504         dns_rdata_t rdata = DNS_RDATA_INIT;
06505         isc_buffer_t buffer;
06506         unsigned char data[1024];
06507         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
06508                       seen_nsec3, seen_ds;
06509         isc_boolean_t bottom;
06510 
06511         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
06512         if (result != ISC_R_SUCCESS) {
06513                 if (result == ISC_R_NOTFOUND)
06514                         result = ISC_R_SUCCESS;
06515                 return (result);
06516         }
06517 
06518         dns_rdataset_init(&rdataset);
06519         isc_buffer_init(&buffer, data, sizeof(data));
06520         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
06521         seen_nsec3 = seen_ds = ISC_FALSE;
06522         for (result = dns_rdatasetiter_first(iterator);
06523              result == ISC_R_SUCCESS;
06524              result = dns_rdatasetiter_next(iterator)) {
06525                 dns_rdatasetiter_current(iterator, &rdataset);
06526                 if (rdataset.type == dns_rdatatype_soa)
06527                         seen_soa = ISC_TRUE;
06528                 else if (rdataset.type == dns_rdatatype_ns)
06529                         seen_ns = ISC_TRUE;
06530                 else if (rdataset.type == dns_rdatatype_ds)
06531                         seen_ds = ISC_TRUE;
06532                 else if (rdataset.type == dns_rdatatype_dname)
06533                         seen_dname = ISC_TRUE;
06534                 else if (rdataset.type == dns_rdatatype_nsec)
06535                         seen_nsec = ISC_TRUE;
06536                 else if (rdataset.type == dns_rdatatype_nsec3)
06537                         seen_nsec3 = ISC_TRUE;
06538                 if (rdataset.type != dns_rdatatype_rrsig)
06539                         seen_rr = ISC_TRUE;
06540                 dns_rdataset_disassociate(&rdataset);
06541         }
06542         if (result != ISC_R_NOMORE)
06543                 goto failure;
06544         if (seen_ns && !seen_soa)
06545                 *delegation = ISC_TRUE;
06546         /*
06547          * Going from insecure to NSEC3.
06548          * Don't generate NSEC3 records for NSEC3 records.
06549          */
06550         if (build_nsec3 && !seen_nsec3 && seen_rr) {
06551                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
06552                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
06553                                           unsecure, diff));
06554                 (*signatures)--;
06555         }
06556         /*
06557          * Going from insecure to NSEC.
06558          * Don't generate NSEC records for NSEC3 records.
06559          */
06560         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
06561                 /* Build and add NSEC. */
06562                 bottom = (seen_ns && !seen_soa) || seen_dname;
06563                 /*
06564                  * Build a NSEC record except at the origin.
06565                  */
06566                 if (!dns_name_equal(name, dns_db_origin(db))) {
06567                         CHECK(add_nsec(db, version, name, node, minimum,
06568                                        bottom, diff));
06569                         /* Count a NSEC generation as a signature generation. */
06570                         (*signatures)--;
06571                 }
06572         }
06573         result = dns_rdatasetiter_first(iterator);
06574         while (result == ISC_R_SUCCESS) {
06575                 dns_rdatasetiter_current(iterator, &rdataset);
06576                 if (rdataset.type == dns_rdatatype_soa ||
06577                     rdataset.type == dns_rdatatype_rrsig)
06578                         goto next_rdataset;
06579                 if (rdataset.type == dns_rdatatype_dnskey) {
06580                         if (!is_ksk && keyset_kskonly)
06581                                 goto next_rdataset;
06582                 } else if (is_ksk)
06583                         goto next_rdataset;
06584                 if (*delegation &&
06585                     rdataset.type != dns_rdatatype_ds &&
06586                     rdataset.type != dns_rdatatype_nsec)
06587                         goto next_rdataset;
06588                 if (signed_with_key(db, node, version, rdataset.type, key))
06589                         goto next_rdataset;
06590                 /* Calculate the signature, creating a RRSIG RDATA. */
06591                 isc_buffer_clear(&buffer);
06592                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
06593                                       &expire, mctx, &buffer, &rdata));
06594                 /* Update the database and journal with the RRSIG. */
06595                 /* XXX inefficient - will cause dataset merging */
06596                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
06597                                     name, rdataset.ttl, &rdata));
06598                 dns_rdata_reset(&rdata);
06599                 (*signatures)--;
06600  next_rdataset:
06601                 dns_rdataset_disassociate(&rdataset);
06602                 result = dns_rdatasetiter_next(iterator);
06603         }
06604         if (result == ISC_R_NOMORE)
06605                 result = ISC_R_SUCCESS;
06606         if (seen_dname)
06607                 *delegation = ISC_TRUE;
06608  failure:
06609         if (dns_rdataset_isassociated(&rdataset))
06610                 dns_rdataset_disassociate(&rdataset);
06611         if (iterator != NULL)
06612                 dns_rdatasetiter_destroy(&iterator);
06613         return (result);
06614 }
06615 
06616 /*
06617  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
06618  */
06619 static isc_result_t
06620 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
06621              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
06622 {
06623         isc_result_t result;
06624         dns_rdataset_t rdataset;
06625         dns_dbnode_t *node = NULL;
06626 
06627         CHECK(dns_db_getoriginnode(db, &node));
06628         if (update_only) {
06629                 dns_rdataset_init(&rdataset);
06630                 result = dns_db_findrdataset(db, node, version,
06631                                              dns_rdatatype_nsec,
06632                                              dns_rdatatype_none,
06633                                              0, &rdataset, NULL);
06634                 if (dns_rdataset_isassociated(&rdataset))
06635                         dns_rdataset_disassociate(&rdataset);
06636                 if (result == ISC_R_NOTFOUND)
06637                         goto success;
06638                 if (result != ISC_R_SUCCESS)
06639                         goto failure;
06640         }
06641         CHECK(delete_nsec(db, version, node, name, diff));
06642         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
06643  success:
06644         result = ISC_R_SUCCESS;
06645  failure:
06646         if (node != NULL)
06647                 dns_db_detachnode(db, &node);
06648         return (result);
06649 }
06650 
06651 static isc_result_t
06652 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
06653                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
06654                   dns_ttl_t minimum, dns_diff_t *diff)
06655 {
06656         isc_result_t result;
06657         dns_dbnode_t *node = NULL;
06658         dns_rdataset_t rdataset;
06659         dns_rdata_t rdata = DNS_RDATA_INIT;
06660         unsigned char data[5];
06661         isc_boolean_t seen_done = ISC_FALSE;
06662         isc_boolean_t have_rr = ISC_FALSE;
06663 
06664         dns_rdataset_init(&rdataset);
06665         result = dns_db_getoriginnode(signing->db, &node);
06666         if (result != ISC_R_SUCCESS)
06667                 goto failure;
06668 
06669         result = dns_db_findrdataset(signing->db, node, version,
06670                                      zone->privatetype, dns_rdatatype_none,
06671                                      0, &rdataset, NULL);
06672         if (result == ISC_R_NOTFOUND) {
06673                 INSIST(!dns_rdataset_isassociated(&rdataset));
06674                 result = ISC_R_SUCCESS;
06675                 goto failure;
06676         }
06677         if (result != ISC_R_SUCCESS) {
06678                 INSIST(!dns_rdataset_isassociated(&rdataset));
06679                 goto failure;
06680         }
06681         for (result = dns_rdataset_first(&rdataset);
06682              result == ISC_R_SUCCESS;
06683              result = dns_rdataset_next(&rdataset)) {
06684                 dns_rdataset_current(&rdataset, &rdata);
06685                 /*
06686                  * If we don't match the algorithm or keyid skip the record.
06687                  */
06688                 if (rdata.length != 5 ||
06689                     rdata.data[0] != signing->algorithm ||
06690                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
06691                     rdata.data[2] != (signing->keyid & 0xff)) {
06692                         have_rr = ISC_TRUE;
06693                         dns_rdata_reset(&rdata);
06694                         continue;
06695                 }
06696                 /*
06697                  * We have a match.  If we were signing (!signing->delete)
06698                  * and we already have a record indicating that we have
06699                  * finished signing (rdata.data[4] != 0) then keep it.
06700                  * Otherwise it needs to be deleted as we have removed all
06701                  * the signatures (signing->delete), so any record indicating
06702                  * completion is now out of date, or we have finished signing
06703                  * with the new record so we no longer need to remember that
06704                  * we need to sign the zone with the matching key across a
06705                  * nameserver re-start.
06706                  */
06707                 if (!signing->delete && rdata.data[4] != 0) {
06708                         seen_done = ISC_TRUE;
06709                         have_rr = ISC_TRUE;
06710                 } else
06711                         CHECK(update_one_rr(signing->db, version, diff,
06712                                             DNS_DIFFOP_DEL, &zone->origin,
06713                                             rdataset.ttl, &rdata));
06714                 dns_rdata_reset(&rdata);
06715         }
06716         if (result == ISC_R_NOMORE)
06717                 result = ISC_R_SUCCESS;
06718         if (!signing->delete && !seen_done) {
06719                 /*
06720                  * If we were signing then we need to indicate that we have
06721                  * finished signing the zone with this key.  If it is already
06722                  * there we don't need to add it a second time.
06723                  */
06724                 data[0] = signing->algorithm;
06725                 data[1] = (signing->keyid >> 8) & 0xff;
06726                 data[2] = signing->keyid & 0xff;
06727                 data[3] = 0;
06728                 data[4] = 1;
06729                 rdata.length = sizeof(data);
06730                 rdata.data = data;
06731                 rdata.type = zone->privatetype;
06732                 rdata.rdclass = dns_db_class(signing->db);
06733                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
06734                                     &zone->origin, rdataset.ttl, &rdata));
06735         } else if (!have_rr) {
06736                 dns_name_t *origin = dns_db_origin(signing->db);
06737                 /*
06738                  * Rebuild the NSEC/NSEC3 record for the origin as we no
06739                  * longer have any private records.
06740                  */
06741                 if (build_nsec3)
06742                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
06743                                                   minimum, ISC_FALSE, diff));
06744                 CHECK(updatesecure(signing->db, version, origin, minimum,
06745                                    ISC_TRUE, diff));
06746         }
06747 
06748  failure:
06749         if (dns_rdataset_isassociated(&rdataset))
06750                 dns_rdataset_disassociate(&rdataset);
06751         if (node != NULL)
06752                 dns_db_detachnode(signing->db, &node);
06753         return (result);
06754 }
06755 
06756 /*
06757  * If 'active' is set then we are not done with the chain yet so only
06758  * delete the nsec3param record which indicates a full chain exists
06759  * (flags == 0).
06760  */
06761 static isc_result_t
06762 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
06763                  isc_boolean_t active, dns_rdatatype_t privatetype,
06764                  dns_diff_t *diff)
06765 {
06766         dns_dbnode_t *node = NULL;
06767         dns_name_t *name = dns_db_origin(db);
06768         dns_rdata_t rdata = DNS_RDATA_INIT;
06769         dns_rdataset_t rdataset;
06770         dns_rdata_nsec3param_t nsec3param;
06771         isc_result_t result;
06772         isc_buffer_t buffer;
06773         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
06774         dns_ttl_t ttl = 0;
06775         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
06776 
06777         dns_rdataset_init(&rdataset);
06778 
06779         result = dns_db_getoriginnode(db, &node);
06780         RUNTIME_CHECK(result == ISC_R_SUCCESS);
06781         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
06782                                      0, 0, &rdataset, NULL);
06783         if (result == ISC_R_NOTFOUND)
06784                 goto try_private;
06785         if (result != ISC_R_SUCCESS)
06786                 goto failure;
06787 
06788         /*
06789          * Preserve the existing ttl.
06790          */
06791         ttl = rdataset.ttl;
06792 
06793         /*
06794          * Delete all NSEC3PARAM records which match that in nsec3chain.
06795          */
06796         for (result = dns_rdataset_first(&rdataset);
06797              result == ISC_R_SUCCESS;
06798              result = dns_rdataset_next(&rdataset)) {
06799 
06800                 dns_rdataset_current(&rdataset, &rdata);
06801                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
06802 
06803                 if (nsec3param.hash != chain->nsec3param.hash ||
06804                     (active && nsec3param.flags != 0) ||
06805                     nsec3param.iterations != chain->nsec3param.iterations ||
06806                     nsec3param.salt_length != chain->nsec3param.salt_length ||
06807                     memcmp(nsec3param.salt, chain->nsec3param.salt,
06808                            nsec3param.salt_length)) {
06809                         dns_rdata_reset(&rdata);
06810                         continue;
06811                 }
06812 
06813                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
06814                                     name, rdataset.ttl, &rdata));
06815                 dns_rdata_reset(&rdata);
06816         }
06817         if (result != ISC_R_NOMORE)
06818                 goto failure;
06819 
06820         dns_rdataset_disassociate(&rdataset);
06821 
06822  try_private:
06823 
06824         if (active)
06825                 goto add;
06826 
06827         result = dns_nsec_nseconly(db, ver, &nseconly);
06828         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
06829 
06830         /*
06831          * Delete all private records which match that in nsec3chain.
06832          */
06833         result = dns_db_findrdataset(db, node, ver, privatetype,
06834                                      0, 0, &rdataset, NULL);
06835         if (result == ISC_R_NOTFOUND)
06836                 goto add;
06837         if (result != ISC_R_SUCCESS)
06838                 goto failure;
06839 
06840         for (result = dns_rdataset_first(&rdataset);
06841              result == ISC_R_SUCCESS;
06842              result = dns_rdataset_next(&rdataset)) {
06843                 dns_rdata_t private = DNS_RDATA_INIT;
06844                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
06845 
06846                 dns_rdataset_current(&rdataset, &private);
06847                 if (!dns_nsec3param_fromprivate(&private, &rdata,
06848                                                 buf, sizeof(buf)))
06849                         continue;
06850                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
06851 
06852                 if ((!nsec3ok &&
06853                      (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
06854                     nsec3param.hash != chain->nsec3param.hash ||
06855                     nsec3param.iterations != chain->nsec3param.iterations ||
06856                     nsec3param.salt_length != chain->nsec3param.salt_length ||
06857                     memcmp(nsec3param.salt, chain->nsec3param.salt,
06858                            nsec3param.salt_length)) {
06859                         dns_rdata_reset(&rdata);
06860                         continue;
06861                 }
06862 
06863                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
06864                                     name, rdataset.ttl, &private));
06865                 dns_rdata_reset(&rdata);
06866         }
06867         if (result != ISC_R_NOMORE)
06868                 goto failure;
06869 
06870   add:
06871         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
06872                 result = ISC_R_SUCCESS;
06873                 goto failure;
06874         }
06875 
06876         /*
06877          * Add a NSEC3PARAM record which matches that in nsec3chain but
06878          * with all flags bits cleared.
06879          *
06880          * Note: we do not clear chain->nsec3param.flags as this change
06881          * may be reversed.
06882          */
06883         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
06884         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
06885                                    dns_rdatatype_nsec3param,
06886                                    &chain->nsec3param, &buffer));
06887         rdata.data[1] = 0;      /* Clear flag bits. */
06888         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
06889 
06890   failure:
06891         dns_db_detachnode(db, &node);
06892         if (dns_rdataset_isassociated(&rdataset))
06893                 dns_rdataset_disassociate(&rdataset);
06894         return (result);
06895 }
06896 
06897 static isc_result_t
06898 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
06899             dns_name_t *name, dns_diff_t *diff)
06900 {
06901         dns_rdataset_t rdataset;
06902         isc_result_t result;
06903 
06904         dns_rdataset_init(&rdataset);
06905 
06906         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
06907                                      0, 0, &rdataset, NULL);
06908         if (result == ISC_R_NOTFOUND)
06909                 return (ISC_R_SUCCESS);
06910         if (result != ISC_R_SUCCESS)
06911                 return (result);
06912         for (result = dns_rdataset_first(&rdataset);
06913              result == ISC_R_SUCCESS;
06914              result = dns_rdataset_next(&rdataset)) {
06915                 dns_rdata_t rdata = DNS_RDATA_INIT;
06916 
06917                 dns_rdataset_current(&rdataset, &rdata);
06918                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
06919                                     rdataset.ttl, &rdata));
06920         }
06921         if (result == ISC_R_NOMORE)
06922                 result = ISC_R_SUCCESS;
06923  failure:
06924         dns_rdataset_disassociate(&rdataset);
06925         return (result);
06926 }
06927 
06928 static isc_result_t
06929 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
06930                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
06931                     dns_diff_t *diff)
06932 {
06933         dns_rdataset_t rdataset;
06934         dns_rdata_nsec3_t nsec3;
06935         isc_result_t result;
06936 
06937         dns_rdataset_init(&rdataset);
06938         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
06939                                      0, 0, &rdataset, NULL);
06940         if (result == ISC_R_NOTFOUND)
06941                 return (ISC_R_SUCCESS);
06942         if (result != ISC_R_SUCCESS)
06943                 return (result);
06944 
06945         for (result = dns_rdataset_first(&rdataset);
06946              result == ISC_R_SUCCESS;
06947              result = dns_rdataset_next(&rdataset)) {
06948                 dns_rdata_t rdata = DNS_RDATA_INIT;
06949 
06950                 dns_rdataset_current(&rdataset, &rdata);
06951                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
06952                 if (nsec3.hash != param->hash ||
06953                     nsec3.iterations != param->iterations ||
06954                     nsec3.salt_length != param->salt_length ||
06955                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
06956                         continue;
06957                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
06958                                     rdataset.ttl, &rdata));
06959         }
06960         if (result == ISC_R_NOMORE)
06961                 result = ISC_R_SUCCESS;
06962  failure:
06963         dns_rdataset_disassociate(&rdataset);
06964         return (result);
06965 }
06966 
06967 static isc_result_t
06968 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
06969                 const dns_rdata_nsec3param_t *param,
06970                 isc_boolean_t *answer)
06971 {
06972         dns_dbnode_t *node = NULL;
06973         dns_rdata_t rdata = DNS_RDATA_INIT;
06974         dns_rdata_nsec3param_t myparam;
06975         dns_rdataset_t rdataset;
06976         isc_result_t result;
06977 
06978         *answer = ISC_FALSE;
06979 
06980         result = dns_db_getoriginnode(db, &node);
06981         RUNTIME_CHECK(result == ISC_R_SUCCESS);
06982 
06983         dns_rdataset_init(&rdataset);
06984 
06985         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
06986                                      0, 0, &rdataset, NULL);
06987         if (result == ISC_R_SUCCESS) {
06988                 dns_rdataset_disassociate(&rdataset);
06989                 dns_db_detachnode(db, &node);
06990                 return (result);
06991         }
06992         if (result != ISC_R_NOTFOUND) {
06993                 dns_db_detachnode(db, &node);
06994                 return (result);
06995         }
06996 
06997         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
06998                                      0, 0, &rdataset, NULL);
06999         if (result == ISC_R_NOTFOUND) {
07000                 *answer = ISC_TRUE;
07001