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                 dns_db_detachnode(db, &node);
07002                 return (ISC_R_SUCCESS);
07003         }
07004         if (result != ISC_R_SUCCESS) {
07005                 dns_db_detachnode(db, &node);
07006                 return (result);
07007         }
07008 
07009         for (result = dns_rdataset_first(&rdataset);
07010              result == ISC_R_SUCCESS;
07011              result = dns_rdataset_next(&rdataset)) {
07012                 dns_rdataset_current(&rdataset, &rdata);
07013                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
07014                 dns_rdata_reset(&rdata);
07015                 /*
07016                  * Ignore any NSEC3PARAM removals.
07017                  */
07018                 if (NSEC3REMOVE(myparam.flags))
07019                         continue;
07020                 /*
07021                  * Ignore the chain that we are in the process of deleting.
07022                  */
07023                 if (myparam.hash == param->hash &&
07024                     myparam.iterations == param->iterations &&
07025                     myparam.salt_length == param->salt_length &&
07026                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
07027                         continue;
07028                 /*
07029                  * Found an active NSEC3 chain.
07030                  */
07031                 break;
07032         }
07033         if (result == ISC_R_NOMORE) {
07034                 *answer = ISC_TRUE;
07035                 result = ISC_R_SUCCESS;
07036         }
07037 
07038  failure:
07039         if (dns_rdataset_isassociated(&rdataset))
07040                 dns_rdataset_disassociate(&rdataset);
07041         dns_db_detachnode(db, &node);
07042         return (result);
07043 }
07044 
07045 static isc_result_t
07046 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
07047             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
07048             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
07049             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
07050             zonediff_t *zonediff)
07051 {
07052         dns_difftuple_t *tuple;
07053         isc_result_t result;
07054 
07055         for (tuple = ISC_LIST_HEAD(diff->tuples);
07056              tuple != NULL;
07057              tuple = ISC_LIST_HEAD(diff->tuples)) {
07058                 result = del_sigs(zone, db, version, &tuple->name,
07059                                   tuple->rdata.type, zonediff,
07060                                   zone_keys, nkeys, now, ISC_FALSE);
07061                 if (result != ISC_R_SUCCESS) {
07062                         dns_zone_log(zone, ISC_LOG_ERROR,
07063                                      "update_sigs:del_sigs -> %s",
07064                                      dns_result_totext(result));
07065                         return (result);
07066                 }
07067                 result = add_sigs(db, version, &tuple->name,
07068                                   tuple->rdata.type, zonediff->diff,
07069                                   zone_keys, nkeys, zone->mctx, inception,
07070                                   expire, check_ksk, keyset_kskonly);
07071                 if (result != ISC_R_SUCCESS) {
07072                         dns_zone_log(zone, ISC_LOG_ERROR,
07073                                      "update_sigs:add_sigs -> %s",
07074                                      dns_result_totext(result));
07075                         return (result);
07076                 }
07077 
07078                 do {
07079                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
07080                         while (next != NULL &&
07081                                (tuple->rdata.type != next->rdata.type ||
07082                                 !dns_name_equal(&tuple->name, &next->name)))
07083                                 next = ISC_LIST_NEXT(next, link);
07084                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
07085                         dns_diff_appendminimal(zonediff->diff, &tuple);
07086                         INSIST(tuple == NULL);
07087                         tuple = next;
07088                 } while (tuple != NULL);
07089         }
07090         return (ISC_R_SUCCESS);
07091 }
07092 
07093 /*
07094  * Incrementally build and sign a new NSEC3 chain using the parameters
07095  * requested.
07096  */
07097 static void
07098 zone_nsec3chain(dns_zone_t *zone) {
07099         const char *me = "zone_nsec3chain";
07100         dns_db_t *db = NULL;
07101         dns_dbnode_t *node = NULL;
07102         dns_dbversion_t *version = NULL;
07103         dns_diff_t _sig_diff;
07104         dns_diff_t nsec_diff;
07105         dns_diff_t nsec3_diff;
07106         dns_diff_t param_diff;
07107         zonediff_t zonediff;
07108         dns_fixedname_t fixed;
07109         dns_fixedname_t nextfixed;
07110         dns_name_t *name, *nextname;
07111         dns_rdataset_t rdataset;
07112         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
07113         dns_nsec3chainlist_t cleanup;
07114         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
07115         isc_int32_t signatures;
07116         isc_boolean_t check_ksk, keyset_kskonly;
07117         isc_boolean_t delegation;
07118         isc_boolean_t first;
07119         isc_result_t result;
07120         isc_stdtime_t now, inception, soaexpire, expire;
07121         isc_uint32_t jitter;
07122         unsigned int i;
07123         unsigned int nkeys = 0;
07124         isc_uint32_t nodes;
07125         isc_boolean_t unsecure = ISC_FALSE;
07126         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
07127         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
07128         dns_rdatasetiter_t *iterator = NULL;
07129         isc_boolean_t buildnsecchain;
07130         isc_boolean_t updatensec = ISC_FALSE;
07131         dns_rdatatype_t privatetype = zone->privatetype;
07132 
07133         ENTER;
07134 
07135         dns_rdataset_init(&rdataset);
07136         dns_fixedname_init(&fixed);
07137         name = dns_fixedname_name(&fixed);
07138         dns_fixedname_init(&nextfixed);
07139         nextname = dns_fixedname_name(&nextfixed);
07140         dns_diff_init(zone->mctx, &param_diff);
07141         dns_diff_init(zone->mctx, &nsec3_diff);
07142         dns_diff_init(zone->mctx, &nsec_diff);
07143         dns_diff_init(zone->mctx, &_sig_diff);
07144         zonediff_init(&zonediff, &_sig_diff);
07145         ISC_LIST_INIT(cleanup);
07146 
07147         /*
07148          * Updates are disabled.  Pause for 5 minutes.
07149          */
07150         if (zone->update_disabled) {
07151                 result = ISC_R_FAILURE;
07152                 goto failure;
07153         }
07154 
07155         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
07156         dns_db_attach(zone->db, &db);
07157         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
07158 
07159         result = dns_db_newversion(db, &version);
07160         if (result != ISC_R_SUCCESS) {
07161                 dns_zone_log(zone, ISC_LOG_ERROR,
07162                              "zone_nsec3chain:dns_db_newversion -> %s",
07163                              dns_result_totext(result));
07164                 goto failure;
07165         }
07166 
07167         result = find_zone_keys(zone, db, version, zone->mctx,
07168                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
07169         if (result != ISC_R_SUCCESS) {
07170                 dns_zone_log(zone, ISC_LOG_ERROR,
07171                              "zone_nsec3chain:find_zone_keys -> %s",
07172                              dns_result_totext(result));
07173                 goto failure;
07174         }
07175 
07176         isc_stdtime_get(&now);
07177         inception = now - 3600; /* Allow for clock skew. */
07178         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
07179 
07180         /*
07181          * Spread out signatures over time if they happen to be
07182          * clumped.  We don't do this for each add_sigs() call as
07183          * we still want some clustering to occur.
07184          */
07185         isc_random_get(&jitter);
07186         expire = soaexpire - jitter % 3600;
07187 
07188         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
07189         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
07190 
07191         /*
07192          * We keep pulling nodes off each iterator in turn until
07193          * we have no more nodes to pull off or we reach the limits
07194          * for this quantum.
07195          */
07196         nodes = zone->nodes;
07197         signatures = zone->signatures;
07198         LOCK_ZONE(zone);
07199         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
07200         UNLOCK_ZONE(zone);
07201         first = ISC_TRUE;
07202 
07203         if (nsec3chain != NULL)
07204                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
07205         /*
07206          * Generate new NSEC3 chains first.
07207          */
07208         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
07209                 LOCK_ZONE(zone);
07210                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
07211 
07212                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
07213                 if (nsec3chain->done || nsec3chain->db != zone->db) {
07214                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
07215                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
07216                 }
07217                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
07218                 UNLOCK_ZONE(zone);
07219                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
07220                         goto next_addchain;
07221 
07222                 /*
07223                  * Possible future db.
07224                  */
07225                 if (nsec3chain->db != db) {
07226                         goto next_addchain;
07227                 }
07228 
07229                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
07230                         goto next_addchain;
07231 
07232                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
07233 
07234                 if (nsec3chain->delete_nsec) {
07235                         delegation = ISC_FALSE;
07236                         dns_dbiterator_pause(nsec3chain->dbiterator);
07237                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
07238                         goto next_addnode;
07239                 }
07240                 /*
07241                  * On the first pass we need to check if the current node
07242                  * has not been obscured.
07243                  */
07244                 delegation = ISC_FALSE;
07245                 unsecure = ISC_FALSE;
07246                 if (first) {
07247                         dns_fixedname_t ffound;
07248                         dns_name_t *found;
07249                         dns_fixedname_init(&ffound);
07250                         found = dns_fixedname_name(&ffound);
07251                         result = dns_db_find(db, name, version,
07252                                              dns_rdatatype_soa,
07253                                              DNS_DBFIND_NOWILD, 0, NULL, found,
07254                                              NULL, NULL);
07255                         if ((result == DNS_R_DELEGATION ||
07256                             result == DNS_R_DNAME) &&
07257                             !dns_name_equal(name, found)) {
07258                                 /*
07259                                  * Remember the obscuring name so that
07260                                  * we skip all obscured names.
07261                                  */
07262                                 dns_name_copy(found, name, NULL);
07263                                 delegation = ISC_TRUE;
07264                                 goto next_addnode;
07265                         }
07266                 }
07267 
07268                 /*
07269                  * Check to see if this is a bottom of zone node.
07270                  */
07271                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
07272                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
07273                         goto next_addnode;
07274                 if (result != ISC_R_SUCCESS)
07275                         goto failure;
07276 
07277                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
07278                         ISC_FALSE;
07279                 for (result = dns_rdatasetiter_first(iterator);
07280                      result == ISC_R_SUCCESS;
07281                      result = dns_rdatasetiter_next(iterator)) {
07282                         dns_rdatasetiter_current(iterator, &rdataset);
07283                         INSIST(rdataset.type != dns_rdatatype_nsec3);
07284                         if (rdataset.type == dns_rdatatype_soa)
07285                                 seen_soa = ISC_TRUE;
07286                         else if (rdataset.type == dns_rdatatype_ns)
07287                                 seen_ns = ISC_TRUE;
07288                         else if (rdataset.type == dns_rdatatype_dname)
07289                                 seen_dname = ISC_TRUE;
07290                         else if (rdataset.type == dns_rdatatype_ds)
07291                                 seen_ds = ISC_TRUE;
07292                         else if (rdataset.type == dns_rdatatype_nsec)
07293                                 seen_nsec = ISC_TRUE;
07294                         dns_rdataset_disassociate(&rdataset);
07295                 }
07296                 dns_rdatasetiter_destroy(&iterator);
07297                 /*
07298                  * Is there a NSEC chain than needs to be cleaned up?
07299                  */
07300                 if (seen_nsec)
07301                         nsec3chain->seen_nsec = ISC_TRUE;
07302                 if (seen_ns && !seen_soa && !seen_ds)
07303                         unsecure = ISC_TRUE;
07304                 if ((seen_ns && !seen_soa) || seen_dname)
07305                         delegation = ISC_TRUE;
07306 
07307                 /*
07308                  * Process one node.
07309                  */
07310                 dns_dbiterator_pause(nsec3chain->dbiterator);
07311                 result = dns_nsec3_addnsec3(db, version, name,
07312                                             &nsec3chain->nsec3param,
07313                                             zone->minimum, unsecure,
07314                                             &nsec3_diff);
07315                 if (result != ISC_R_SUCCESS) {
07316                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07317                                      "dns_nsec3_addnsec3 -> %s",
07318                                      dns_result_totext(result));
07319                         goto failure;
07320                 }
07321 
07322                 /*
07323                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
07324                  * two signatures.  Additionally there will, in general, be
07325                  * two signature generated below.
07326                  *
07327                  * If we are only changing the optout flag the cost is half
07328                  * that of the cost of generating a completely new chain.
07329                  */
07330                 signatures -= 4;
07331 
07332                 /*
07333                  * Go onto next node.
07334                  */
07335  next_addnode:
07336                 first = ISC_FALSE;
07337                 dns_db_detachnode(db, &node);
07338                 do {
07339                         result = dns_dbiterator_next(nsec3chain->dbiterator);
07340 
07341                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
07342                                 dns_dbiterator_pause(nsec3chain->dbiterator);
07343                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
07344                                                        ISC_FALSE, privatetype,
07345                                                        &param_diff));
07346                                 LOCK_ZONE(zone);
07347                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
07348                                                 link);
07349                                 UNLOCK_ZONE(zone);
07350                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
07351                                 goto next_addchain;
07352                         }
07353                         if (result == ISC_R_NOMORE) {
07354                                 dns_dbiterator_pause(nsec3chain->dbiterator);
07355                                 if (nsec3chain->seen_nsec) {
07356                                         CHECK(fixup_nsec3param(db, version,
07357                                                                nsec3chain,
07358                                                                ISC_TRUE,
07359                                                                privatetype,
07360                                                                &param_diff));
07361                                         nsec3chain->delete_nsec = ISC_TRUE;
07362                                         goto same_addchain;
07363                                 }
07364                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
07365                                                        ISC_FALSE, privatetype,
07366                                                        &param_diff));
07367                                 LOCK_ZONE(zone);
07368                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
07369                                                 link);
07370                                 UNLOCK_ZONE(zone);
07371                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
07372                                 goto next_addchain;
07373                         } else if (result != ISC_R_SUCCESS) {
07374                                 dns_zone_log(zone, ISC_LOG_ERROR,
07375                                              "zone_nsec3chain:"
07376                                              "dns_dbiterator_next -> %s",
07377                                              dns_result_totext(result));
07378                                 goto failure;
07379                         } else if (delegation) {
07380                                 dns_dbiterator_current(nsec3chain->dbiterator,
07381                                                        &node, nextname);
07382                                 dns_db_detachnode(db, &node);
07383                                 if (!dns_name_issubdomain(nextname, name))
07384                                         break;
07385                         } else
07386                                 break;
07387                 } while (1);
07388                 continue;
07389 
07390  same_addchain:
07391                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
07392                 first = ISC_TRUE;
07393                 continue;
07394 
07395  next_addchain:
07396                 dns_dbiterator_pause(nsec3chain->dbiterator);
07397                 nsec3chain = nextnsec3chain;
07398                 first = ISC_TRUE;
07399                 if (nsec3chain != NULL)
07400                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
07401         }
07402 
07403         /*
07404          * Process removals.
07405          */
07406         LOCK_ZONE(zone);
07407         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
07408         UNLOCK_ZONE(zone);
07409         first = ISC_TRUE;
07410         buildnsecchain = ISC_FALSE;
07411         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
07412                 LOCK_ZONE(zone);
07413                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
07414                 UNLOCK_ZONE(zone);
07415 
07416                 if (nsec3chain->db != db)
07417                         goto next_removechain;
07418 
07419                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
07420                         goto next_removechain;
07421 
07422                 /*
07423                  * Work out if we need to build a NSEC chain as a consequence
07424                  * of removing this NSEC3 chain.
07425                  */
07426                 if (first && !updatensec &&
07427                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
07428                 {
07429                         result = need_nsec_chain(db, version,
07430                                                  &nsec3chain->nsec3param,
07431                                                  &buildnsecchain);
07432                         if (result != ISC_R_SUCCESS) {
07433                                 dns_zone_log(zone, ISC_LOG_ERROR,
07434                                              "zone_nsec3chain:"
07435                                              "need_nsec_chain -> %s",
07436                                              dns_result_totext(result));
07437                                 goto failure;
07438                         }
07439                 }
07440 
07441                 if (first)
07442                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
07443                                      "buildnsecchain = %u\n", buildnsecchain);
07444 
07445                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
07446                 delegation = ISC_FALSE;
07447 
07448                 if (!buildnsecchain) {
07449                         /*
07450                          * Delete the NSECPARAM record that matches this chain.
07451                          */
07452                         if (first) {
07453                                 result = fixup_nsec3param(db, version,
07454                                                           nsec3chain,
07455                                                           ISC_TRUE, privatetype,
07456                                                           &param_diff);
07457                                 if (result != ISC_R_SUCCESS) {
07458                                         dns_zone_log(zone, ISC_LOG_ERROR,
07459                                                      "zone_nsec3chain:"
07460                                                      "fixup_nsec3param -> %s",
07461                                                      dns_result_totext(result));
07462                                         goto failure;
07463                                 }
07464                         }
07465 
07466                         /*
07467                          *  Delete the NSEC3 records.
07468                          */
07469                         result = deletematchingnsec3(db, version, node, name,
07470                                                      &nsec3chain->nsec3param,
07471                                                      &nsec3_diff);
07472                         if (result != ISC_R_SUCCESS) {
07473                                 dns_zone_log(zone, ISC_LOG_ERROR,
07474                                              "zone_nsec3chain:"
07475                                              "deletematchingnsec3 -> %s",
07476                                              dns_result_totext(result));
07477                                 goto failure;
07478                         }
07479                         goto next_removenode;
07480                 }
07481 
07482                 if (first) {
07483                         dns_fixedname_t ffound;
07484                         dns_name_t *found;
07485                         dns_fixedname_init(&ffound);
07486                         found = dns_fixedname_name(&ffound);
07487                         result = dns_db_find(db, name, version,
07488                                              dns_rdatatype_soa,
07489                                              DNS_DBFIND_NOWILD, 0, NULL, found,
07490                                              NULL, NULL);
07491                         if ((result == DNS_R_DELEGATION ||
07492                              result == DNS_R_DNAME) &&
07493                             !dns_name_equal(name, found)) {
07494                                 /*
07495                                  * Remember the obscuring name so that
07496                                  * we skip all obscured names.
07497                                  */
07498                                 dns_name_copy(found, name, NULL);
07499                                 delegation = ISC_TRUE;
07500                                 goto next_removenode;
07501                         }
07502                 }
07503 
07504                 /*
07505                  * Check to see if this is a bottom of zone node.
07506                  */
07507                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
07508                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
07509                         goto next_removenode;
07510                 if (result != ISC_R_SUCCESS)
07511                         goto failure;
07512 
07513                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
07514                         seen_rr = ISC_FALSE;
07515                 for (result = dns_rdatasetiter_first(iterator);
07516                      result == ISC_R_SUCCESS;
07517                      result = dns_rdatasetiter_next(iterator)) {
07518                         dns_rdatasetiter_current(iterator, &rdataset);
07519                         if (rdataset.type == dns_rdatatype_soa)
07520                                 seen_soa = ISC_TRUE;
07521                         else if (rdataset.type == dns_rdatatype_ns)
07522                                 seen_ns = ISC_TRUE;
07523                         else if (rdataset.type == dns_rdatatype_dname)
07524                                 seen_dname = ISC_TRUE;
07525                         else if (rdataset.type == dns_rdatatype_nsec)
07526                                 seen_nsec = ISC_TRUE;
07527                         else if (rdataset.type == dns_rdatatype_nsec3)
07528                                 seen_nsec3 = ISC_TRUE;
07529                         if (rdataset.type != dns_rdatatype_rrsig)
07530                                 seen_rr = ISC_TRUE;
07531                         dns_rdataset_disassociate(&rdataset);
07532                 }
07533                 dns_rdatasetiter_destroy(&iterator);
07534 
07535                 if (!seen_rr || seen_nsec3 || seen_nsec)
07536                         goto next_removenode;
07537                 if ((seen_ns && !seen_soa) || seen_dname)
07538                         delegation = ISC_TRUE;
07539 
07540                 /*
07541                  * Add a NSEC record except at the origin.
07542                  */
07543                 if (!dns_name_equal(name, dns_db_origin(db))) {
07544                         dns_dbiterator_pause(nsec3chain->dbiterator);
07545                         CHECK(add_nsec(db, version, name, node, zone->minimum,
07546                                        delegation, &nsec_diff));
07547                 }
07548 
07549  next_removenode:
07550                 first = ISC_FALSE;
07551                 dns_db_detachnode(db, &node);
07552                 do {
07553                         result = dns_dbiterator_next(nsec3chain->dbiterator);
07554                         if (result == ISC_R_NOMORE && buildnsecchain) {
07555                                 /*
07556                                  * The NSEC chain should now be built.
07557                                  * We can now remove the NSEC3 chain.
07558                                  */
07559                                 updatensec = ISC_TRUE;
07560                                 goto same_removechain;
07561                         }
07562                         if (result == ISC_R_NOMORE) {
07563                                 LOCK_ZONE(zone);
07564                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
07565                                                 link);
07566                                 UNLOCK_ZONE(zone);
07567                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
07568                                 dns_dbiterator_pause(nsec3chain->dbiterator);
07569                                 result = fixup_nsec3param(db, version,
07570                                                           nsec3chain, ISC_FALSE,
07571                                                           privatetype,
07572                                                           &param_diff);
07573                                 if (result != ISC_R_SUCCESS) {
07574                                         dns_zone_log(zone, ISC_LOG_ERROR,
07575                                                      "zone_nsec3chain:"
07576                                                      "fixup_nsec3param -> %s",
07577                                                      dns_result_totext(result));
07578                                         goto failure;
07579                                 }
07580                                 goto next_removechain;
07581                         } else if (result != ISC_R_SUCCESS) {
07582                                 dns_zone_log(zone, ISC_LOG_ERROR,
07583                                              "zone_nsec3chain:"
07584                                              "dns_dbiterator_next -> %s",
07585                                              dns_result_totext(result));
07586                                 goto failure;
07587                         } else if (delegation) {
07588                                 dns_dbiterator_current(nsec3chain->dbiterator,
07589                                                        &node, nextname);
07590                                 dns_db_detachnode(db, &node);
07591                                 if (!dns_name_issubdomain(nextname, name))
07592                                         break;
07593                         } else
07594                                 break;
07595                 } while (1);
07596                 continue;
07597 
07598  same_removechain:
07599                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
07600                 buildnsecchain = ISC_FALSE;
07601                 first = ISC_TRUE;
07602                 continue;
07603 
07604  next_removechain:
07605                 dns_dbiterator_pause(nsec3chain->dbiterator);
07606                 nsec3chain = nextnsec3chain;
07607                 first = ISC_TRUE;
07608         }
07609 
07610         /*
07611          * We may need to update the NSEC/NSEC3 records for the zone apex.
07612          */
07613         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
07614                 isc_boolean_t rebuild_nsec = ISC_FALSE,
07615                               rebuild_nsec3 = ISC_FALSE;
07616                 result = dns_db_getoriginnode(db, &node);
07617                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
07618                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
07619                 if (result != ISC_R_SUCCESS) {
07620                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07621                                      "dns_db_allrdatasets -> %s",
07622                                      dns_result_totext(result));
07623                         goto failure;
07624                 }
07625                 for (result = dns_rdatasetiter_first(iterator);
07626                      result == ISC_R_SUCCESS;
07627                      result = dns_rdatasetiter_next(iterator)) {
07628                         dns_rdatasetiter_current(iterator, &rdataset);
07629                         if (rdataset.type == dns_rdatatype_nsec)
07630                                 rebuild_nsec = ISC_TRUE;
07631                         if (rdataset.type == dns_rdatatype_nsec3param)
07632                                 rebuild_nsec3 = ISC_TRUE;
07633                         dns_rdataset_disassociate(&rdataset);
07634                 }
07635                 dns_rdatasetiter_destroy(&iterator);
07636                 dns_db_detachnode(db, &node);
07637 
07638                 if (rebuild_nsec) {
07639                         if (nsec3chain != NULL)
07640                                 dns_dbiterator_pause(nsec3chain->dbiterator);
07641 
07642                         result = updatesecure(db, version, &zone->origin,
07643                                               zone->minimum, ISC_TRUE,
07644                                               &nsec_diff);
07645                         if (result != ISC_R_SUCCESS) {
07646                                 dns_zone_log(zone, ISC_LOG_ERROR,
07647                                              "zone_nsec3chain:"
07648                                              "updatesecure -> %s",
07649                                              dns_result_totext(result));
07650                                 goto failure;
07651                         }
07652                 }
07653 
07654                 if (rebuild_nsec3) {
07655                         if (nsec3chain != NULL)
07656                                 dns_dbiterator_pause(nsec3chain->dbiterator);
07657 
07658                         result = dns_nsec3_addnsec3s(db, version,
07659                                                      dns_db_origin(db),
07660                                                      zone->minimum, ISC_FALSE,
07661                                                      &nsec3_diff);
07662                         if (result != ISC_R_SUCCESS) {
07663                                 dns_zone_log(zone, ISC_LOG_ERROR,
07664                                              "zone_nsec3chain:"
07665                                              "dns_nsec3_addnsec3s -> %s",
07666                                              dns_result_totext(result));
07667                                 goto failure;
07668                         }
07669                 }
07670         }
07671 
07672         if (nsec3chain != NULL)
07673                 dns_dbiterator_pause(nsec3chain->dbiterator);
07674 
07675         /*
07676          * Add / update signatures for the NSEC3 records.
07677          */
07678         if (nsec3chain != NULL)
07679                 dns_dbiterator_pause(nsec3chain->dbiterator);
07680         result = update_sigs(&nsec3_diff, db, version, zone_keys,
07681                              nkeys, zone, inception, expire, now,
07682                              check_ksk, keyset_kskonly, &zonediff);
07683         if (result != ISC_R_SUCCESS) {
07684                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07685                              "update_sigs -> %s", dns_result_totext(result));
07686                 goto failure;
07687         }
07688 
07689         /*
07690          * We have changed the NSEC3PARAM or private RRsets
07691          * above so we need to update the signatures.
07692          */
07693         result = update_sigs(&param_diff, db, version, zone_keys,
07694                              nkeys, zone, inception, expire, now,
07695                              check_ksk, keyset_kskonly, &zonediff);
07696         if (result != ISC_R_SUCCESS) {
07697                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07698                              "update_sigs -> %s", dns_result_totext(result));
07699                 goto failure;
07700         }
07701 
07702         if (updatensec) {
07703                 result = updatesecure(db, version, &zone->origin,
07704                                       zone->minimum, ISC_FALSE, &nsec_diff);
07705                 if (result != ISC_R_SUCCESS) {
07706                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07707                                      "updatesecure -> %s",
07708                                      dns_result_totext(result));
07709                         goto failure;
07710                 }
07711         }
07712 
07713         result = update_sigs(&nsec_diff, db, version, zone_keys,
07714                              nkeys, zone, inception, expire, now,
07715                              check_ksk, keyset_kskonly, &zonediff);
07716         if (result != ISC_R_SUCCESS) {
07717                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07718                              "update_sigs -> %s", dns_result_totext(result));
07719                 goto failure;
07720         }
07721 
07722         /*
07723          * If we made no effective changes to the zone then we can just
07724          * cleanup otherwise we need to increment the serial.
07725          */
07726         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
07727                 /*
07728                  * No need to call dns_db_closeversion() here as it is
07729                  * called with commit = ISC_TRUE below.
07730                  */
07731                 goto done;
07732         }
07733 
07734         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
07735                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
07736         if (result != ISC_R_SUCCESS) {
07737                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07738                              "del_sigs -> %s", dns_result_totext(result));
07739                 goto failure;
07740         }
07741 
07742         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
07743                                    zone->updatemethod);
07744         if (result != ISC_R_SUCCESS) {
07745                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07746                              "update_soa_serial -> %s",
07747                              dns_result_totext(result));
07748                 goto failure;
07749         }
07750 
07751         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
07752                           zonediff.diff, zone_keys, nkeys, zone->mctx,
07753                           inception, soaexpire, check_ksk, keyset_kskonly);
07754         if (result != ISC_R_SUCCESS) {
07755                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
07756                              "add_sigs -> %s", dns_result_totext(result));
07757                 goto failure;
07758         }
07759 
07760         /* Write changes to journal file. */
07761         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
07762 
07763         LOCK_ZONE(zone);
07764         zone_needdump(zone, DNS_DUMP_DELAY);
07765         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
07766         UNLOCK_ZONE(zone);
07767 
07768  done:
07769         /*
07770          * Pause all iterators so that dns_db_closeversion() can succeed.
07771          */
07772         LOCK_ZONE(zone);
07773         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
07774              nsec3chain != NULL;
07775              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
07776                 dns_dbiterator_pause(nsec3chain->dbiterator);
07777         UNLOCK_ZONE(zone);
07778 
07779         /*
07780          * Everything has succeeded. Commit the changes.
07781          * Unconditionally commit as zonediff.offline not checked above.
07782          */
07783         dns_db_closeversion(db, &version, ISC_TRUE);
07784 
07785         /*
07786          * Everything succeeded so we can clean these up now.
07787          */
07788         nsec3chain = ISC_LIST_HEAD(cleanup);
07789         while (nsec3chain != NULL) {
07790                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
07791                 dns_db_detach(&nsec3chain->db);
07792                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
07793                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
07794                 nsec3chain = ISC_LIST_HEAD(cleanup);
07795         }
07796 
07797         set_resigntime(zone);
07798 
07799  failure:
07800         if (result != ISC_R_SUCCESS)
07801                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
07802                              dns_result_totext(result));
07803         /*
07804          * On error roll back the current nsec3chain.
07805          */
07806         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
07807                 if (nsec3chain->done) {
07808                         dns_db_detach(&nsec3chain->db);
07809                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
07810                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
07811                 } else {
07812                         result = dns_dbiterator_first(nsec3chain->dbiterator);
07813                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
07814                         dns_dbiterator_pause(nsec3chain->dbiterator);
07815                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
07816                 }
07817         }
07818 
07819         /*
07820          * Rollback the cleanup list.
07821          */
07822         nsec3chain = ISC_LIST_TAIL(cleanup);
07823         while (nsec3chain != NULL) {
07824                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
07825                 if (nsec3chain->done) {
07826                         dns_db_detach(&nsec3chain->db);
07827                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
07828                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
07829                 } else {
07830                         LOCK_ZONE(zone);
07831                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
07832                         UNLOCK_ZONE(zone);
07833                         result = dns_dbiterator_first(nsec3chain->dbiterator);
07834                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
07835                         dns_dbiterator_pause(nsec3chain->dbiterator);
07836                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
07837                 }
07838                 nsec3chain = ISC_LIST_TAIL(cleanup);
07839         }
07840 
07841         LOCK_ZONE(zone);
07842         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
07843              nsec3chain != NULL;
07844              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
07845                 dns_dbiterator_pause(nsec3chain->dbiterator);
07846         UNLOCK_ZONE(zone);
07847 
07848         dns_diff_clear(&param_diff);
07849         dns_diff_clear(&nsec3_diff);
07850         dns_diff_clear(&nsec_diff);
07851         dns_diff_clear(&_sig_diff);
07852 
07853         if (iterator != NULL)
07854                 dns_rdatasetiter_destroy(&iterator);
07855 
07856         for (i = 0; i < nkeys; i++)
07857                 dst_key_free(&zone_keys[i]);
07858 
07859         if (node != NULL)
07860                 dns_db_detachnode(db, &node);
07861         if (version != NULL) {
07862                 dns_db_closeversion(db, &version, ISC_FALSE);
07863                 dns_db_detach(&db);
07864         } else if (db != NULL)
07865                 dns_db_detach(&db);
07866 
07867         LOCK_ZONE(zone);
07868         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
07869                 isc_interval_t interval;
07870                 if (zone->update_disabled || result != ISC_R_SUCCESS)
07871                         isc_interval_set(&interval, 60, 0);       /* 1 minute */
07872                 else
07873                         isc_interval_set(&interval, 0, 10000000); /* 10 ms */
07874                 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
07875         } else
07876                 isc_time_settoepoch(&zone->nsec3chaintime);
07877         UNLOCK_ZONE(zone);
07878 
07879         INSIST(version == NULL);
07880 }
07881 
07882 static isc_result_t
07883 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
07884         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
07885         isc_uint16_t keyid, dns_diff_t *diff)
07886 {
07887         dns_rdata_rrsig_t rrsig;
07888         dns_rdataset_t rdataset;
07889         dns_rdatasetiter_t *iterator = NULL;
07890         isc_result_t result;
07891 
07892         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
07893         if (result != ISC_R_SUCCESS) {
07894                 if (result == ISC_R_NOTFOUND)
07895                         result = ISC_R_SUCCESS;
07896                 return (result);
07897         }
07898 
07899         dns_rdataset_init(&rdataset);
07900         for (result = dns_rdatasetiter_first(iterator);
07901              result == ISC_R_SUCCESS;
07902              result = dns_rdatasetiter_next(iterator)) {
07903                 dns_rdatasetiter_current(iterator, &rdataset);
07904                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
07905                         for (result = dns_rdataset_first(&rdataset);
07906                              result == ISC_R_SUCCESS;
07907                              result = dns_rdataset_next(&rdataset)) {
07908                                 dns_rdata_t rdata = DNS_RDATA_INIT;
07909                                 dns_rdataset_current(&rdataset, &rdata);
07910                                 CHECK(update_one_rr(db, version, diff,
07911                                                     DNS_DIFFOP_DEL, name,
07912                                                     rdataset.ttl, &rdata));
07913                         }
07914                         if (result != ISC_R_NOMORE)
07915                                 goto failure;
07916                         dns_rdataset_disassociate(&rdataset);
07917                         continue;
07918                 }
07919                 if (rdataset.type != dns_rdatatype_rrsig) {
07920                         dns_rdataset_disassociate(&rdataset);
07921                         continue;
07922                 }
07923                 for (result = dns_rdataset_first(&rdataset);
07924                      result == ISC_R_SUCCESS;
07925                      result = dns_rdataset_next(&rdataset)) {
07926                         dns_rdata_t rdata = DNS_RDATA_INIT;
07927                         dns_rdataset_current(&rdataset, &rdata);
07928                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
07929                         if (rrsig.algorithm != algorithm ||
07930                             rrsig.keyid != keyid)
07931                                 continue;
07932                         CHECK(update_one_rr(db, version, diff,
07933                                             DNS_DIFFOP_DELRESIGN, name,
07934                                             rdataset.ttl, &rdata));
07935                 }
07936                 dns_rdataset_disassociate(&rdataset);
07937                 if (result != ISC_R_NOMORE)
07938                         break;
07939         }
07940         if (result == ISC_R_NOMORE)
07941                 result = ISC_R_SUCCESS;
07942  failure:
07943         if (dns_rdataset_isassociated(&rdataset))
07944                 dns_rdataset_disassociate(&rdataset);
07945         dns_rdatasetiter_destroy(&iterator);
07946         return (result);
07947 }
07948 
07949 /*
07950  * Incrementally sign the zone using the keys requested.
07951  * Builds the NSEC chain if required.
07952  */
07953 static void
07954 zone_sign(dns_zone_t *zone) {
07955         const char *me = "zone_sign";
07956         dns_db_t *db = NULL;
07957         dns_dbnode_t *node = NULL;
07958         dns_dbversion_t *version = NULL;
07959         dns_diff_t _sig_diff;
07960         dns_diff_t post_diff;
07961         zonediff_t zonediff;
07962         dns_fixedname_t fixed;
07963         dns_fixedname_t nextfixed;
07964         dns_name_t *name, *nextname;
07965         dns_rdataset_t rdataset;
07966         dns_signing_t *signing, *nextsigning;
07967         dns_signinglist_t cleanup;
07968         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
07969         isc_int32_t signatures;
07970         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
07971         isc_boolean_t commit = ISC_FALSE;
07972         isc_boolean_t delegation;
07973         isc_boolean_t build_nsec = ISC_FALSE;
07974         isc_boolean_t build_nsec3 = ISC_FALSE;
07975         isc_boolean_t first;
07976         isc_result_t result;
07977         isc_stdtime_t now, inception, soaexpire, expire;
07978         isc_uint32_t jitter;
07979         unsigned int i, j;
07980         unsigned int nkeys = 0;
07981         isc_uint32_t nodes;
07982 
07983         ENTER;
07984 
07985         dns_rdataset_init(&rdataset);
07986         dns_fixedname_init(&fixed);
07987         name = dns_fixedname_name(&fixed);
07988         dns_fixedname_init(&nextfixed);
07989         nextname = dns_fixedname_name(&nextfixed);
07990         dns_diff_init(zone->mctx, &_sig_diff);
07991         dns_diff_init(zone->mctx, &post_diff);
07992         zonediff_init(&zonediff, &_sig_diff);
07993         ISC_LIST_INIT(cleanup);
07994 
07995         /*
07996          * Updates are disabled.  Pause for 5 minutes.
07997          */
07998         if (zone->update_disabled) {
07999                 result = ISC_R_FAILURE;
08000                 goto failure;
08001         }
08002 
08003         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
08004         if (zone->db != NULL)
08005                 dns_db_attach(zone->db, &db);
08006         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
08007         if (db == NULL) {
08008                 result = ISC_R_FAILURE;
08009                 goto failure;
08010         }
08011 
08012         result = dns_db_newversion(db, &version);
08013         if (result != ISC_R_SUCCESS) {
08014                 dns_zone_log(zone, ISC_LOG_ERROR,
08015                              "zone_sign:dns_db_newversion -> %s",
08016                              dns_result_totext(result));
08017                 goto failure;
08018         }
08019 
08020         result = find_zone_keys(zone, db, version, zone->mctx,
08021                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
08022         if (result != ISC_R_SUCCESS) {
08023                 dns_zone_log(zone, ISC_LOG_ERROR,
08024                              "zone_sign:find_zone_keys -> %s",
08025                              dns_result_totext(result));
08026                 goto failure;
08027         }
08028 
08029         isc_stdtime_get(&now);
08030         inception = now - 3600; /* Allow for clock skew. */
08031         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
08032 
08033         /*
08034          * Spread out signatures over time if they happen to be
08035          * clumped.  We don't do this for each add_sigs() call as
08036          * we still want some clustering to occur.
08037          */
08038         isc_random_get(&jitter);
08039         expire = soaexpire - jitter % 3600;
08040 
08041         /*
08042          * We keep pulling nodes off each iterator in turn until
08043          * we have no more nodes to pull off or we reach the limits
08044          * for this quantum.
08045          */
08046         nodes = zone->nodes;
08047         signatures = zone->signatures;
08048         signing = ISC_LIST_HEAD(zone->signing);
08049         first = ISC_TRUE;
08050 
08051         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
08052         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
08053 
08054         /* Determine which type of chain to build */
08055         CHECK(dns_private_chains(db, version, zone->privatetype,
08056                                  &build_nsec, &build_nsec3));
08057 
08058         /* If neither chain is found, default to NSEC */
08059         if (!build_nsec && !build_nsec3)
08060                 build_nsec = ISC_TRUE;
08061 
08062         while (signing != NULL && nodes-- > 0 && signatures > 0) {
08063                 nextsigning = ISC_LIST_NEXT(signing, link);
08064 
08065                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
08066                 if (signing->done || signing->db != zone->db) {
08067                         /*
08068                          * The zone has been reloaded.  We will have
08069                          * created new signings as part of the reload
08070                          * process so we can destroy this one.
08071                          */
08072                         ISC_LIST_UNLINK(zone->signing, signing, link);
08073                         ISC_LIST_APPEND(cleanup, signing, link);
08074                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
08075                         goto next_signing;
08076                 }
08077                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
08078 
08079                 if (signing->db != db)
08080                         goto next_signing;
08081 
08082                 delegation = ISC_FALSE;
08083 
08084                 if (first && signing->delete) {
08085                         /*
08086                          * Remove the key we are deleting from consideration.
08087                          */
08088                         for (i = 0, j = 0; i < nkeys; i++) {
08089                                 /*
08090                                  * Find the key we want to remove.
08091                                  */
08092                                 if (ALG(zone_keys[i]) == signing->algorithm &&
08093                                     dst_key_id(zone_keys[i]) == signing->keyid)
08094                                 {
08095                                         if (KSK(zone_keys[i]))
08096                                                 dst_key_free(&zone_keys[i]);
08097                                         continue;
08098                                 }
08099                                 zone_keys[j] = zone_keys[i];
08100                                 j++;
08101                         }
08102                         nkeys = j;
08103                 }
08104 
08105                 dns_dbiterator_current(signing->dbiterator, &node, name);
08106 
08107                 if (signing->delete) {
08108                         dns_dbiterator_pause(signing->dbiterator);
08109                         CHECK(del_sig(db, version, name, node, nkeys,
08110                                       signing->algorithm, signing->keyid,
08111                                       zonediff.diff));
08112                 }
08113 
08114                 /*
08115                  * On the first pass we need to check if the current node
08116                  * has not been obscured.
08117                  */
08118                 if (first) {
08119                         dns_fixedname_t ffound;
08120                         dns_name_t *found;
08121                         dns_fixedname_init(&ffound);
08122                         found = dns_fixedname_name(&ffound);
08123                         result = dns_db_find(db, name, version,
08124                                              dns_rdatatype_soa,
08125                                              DNS_DBFIND_NOWILD, 0, NULL, found,
08126                                              NULL, NULL);
08127                         if ((result == DNS_R_DELEGATION ||
08128                             result == DNS_R_DNAME) &&
08129                             !dns_name_equal(name, found)) {
08130                                 /*
08131                                  * Remember the obscuring name so that
08132                                  * we skip all obscured names.
08133                                  */
08134                                 dns_name_copy(found, name, NULL);
08135                                 delegation = ISC_TRUE;
08136                                 goto next_node;
08137                         }
08138                 }
08139 
08140                 /*
08141                  * Process one node.
08142                  */
08143                 dns_dbiterator_pause(signing->dbiterator);
08144                 for (i = 0; i < nkeys; i++) {
08145                         isc_boolean_t both = ISC_FALSE;
08146 
08147                         /*
08148                          * Find the keys we want to sign with.
08149                          */
08150                         if (!dst_key_isprivate(zone_keys[i]))
08151                                 continue;
08152 
08153                         /*
08154                          * When adding look for the specific key.
08155                          */
08156                         if (!signing->delete &&
08157                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
08158                              dst_key_id(zone_keys[i]) != signing->keyid))
08159                                 continue;
08160 
08161                         /*
08162                          * When deleting make sure we are properly signed
08163                          * with the algorithm that was being removed.
08164                          */
08165                         if (signing->delete &&
08166                             ALG(zone_keys[i]) != signing->algorithm)
08167                                 continue;
08168 
08169                         /*
08170                          * Do we do KSK processing?
08171                          */
08172                         if (check_ksk && !REVOKE(zone_keys[i])) {
08173                                 isc_boolean_t have_ksk, have_nonksk;
08174                                 if (KSK(zone_keys[i])) {
08175                                         have_ksk = ISC_TRUE;
08176                                         have_nonksk = ISC_FALSE;
08177                                 } else {
08178                                         have_ksk = ISC_FALSE;
08179                                         have_nonksk = ISC_TRUE;
08180                                 }
08181                                 for (j = 0; j < nkeys; j++) {
08182                                         if (j == i ||
08183                                             ALG(zone_keys[i]) !=
08184                                             ALG(zone_keys[j]))
08185                                                 continue;
08186                                         if (REVOKE(zone_keys[j]))
08187                                                 continue;
08188                                         if (KSK(zone_keys[j]))
08189                                                 have_ksk = ISC_TRUE;
08190                                         else
08191                                                 have_nonksk = ISC_TRUE;
08192                                         both = have_ksk && have_nonksk;
08193                                         if (both)
08194                                                 break;
08195                                 }
08196                         }
08197                         if (both || REVOKE(zone_keys[i]))
08198                                 is_ksk = KSK(zone_keys[i]);
08199                         else
08200                                 is_ksk = ISC_FALSE;
08201 
08202                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
08203                                           build_nsec, zone_keys[i], inception,
08204                                           expire, zone->minimum, is_ksk,
08205                                           ISC_TF(both && keyset_kskonly),
08206                                           &delegation, zonediff.diff,
08207                                           &signatures, zone->mctx));
08208                         /*
08209                          * If we are adding we are done.  Look for other keys
08210                          * of the same algorithm if deleting.
08211                          */
08212                         if (!signing->delete)
08213                                 break;
08214                 }
08215 
08216                 /*
08217                  * Go onto next node.
08218                  */
08219  next_node:
08220                 first = ISC_FALSE;
08221                 dns_db_detachnode(db, &node);
08222                 do {
08223                         result = dns_dbiterator_next(signing->dbiterator);
08224                         if (result == ISC_R_NOMORE) {
08225                                 ISC_LIST_UNLINK(zone->signing, signing, link);
08226                                 ISC_LIST_APPEND(cleanup, signing, link);
08227                                 dns_dbiterator_pause(signing->dbiterator);
08228                                 if (nkeys != 0 && build_nsec) {
08229                                         /*
08230                                          * We have finished regenerating the
08231                                          * zone with a zone signing key.
08232                                          * The NSEC chain is now complete and
08233                                          * there is a full set of signatures
08234                                          * for the zone.  We can now clear the
08235                                          * OPT bit from the NSEC record.
08236                                          */
08237                                         result = updatesecure(db, version,
08238                                                               &zone->origin,
08239                                                               zone->minimum,
08240                                                               ISC_FALSE,
08241                                                               &post_diff);
08242                                         if (result != ISC_R_SUCCESS) {
08243                                                 dns_zone_log(zone,
08244                                                              ISC_LOG_ERROR,
08245                                                     "updatesecure -> %s",
08246                                                     dns_result_totext(result));
08247                                                 goto failure;
08248                                         }
08249                                 }
08250                                 result = updatesignwithkey(zone, signing,
08251                                                            version,
08252                                                            build_nsec3,
08253                                                            zone->minimum,
08254                                                            &post_diff);
08255                                 if (result != ISC_R_SUCCESS) {
08256                                         dns_zone_log(zone, ISC_LOG_ERROR,
08257                                                      "updatesignwithkey -> %s",
08258                                                      dns_result_totext(result));
08259                                         goto failure;
08260                                 }
08261                                 build_nsec = ISC_FALSE;
08262                                 goto next_signing;
08263                         } else if (result != ISC_R_SUCCESS) {
08264                                 dns_zone_log(zone, ISC_LOG_ERROR,
08265                                         "zone_sign:dns_dbiterator_next -> %s",
08266                                              dns_result_totext(result));
08267                                 goto failure;
08268                         } else if (delegation) {
08269                                 dns_dbiterator_current(signing->dbiterator,
08270                                                        &node, nextname);
08271                                 dns_db_detachnode(db, &node);
08272                                 if (!dns_name_issubdomain(nextname, name))
08273                                         break;
08274                         } else
08275                                 break;
08276                 } while (1);
08277                 continue;
08278 
08279  next_signing:
08280                 dns_dbiterator_pause(signing->dbiterator);
08281                 signing = nextsigning;
08282                 first = ISC_TRUE;
08283         }
08284 
08285         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
08286                 result = update_sigs(&post_diff, db, version, zone_keys,
08287                                      nkeys, zone, inception, expire, now,
08288                                      check_ksk, keyset_kskonly, &zonediff);
08289                 if (result != ISC_R_SUCCESS) {
08290                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
08291                                      "update_sigs -> %s",
08292                                      dns_result_totext(result));
08293                         goto failure;
08294                 }
08295         }
08296 
08297         /*
08298          * Have we changed anything?
08299          */
08300         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
08301                 if (zonediff.offline)
08302                         commit = ISC_TRUE;
08303                 result = ISC_R_SUCCESS;
08304                 goto pauseall;
08305         }
08306 
08307         commit = ISC_TRUE;
08308 
08309         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
08310                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
08311         if (result != ISC_R_SUCCESS) {
08312                 dns_zone_log(zone, ISC_LOG_ERROR,
08313                              "zone_sign:del_sigs -> %s",
08314                              dns_result_totext(result));
08315                 goto failure;
08316         }
08317 
08318         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
08319                                    zone->updatemethod);
08320         if (result != ISC_R_SUCCESS) {
08321                 dns_zone_log(zone, ISC_LOG_ERROR,
08322                              "zone_sign:update_soa_serial -> %s",
08323                              dns_result_totext(result));
08324                 goto failure;
08325         }
08326 
08327         /*
08328          * Generate maximum life time signatures so that the above loop
08329          * termination is sensible.
08330          */
08331         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
08332                           zonediff.diff, zone_keys, nkeys, zone->mctx,
08333                           inception, soaexpire, check_ksk, keyset_kskonly);
08334         if (result != ISC_R_SUCCESS) {
08335                 dns_zone_log(zone, ISC_LOG_ERROR,
08336                              "zone_sign:add_sigs -> %s",
08337                              dns_result_totext(result));
08338                 goto failure;
08339         }
08340 
08341         /*
08342          * Write changes to journal file.
08343          */
08344         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
08345 
08346  pauseall:
08347         /*
08348          * Pause all iterators so that dns_db_closeversion() can succeed.
08349          */
08350         for (signing = ISC_LIST_HEAD(zone->signing);
08351              signing != NULL;
08352              signing = ISC_LIST_NEXT(signing, link))
08353                 dns_dbiterator_pause(signing->dbiterator);
08354 
08355         for (signing = ISC_LIST_HEAD(cleanup);
08356              signing != NULL;
08357              signing = ISC_LIST_NEXT(signing, link))
08358                 dns_dbiterator_pause(signing->dbiterator);
08359 
08360         /*
08361          * Everything has succeeded. Commit the changes.
08362          */
08363         dns_db_closeversion(db, &version, commit);
08364 
08365         /*
08366          * Everything succeeded so we can clean these up now.
08367          */
08368         signing = ISC_LIST_HEAD(cleanup);
08369         while (signing != NULL) {
08370                 ISC_LIST_UNLINK(cleanup, signing, link);
08371                 dns_db_detach(&signing->db);
08372                 dns_dbiterator_destroy(&signing->dbiterator);
08373                 isc_mem_put(zone->mctx, signing, sizeof *signing);
08374                 signing = ISC_LIST_HEAD(cleanup);
08375         }
08376 
08377         set_resigntime(zone);
08378 
08379         if (commit) {
08380                 LOCK_ZONE(zone);
08381                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
08382                 zone_needdump(zone, DNS_DUMP_DELAY);
08383                 UNLOCK_ZONE(zone);
08384         }
08385 
08386  failure:
08387         /*
08388          * Rollback the cleanup list.
08389          */
08390         signing = ISC_LIST_HEAD(cleanup);
08391         while (signing != NULL) {
08392                 ISC_LIST_UNLINK(cleanup, signing, link);
08393                 ISC_LIST_PREPEND(zone->signing, signing, link);
08394                 dns_dbiterator_first(signing->dbiterator);
08395                 dns_dbiterator_pause(signing->dbiterator);
08396                 signing = ISC_LIST_HEAD(cleanup);
08397         }
08398 
08399         for (signing = ISC_LIST_HEAD(zone->signing);
08400              signing != NULL;
08401              signing = ISC_LIST_NEXT(signing, link))
08402                 dns_dbiterator_pause(signing->dbiterator);
08403 
08404         dns_diff_clear(&_sig_diff);
08405 
08406         for (i = 0; i < nkeys; i++)
08407                 dst_key_free(&zone_keys[i]);
08408 
08409         if (node != NULL)
08410                 dns_db_detachnode(db, &node);
08411 
08412         if (version != NULL) {
08413                 dns_db_closeversion(db, &version, ISC_FALSE);
08414                 dns_db_detach(&db);
08415         } else if (db != NULL)
08416                 dns_db_detach(&db);
08417 
08418         if (ISC_LIST_HEAD(zone->signing) != NULL) {
08419                 isc_interval_t interval;
08420                 if (zone->update_disabled || result != ISC_R_SUCCESS)
08421                         isc_interval_set(&interval, 60, 0);       /* 1 minute */
08422                 else
08423                         isc_interval_set(&interval, 0, 10000000); /* 10 ms */
08424                 isc_time_nowplusinterval(&zone->signingtime, &interval);
08425         } else
08426                 isc_time_settoepoch(&zone->signingtime);
08427 
08428         INSIST(version == NULL);
08429 }
08430 
08431 static isc_result_t
08432 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
08433               unsigned char *data, int size)
08434 {
08435         dns_rdata_dnskey_t dnskey;
08436         dns_rdata_keydata_t keydata;
08437         isc_buffer_t buf;
08438         isc_result_t result;
08439 
08440         dns_rdata_reset(target);
08441         isc_buffer_init(&buf, data, size);
08442 
08443         switch (rr->type) {
08444             case dns_rdatatype_dnskey:
08445                 result = dns_rdata_tostruct(rr, &dnskey, NULL);
08446                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08447                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
08448                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
08449                                      &dnskey, &buf);
08450                 break;
08451             case dns_rdatatype_keydata:
08452                 result = dns_rdata_tostruct(rr, &keydata, NULL);
08453                 if (result == ISC_R_UNEXPECTEDEND)
08454                         return (result);
08455                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08456                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
08457                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
08458                                      &dnskey, &buf);
08459                 break;
08460             default:
08461                 INSIST(0);
08462         }
08463         return (ISC_R_SUCCESS);
08464 }
08465 
08466 /*
08467  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
08468  * a KEYDATA rdataset from the key zone.
08469  *
08470  * 'rr' contains either a DNSKEY record, or a KEYDATA record
08471  *
08472  * After normalizing keys to the same format (DNSKEY, with revoke bit
08473  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
08474  * 'rdset', or ISC_FALSE if not.
08475  */
08476 
08477 static isc_boolean_t
08478 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
08479         unsigned char data1[4096], data2[4096];
08480         dns_rdata_t rdata, rdata1, rdata2;
08481         isc_result_t result;
08482 
08483         dns_rdata_init(&rdata);
08484         dns_rdata_init(&rdata1);
08485         dns_rdata_init(&rdata2);
08486 
08487         result = normalize_key(rr, &rdata1, data1, sizeof(data1));
08488         if (result != ISC_R_SUCCESS)
08489                 return (ISC_FALSE);
08490 
08491         for (result = dns_rdataset_first(rdset);
08492              result == ISC_R_SUCCESS;
08493              result = dns_rdataset_next(rdset)) {
08494                 dns_rdata_reset(&rdata);
08495                 dns_rdataset_current(rdset, &rdata);
08496                 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
08497                 if (result != ISC_R_SUCCESS)
08498                         continue;
08499                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
08500                         return (ISC_TRUE);
08501         }
08502 
08503         return (ISC_FALSE);
08504 }
08505 
08506 /*
08507  * Calculate the refresh interval for a keydata zone, per
08508  * RFC5011: MAX(1 hr,
08509  *              MIN(15 days,
08510  *                  1/2 * OrigTTL,
08511  *                  1/2 * RRSigExpirationInterval))
08512  * or for retries: MAX(1 hr,
08513  *                     MIN(1 day,
08514  *                         1/10 * OrigTTL,
08515  *                         1/10 * RRSigExpirationInterval))
08516  */
08517 static inline isc_stdtime_t
08518 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
08519         isc_result_t result;
08520         isc_uint32_t t;
08521         dns_rdataset_t *rdset;
08522         dns_rdata_t sigrr = DNS_RDATA_INIT;
08523         dns_rdata_sig_t sig;
08524         isc_stdtime_t now;
08525 
08526         isc_stdtime_get(&now);
08527 
08528         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
08529                 rdset = &kfetch->dnskeysigset;
08530         else
08531                 return (now + dns_zone_mkey_hour);
08532 
08533         result = dns_rdataset_first(rdset);
08534         if (result != ISC_R_SUCCESS)
08535                 return (now + dns_zone_mkey_hour);
08536 
08537         dns_rdataset_current(rdset, &sigrr);
08538         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
08539         RUNTIME_CHECK(result == ISC_R_SUCCESS);
08540 
08541         if (!retry) {
08542                 t = sig.originalttl / 2;
08543 
08544                 if (isc_serial_gt(sig.timeexpire, now)) {
08545                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
08546                         if (t > exp)
08547                                 t = exp;
08548                 }
08549 
08550                 if (t > (15 * dns_zone_mkey_day))
08551                         t = (15 * dns_zone_mkey_day);
08552 
08553                 if (t < dns_zone_mkey_hour)
08554                         t = dns_zone_mkey_hour;
08555         } else {
08556                 t = sig.originalttl / 10;
08557 
08558                 if (isc_serial_gt(sig.timeexpire, now)) {
08559                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
08560                         if (t > exp)
08561                                 t = exp;
08562                 }
08563 
08564                 if (t > dns_zone_mkey_day)
08565                         t = dns_zone_mkey_day;
08566 
08567                 if (t < dns_zone_mkey_hour)
08568                         t = dns_zone_mkey_hour;
08569         }
08570 
08571         return (now + t);
08572 }
08573 
08574 /*
08575  * This routine is called when no changes are needed in a KEYDATA
08576  * record except to simply update the refresh timer.  Caller should
08577  * hold zone lock.
08578  */
08579 static isc_result_t
08580 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
08581 {
08582         isc_result_t result;
08583         isc_buffer_t keyb;
08584         unsigned char key_buf[4096];
08585         dns_rdata_t rdata = DNS_RDATA_INIT;
08586         dns_rdata_keydata_t keydata;
08587         dns_name_t *name;
08588         dns_zone_t *zone = kfetch->zone;
08589         isc_stdtime_t now;
08590 
08591         name = dns_fixedname_name(&kfetch->name);
08592         isc_stdtime_get(&now);
08593 
08594         for (result = dns_rdataset_first(&kfetch->keydataset);
08595              result == ISC_R_SUCCESS;
08596              result = dns_rdataset_next(&kfetch->keydataset)) {
08597                 dns_rdata_reset(&rdata);
08598                 dns_rdataset_current(&kfetch->keydataset, &rdata);
08599 
08600                 /* Delete old version */
08601                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
08602                                     name, 0, &rdata));
08603 
08604                 /* Update refresh timer */
08605                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
08606                 if (result == ISC_R_UNEXPECTEDEND)
08607                         continue;
08608                 if (result != ISC_R_SUCCESS)
08609                         goto failure;
08610                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
08611                 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
08612 
08613                 dns_rdata_reset(&rdata);
08614                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
08615                 CHECK(dns_rdata_fromstruct(&rdata,
08616                                            zone->rdclass, dns_rdatatype_keydata,
08617                                            &keydata, &keyb));
08618 
08619                 /* Insert updated version */
08620                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
08621                                     name, 0, &rdata));
08622         }
08623         result = ISC_R_SUCCESS;
08624   failure:
08625         return (result);
08626 }
08627 
08628 /*
08629  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
08630  */
08631 static isc_boolean_t
08632 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
08633         isc_result_t result;
08634         dns_name_t *keyname;
08635         isc_mem_t *mctx;
08636         dns_rdata_t sigrr = DNS_RDATA_INIT;
08637         dns_rdata_t rr = DNS_RDATA_INIT;
08638         dns_rdata_rrsig_t sig;
08639         dns_rdata_dnskey_t dnskey;
08640         dst_key_t *dstkey = NULL;
08641         unsigned char key_buf[4096];
08642         isc_buffer_t keyb;
08643         isc_boolean_t answer = ISC_FALSE;
08644 
08645         REQUIRE(kfetch != NULL && keydata != NULL);
08646         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
08647 
08648         keyname = dns_fixedname_name(&kfetch->name);
08649         mctx = kfetch->zone->view->mctx;
08650 
08651         /* Generate a key from keydata */
08652         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
08653         dns_keydata_todnskey(keydata, &dnskey, NULL);
08654         dns_rdata_fromstruct(&rr, keydata->common.rdclass,
08655                              dns_rdatatype_dnskey, &dnskey, &keyb);
08656         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
08657         if (result != ISC_R_SUCCESS)
08658                 return (ISC_FALSE);
08659 
08660         /* See if that key generated any of the signatures */
08661         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
08662              result == ISC_R_SUCCESS;
08663              result = dns_rdataset_next(&kfetch->dnskeysigset))
08664         {
08665                 dns_fixedname_t fixed;
08666                 dns_fixedname_init(&fixed);
08667 
08668                 dns_rdata_reset(&sigrr);
08669                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
08670                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
08671                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08672 
08673                 if (dst_key_alg(dstkey) == sig.algorithm &&
08674                     dst_key_rid(dstkey) == sig.keyid)
08675                 {
08676                         result = dns_dnssec_verify2(keyname,
08677                                             &kfetch->dnskeyset,
08678                                             dstkey, ISC_FALSE, mctx, &sigrr,
08679                                             dns_fixedname_name(&fixed));
08680 
08681                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
08682                                      "Confirm revoked DNSKEY is self-signed: "
08683                                      "%s", dns_result_totext(result));
08684 
08685                         if (result == ISC_R_SUCCESS) {
08686                                 answer = ISC_TRUE;
08687                                 break;
08688                         }
08689                 }
08690         }
08691 
08692         dst_key_free(&dstkey);
08693         return (answer);
08694 }
08695 
08696 /*
08697  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
08698  * anchors are being managed; scan the keyset, and update the key zone and the
08699  * local trust anchors according to RFC5011.
08700  */
08701 static void
08702 keyfetch_done(isc_task_t *task, isc_event_t *event) {
08703         isc_result_t result, eresult;
08704         dns_fetchevent_t *devent;
08705         dns_keyfetch_t *kfetch;
08706         dns_zone_t *zone;
08707         isc_mem_t *mctx = NULL;
08708         dns_keytable_t *secroots = NULL;
08709         dns_dbversion_t *ver = NULL;
08710         dns_diff_t diff;
08711         isc_boolean_t alldone = ISC_FALSE;
08712         isc_boolean_t commit = ISC_FALSE;
08713         dns_name_t *keyname;
08714         dns_rdata_t sigrr = DNS_RDATA_INIT;
08715         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
08716         dns_rdata_t keydatarr = DNS_RDATA_INIT;
08717         dns_rdata_rrsig_t sig;
08718         dns_rdata_dnskey_t dnskey;
08719         dns_rdata_keydata_t keydata;
08720         isc_boolean_t initializing;
08721         char namebuf[DNS_NAME_FORMATSIZE];
08722         unsigned char key_buf[4096];
08723         isc_buffer_t keyb;
08724         dst_key_t *dstkey;
08725         isc_stdtime_t now;
08726         int pending = 0;
08727         isc_boolean_t secure;
08728         isc_boolean_t free_needed;
08729 
08730         UNUSED(task);
08731         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
08732         INSIST(event->ev_arg != NULL);
08733 
08734         kfetch = event->ev_arg;
08735         zone = kfetch->zone;
08736         isc_mem_attach(zone->mctx, &mctx);
08737         keyname = dns_fixedname_name(&kfetch->name);
08738 
08739         devent = (dns_fetchevent_t *) event;
08740         eresult = devent->result;
08741 
08742         /* Free resources which are not of interest */
08743         if (devent->node != NULL)
08744                 dns_db_detachnode(devent->db, &devent->node);
08745         if (devent->db != NULL)
08746                 dns_db_detach(&devent->db);
08747         isc_event_free(&event);
08748         dns_resolver_destroyfetch(&kfetch->fetch);
08749 
08750         LOCK_ZONE(zone);
08751         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
08752                 goto cleanup;
08753 
08754         isc_stdtime_get(&now);
08755         dns_name_format(keyname, namebuf, sizeof(namebuf));
08756 
08757         result = dns_view_getsecroots(zone->view, &secroots);
08758         INSIST(result == ISC_R_SUCCESS);
08759 
08760         dns_diff_init(mctx, &diff);
08761 
08762         CHECK(dns_db_newversion(kfetch->db, &ver));
08763 
08764         zone->refreshkeycount--;
08765         alldone = ISC_TF(zone->refreshkeycount == 0);
08766 
08767         if (alldone)
08768                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
08769 
08770         /* Fetch failed */
08771         if (eresult != ISC_R_SUCCESS ||
08772             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
08773                 dns_zone_log(zone, ISC_LOG_WARNING,
08774                              "Unable to fetch DNSKEY set "
08775                              "'%s': %s", namebuf, dns_result_totext(eresult));
08776                 CHECK(minimal_update(kfetch, ver, &diff));
08777                 goto done;
08778         }
08779 
08780         /* No RRSIGs found */
08781         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
08782                 dns_zone_log(zone, ISC_LOG_WARNING,
08783                              "No DNSKEY RRSIGs found for "
08784                              "'%s': %s", namebuf, dns_result_totext(eresult));
08785                 CHECK(minimal_update(kfetch, ver, &diff));
08786                 goto done;
08787         }
08788 
08789         /*
08790          * Clear any cached trust level, as we need to run validation
08791          * over again; trusted keys might have changed.
08792          */
08793         kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
08794 
08795         /*
08796          * Validate the dnskeyset against the current trusted keys.
08797          */
08798         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
08799              result == ISC_R_SUCCESS;
08800              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
08801                 dns_keynode_t *keynode = NULL;
08802 
08803                 dns_rdata_reset(&sigrr);
08804                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
08805                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
08806                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08807 
08808                 result = dns_keytable_find(secroots, keyname, &keynode);
08809                 while (result == ISC_R_SUCCESS) {
08810                         dns_keynode_t *nextnode = NULL;
08811                         dns_fixedname_t fixed;
08812                         dns_fixedname_init(&fixed);
08813 
08814                         dstkey = dns_keynode_key(keynode);
08815                         if (dstkey == NULL) /* fail_secure() was called */
08816                                 break;
08817 
08818                         if (dst_key_alg(dstkey) == sig.algorithm &&
08819                             dst_key_id(dstkey) == sig.keyid) {
08820                                 result = dns_dnssec_verify2(keyname,
08821                                                     &kfetch->dnskeyset,
08822                                                     dstkey, ISC_FALSE,
08823                                                     zone->view->mctx, &sigrr,
08824                                                     dns_fixedname_name(&fixed));
08825 
08826                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
08827                                              "Verifying DNSKEY set for zone "
08828                                              "'%s' using key %d/%d: %s",
08829                                              namebuf, sig.keyid, sig.algorithm,
08830                                              dns_result_totext(result));
08831 
08832                                 if (result == ISC_R_SUCCESS) {
08833                                         kfetch->dnskeyset.trust =
08834                                                 dns_trust_secure;
08835                                         kfetch->dnskeysigset.trust =
08836                                                 dns_trust_secure;
08837                                         break;
08838                                 }
08839                         }
08840 
08841                         result = dns_keytable_nextkeynode(secroots,
08842                                                           keynode, &nextnode);
08843                         dns_keytable_detachkeynode(secroots, &keynode);
08844                         keynode = nextnode;
08845                 }
08846 
08847                 if (keynode != NULL)
08848                         dns_keytable_detachkeynode(secroots, &keynode);
08849 
08850                 if (kfetch->dnskeyset.trust == dns_trust_secure)
08851                         break;
08852         }
08853 
08854         /*
08855          * If we were not able to verify the answer using the current
08856          * trusted keys then all we can do is look at any revoked keys.
08857          */
08858         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
08859 
08860         /*
08861          * First scan keydataset to find keys that are not in dnskeyset
08862          *   - Missing keys which are not scheduled for removal,
08863          *     log a warning
08864          *   - Missing keys which are scheduled for removal and
08865          *     the remove hold-down timer has completed should
08866          *     be removed from the key zone
08867          *   - Missing keys whose acceptance timers have not yet
08868          *     completed, log a warning and reset the acceptance
08869          *     timer to 30 days in the future
08870          *   - All keys not being removed have their refresh timers
08871          *     updated
08872          */
08873         initializing = ISC_TRUE;
08874         for (result = dns_rdataset_first(&kfetch->keydataset);
08875              result == ISC_R_SUCCESS;
08876              result = dns_rdataset_next(&kfetch->keydataset)) {
08877                 dns_rdata_reset(&keydatarr);
08878                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
08879                 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
08880                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08881 
08882                 /*
08883                  * If any keydata record has a nonzero add holddown, then
08884                  * there was a pre-existing trust anchor for this domain;
08885                  * that means we are *not* initializing it and shouldn't
08886                  * automatically trust all the keys we find at the zone apex.
08887                  */
08888                 initializing = initializing && ISC_TF(keydata.addhd == 0);
08889 
08890                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
08891                         isc_boolean_t deletekey = ISC_FALSE;
08892 
08893                         if (!secure) {
08894                                 if (keydata.removehd != 0 &&
08895                                     keydata.removehd <= now)
08896                                         deletekey = ISC_TRUE;
08897                         } else if (keydata.addhd == 0) {
08898                                 deletekey = ISC_TRUE;
08899                         } else if (keydata.addhd > now) {
08900                                 dns_zone_log(zone, ISC_LOG_WARNING,
08901                                              "Pending key unexpectedly missing "
08902                                              "from %s; restarting acceptance "
08903                                              "timer", namebuf);
08904                                 if (keydata.addhd < now + dns_zone_mkey_month)
08905                                         keydata.addhd =
08906                                                 now + dns_zone_mkey_month;
08907                                 keydata.refresh = refresh_time(kfetch,
08908                                                                ISC_FALSE);
08909                         } else if (keydata.removehd == 0) {
08910                                 dns_zone_log(zone, ISC_LOG_WARNING,
08911                                              "Active key unexpectedly missing "
08912                                              "from %s", namebuf);
08913                                 keydata.refresh = now + dns_zone_mkey_hour;
08914                         } else if (keydata.removehd <= now) {
08915                                 deletekey = ISC_TRUE;
08916                         } else {
08917                                 keydata.refresh = refresh_time(kfetch,
08918                                                                ISC_FALSE);
08919                         }
08920 
08921                         if (secure || deletekey) {
08922                                 /* Delete old version */
08923                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
08924                                                     DNS_DIFFOP_DEL, keyname, 0,
08925                                                     &keydatarr));
08926                         }
08927 
08928                         if (!secure || deletekey)
08929                                 continue;
08930 
08931                         dns_rdata_reset(&keydatarr);
08932                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
08933                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
08934                                              dns_rdatatype_keydata,
08935                                              &keydata, &keyb);
08936 
08937                         /* Insert updated version */
08938                         CHECK(update_one_rr(kfetch->db, ver, &diff,
08939                                             DNS_DIFFOP_ADD, keyname, 0,
08940                                             &keydatarr));
08941 
08942                         set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
08943                 }
08944         }
08945 
08946         /*
08947          * Next scan dnskeyset:
08948          *   - If new keys are found (i.e., lacking a match in keydataset)
08949          *     add them to the key zone and set the acceptance timer
08950          *     to 30 days in the future (or to immediately if we've
08951          *     determined that we're initializing the zone for the
08952          *     first time)
08953          *   - Previously-known keys that have been revoked
08954          *     must be scheduled for removal from the key zone (or,
08955          *     if they hadn't been accepted as trust anchors yet
08956          *     anyway, removed at once)
08957          *   - Previously-known unrevoked keys whose acceptance timers
08958          *     have completed are promoted to trust anchors
08959          *   - All keys not being removed have their refresh
08960          *     timers updated
08961          */
08962         for (result = dns_rdataset_first(&kfetch->dnskeyset);
08963              result == ISC_R_SUCCESS;
08964              result = dns_rdataset_next(&kfetch->dnskeyset))
08965         {
08966                 isc_boolean_t revoked = ISC_FALSE;
08967                 isc_boolean_t newkey = ISC_FALSE;
08968                 isc_boolean_t updatekey = ISC_FALSE;
08969                 isc_boolean_t deletekey = ISC_FALSE;
08970                 isc_boolean_t trustkey = ISC_FALSE;
08971 
08972                 dns_rdata_reset(&dnskeyrr);
08973                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
08974                 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
08975                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08976 
08977                 /* Skip ZSK's */
08978                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
08979                         continue;
08980 
08981                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
08982 
08983                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
08984                         dns_rdata_reset(&keydatarr);
08985                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
08986                         result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
08987                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
08988 
08989                         if (revoked && revocable(kfetch, &keydata)) {
08990                                 if (keydata.addhd > now) {
08991                                         /*
08992                                          * Key wasn't trusted yet, and now
08993                                          * it's been revoked?  Just remove it
08994                                          */
08995                                         deletekey = ISC_TRUE;
08996                                 } else if (keydata.removehd == 0) {
08997                                         /* Remove from secroots */
08998                                         dns_view_untrust(zone->view, keyname,
08999                                                          &dnskey, mctx);
09000 
09001                                         /* But ensure there's a null key */
09002                                         fail_secure(zone, keyname);
09003 
09004                                         /* If initializing, delete now */
09005                                         if (keydata.addhd == 0)
09006                                                 deletekey = ISC_TRUE;
09007                                         else {
09008                                                 keydata.removehd = now +
09009                                                         dns_zone_mkey_month;
09010                                                 keydata.flags |=
09011                                                         DNS_KEYFLAG_REVOKE;
09012                                         }
09013                                 } else if (keydata.removehd < now) {
09014                                         /* Scheduled for removal */
09015                                         deletekey = ISC_TRUE;
09016                                 }
09017                         } else if (revoked && keydata.removehd == 0) {
09018                                 dns_zone_log(zone, ISC_LOG_WARNING,
09019                                              "Active key for zone "
09020                                              "'%s' is revoked but "
09021                                              "did not self-sign; "
09022                                              "ignoring.", namebuf);
09023                                         continue;
09024                         } else if (secure) {
09025                                 if (keydata.removehd != 0) {
09026                                         /*
09027                                          * Key isn't revoked--but it
09028                                          * seems it used to be.
09029                                          * Remove it now and add it
09030                                          * back as if it were a fresh key,
09031                                          * with a 30 day acceptance timer.
09032                                          */
09033                                         deletekey = ISC_TRUE;
09034                                         newkey = ISC_TRUE;
09035                                         keydata.removehd = 0;
09036                                         keydata.addhd =
09037                                                 now + dns_zone_mkey_month;
09038                                 } else if (keydata.addhd > now)
09039                                         pending++;
09040                                 else if (keydata.addhd == 0)
09041                                         keydata.addhd = now;
09042 
09043                                 if (keydata.addhd <= now)
09044                                         trustkey = ISC_TRUE;
09045                         } else if (keydata.addhd > now) {
09046                                 /*
09047                                  * Not secure, and key is pending:
09048                                  * reset the acceptance timer
09049                                  */
09050                                 pending++;
09051                                 keydata.addhd = now + dns_zone_mkey_month;
09052                         }
09053 
09054                         if (!deletekey && !newkey)
09055                                 updatekey = ISC_TRUE;
09056                 } else if (secure) {
09057                         /*
09058                          * Key wasn't in the key zone but it's
09059                          * revoked now anyway, so just skip it
09060                          */
09061                         if (revoked)
09062                                 continue;
09063 
09064                         /* Key wasn't in the key zone: add it */
09065                         newkey = ISC_TRUE;
09066 
09067                         if (initializing) {
09068                                 dns_keytag_t tag = 0;
09069                                 CHECK(compute_tag(keyname, &dnskey,
09070                                                   mctx, &tag));
09071                                 dns_zone_log(zone, ISC_LOG_WARNING,
09072                                              "Initializing automatic trust "
09073                                              "anchor management for zone '%s'; "
09074                                              "DNSKEY ID %d is now trusted, "
09075                                              "waiving the normal 30-day "
09076                                              "waiting period.",
09077                                              namebuf, tag);
09078                                 trustkey = ISC_TRUE;
09079                         }
09080                 } else {
09081                         /*
09082                          * No previously known key, and the key is not
09083                          * secure, so skip it.
09084                          */
09085                         continue;
09086                 }
09087 
09088                 /* Delete old version */
09089                 if (deletekey || !newkey)
09090                         CHECK(update_one_rr(kfetch->db, ver, &diff,
09091                                             DNS_DIFFOP_DEL, keyname, 0,
09092                                             &keydatarr));
09093 
09094                 if (updatekey) {
09095                         /* Set refresh timer */
09096                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
09097                         dns_rdata_reset(&keydatarr);
09098                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
09099                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
09100                                              dns_rdatatype_keydata,
09101                                              &keydata, &keyb);
09102 
09103                         /* Insert updated version */
09104                         CHECK(update_one_rr(kfetch->db, ver, &diff,
09105                                             DNS_DIFFOP_ADD, keyname, 0,
09106                                             &keydatarr));
09107                 } else if (newkey) {
09108                         /* Convert DNSKEY to KEYDATA */
09109                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
09110                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
09111                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
09112                                                NULL);
09113                         keydata.addhd = initializing
09114                                          ? now : now + dns_zone_mkey_month;
09115                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
09116                         dns_rdata_reset(&keydatarr);
09117                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
09118                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
09119                                              dns_rdatatype_keydata,
09120                                              &keydata, &keyb);
09121 
09122                         /* Insert into key zone */
09123                         CHECK(update_one_rr(kfetch->db, ver, &diff,
09124                                             DNS_DIFFOP_ADD, keyname, 0,
09125                                             &keydatarr));
09126                 }
09127 
09128                 if (trustkey) {
09129                         /* Trust this key. */
09130                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
09131                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
09132                         trust_key(zone, keyname, &dnskey, mctx);
09133                 }
09134 
09135                 if (secure && !deletekey) {
09136                         INSIST(newkey || updatekey);
09137                         set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
09138                 }
09139         }
09140 
09141         /*
09142          * RFC5011 says, "A trust point that has all of its trust anchors
09143          * revoked is considered deleted and is treated as if the trust
09144          * point was never configured."  But if someone revoked their
09145          * active key before the standby was trusted, that would mean the
09146          * zone would suddenly be nonsecured.  We avoid this by checking to
09147          * see if there's pending keydata.  If so, we put a null key in
09148          * the security roots; then all queries to the zone will fail.
09149          */
09150         if (pending != 0)
09151                 fail_secure(zone, keyname);
09152 
09153  done:
09154 
09155         if (!ISC_LIST_EMPTY(diff.tuples)) {
09156                 /* Write changes to journal file. */
09157                 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
09158                                         zone->updatemethod));
09159                 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
09160                 commit = ISC_TRUE;
09161 
09162                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
09163                 zone_needdump(zone, 30);
09164         }
09165 
09166  failure:
09167 
09168         dns_diff_clear(&diff);
09169         if (ver != NULL)
09170                 dns_db_closeversion(kfetch->db, &ver, commit);
09171 
09172  cleanup:
09173         dns_db_detach(&kfetch->db);
09174 
09175         INSIST(zone->irefs > 0);
09176         zone->irefs--;
09177         kfetch->zone = NULL;
09178 
09179         if (dns_rdataset_isassociated(&kfetch->keydataset))
09180                 dns_rdataset_disassociate(&kfetch->keydataset);
09181         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
09182                 dns_rdataset_disassociate(&kfetch->dnskeyset);
09183         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
09184                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
09185 
09186         dns_name_free(keyname, mctx);
09187         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
09188         isc_mem_detach(&mctx);
09189 
09190         if (secroots != NULL)
09191                 dns_keytable_detach(&secroots);
09192 
09193         free_needed = exit_check(zone);
09194         UNLOCK_ZONE(zone);
09195         if (free_needed)
09196                 zone_free(zone);
09197 
09198         INSIST(ver == NULL);
09199 }
09200 
09201 /*
09202  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
09203  * records from the zone apex.
09204  */
09205 static void
09206 zone_refreshkeys(dns_zone_t *zone) {
09207         const char me[] = "zone_refreshkeys";
09208         isc_result_t result;
09209         dns_rriterator_t rrit;
09210         dns_db_t *db = NULL;
09211         dns_dbversion_t *ver = NULL;
09212         dns_diff_t diff;
09213         dns_rdata_t rdata = DNS_RDATA_INIT;
09214         dns_rdata_keydata_t kd;
09215         isc_stdtime_t now;
09216         isc_boolean_t commit = ISC_FALSE;
09217         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
09218 
09219         ENTER;
09220         REQUIRE(zone->db != NULL);
09221 
09222         isc_stdtime_get(&now);
09223 
09224         LOCK_ZONE(zone);
09225         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
09226                 isc_time_settoepoch(&zone->refreshkeytime);
09227                 UNLOCK_ZONE(zone);
09228                 return;
09229         }
09230 
09231         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
09232         dns_db_attach(zone->db, &db);
09233         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
09234 
09235         dns_diff_init(zone->mctx, &diff);
09236 
09237         CHECK(dns_db_newversion(db, &ver));
09238 
09239         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
09240 
09241         dns_rriterator_init(&rrit, db, ver, 0);
09242         for (result = dns_rriterator_first(&rrit);
09243              result == ISC_R_SUCCESS;
09244              result = dns_rriterator_nextrrset(&rrit)) {
09245                 isc_stdtime_t timer = 0xffffffff;
09246                 dns_name_t *name = NULL, *kname = NULL;
09247                 dns_rdataset_t *kdset = NULL;
09248                 dns_keyfetch_t *kfetch;
09249                 isc_uint32_t ttl;
09250 
09251                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
09252                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
09253                     !dns_rdataset_isassociated(kdset))
09254                         continue;
09255 
09256                 /*
09257                  * Scan the stored keys looking for ones that need
09258                  * removal or refreshing
09259                  */
09260                 for (result = dns_rdataset_first(kdset);
09261                      result == ISC_R_SUCCESS;
09262                      result = dns_rdataset_next(kdset)) {
09263                         dns_rdata_reset(&rdata);
09264                         dns_rdataset_current(kdset, &rdata);
09265                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
09266                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
09267 
09268                         /* Removal timer expired? */
09269                         if (kd.removehd != 0 && kd.removehd < now) {
09270                                 CHECK(update_one_rr(db, ver, &diff,
09271                                                     DNS_DIFFOP_DEL, name, ttl,
09272                                                     &rdata));
09273                                 continue;
09274                         }
09275 
09276                         /* Acceptance timer expired? */
09277                         if (kd.addhd != 0 && kd.addhd < now)
09278                                 timer = kd.addhd;
09279 
09280                         /* Or do we just need to refresh the keyset? */
09281                         if (timer > kd.refresh)
09282                                 timer = kd.refresh;
09283                 }
09284 
09285                 if (timer > now)
09286                         continue;
09287 
09288                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
09289                 if (kfetch == NULL) {
09290                         fetch_err = ISC_TRUE;
09291                         goto failure;
09292                 }
09293 
09294                 zone->refreshkeycount++;
09295                 kfetch->zone = zone;
09296                 zone->irefs++;
09297                 INSIST(zone->irefs != 0);
09298                 dns_fixedname_init(&kfetch->name);
09299                 kname = dns_fixedname_name(&kfetch->name);
09300                 dns_name_dup(name, zone->mctx, kname);
09301                 dns_rdataset_init(&kfetch->dnskeyset);
09302                 dns_rdataset_init(&kfetch->dnskeysigset);
09303                 dns_rdataset_init(&kfetch->keydataset);
09304                 dns_rdataset_clone(kdset, &kfetch->keydataset);
09305                 kfetch->db = NULL;
09306                 dns_db_attach(db, &kfetch->db);
09307                 kfetch->fetch = NULL;
09308 
09309                 result = dns_resolver_createfetch(zone->view->resolver,
09310                                                   kname, dns_rdatatype_dnskey,
09311                                                   NULL, NULL, NULL,
09312                                                   DNS_FETCHOPT_NOVALIDATE,
09313                                                   zone->task,
09314                                                   keyfetch_done, kfetch,
09315                                                   &kfetch->dnskeyset,
09316                                                   &kfetch->dnskeysigset,
09317                                                   &kfetch->fetch);
09318                 if (result == ISC_R_SUCCESS)
09319                         fetching = ISC_TRUE;
09320                 else {
09321                         zone->refreshkeycount--;
09322                         zone->irefs--;
09323                         dns_db_detach(&kfetch->db);
09324                         dns_rdataset_disassociate(&kfetch->keydataset);
09325                         dns_name_free(kname, zone->mctx);
09326                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
09327                         dns_zone_log(zone, ISC_LOG_WARNING,
09328                                      "Failed to create fetch for "
09329                                      "DNSKEY update");
09330                         fetch_err = ISC_TRUE;
09331                 }
09332         }
09333         if (!ISC_LIST_EMPTY(diff.tuples)) {
09334                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
09335                                         zone->updatemethod));
09336                 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
09337                 commit = ISC_TRUE;
09338                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
09339                 zone_needdump(zone, 30);
09340         }
09341 
09342   failure:
09343         if (fetch_err) {
09344                 /*
09345                  * Error during a key fetch; retry in an hour.
09346                  */
09347                 isc_time_t timenow, timethen;
09348                 char timebuf[80];
09349 
09350                 TIME_NOW(&timenow);
09351                 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
09352                 zone->refreshkeytime = timethen;
09353                 zone_settimer(zone, &timenow);
09354 
09355                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
09356                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
09357                              timebuf);
09358 
09359                 if (!fetching)
09360                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
09361         }
09362 
09363         UNLOCK_ZONE(zone);
09364 
09365         dns_diff_clear(&diff);
09366         if (ver != NULL) {
09367                 dns_rriterator_destroy(&rrit);
09368                 dns_db_closeversion(db, &ver, commit);
09369         }
09370         dns_db_detach(&db);
09371 
09372         INSIST(ver == NULL);
09373 }
09374 
09375 static void
09376 zone_maintenance(dns_zone_t *zone) {
09377         const char me[] = "zone_maintenance";
09378         isc_time_t now;
09379         isc_result_t result;
09380         isc_boolean_t dumping;
09381 
09382         REQUIRE(DNS_ZONE_VALID(zone));
09383         ENTER;
09384 
09385         /*
09386          * Are we pending load/reload?
09387          */
09388         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
09389                 return;
09390 
09391         /*
09392          * Configuring the view of this zone may have
09393          * failed, for example because the config file
09394          * had a syntax error.  In that case, the view
09395          * adb or resolver will be NULL, and we had better not try
09396          * to do further maintenance on it.
09397          */
09398         if (zone->view == NULL || zone->view->adb == NULL)
09399                 return;
09400 
09401         TIME_NOW(&now);
09402 
09403         /*
09404          * Expire check.
09405          */
09406         switch (zone->type) {
09407         case dns_zone_redirect:
09408                 if (zone->masters == NULL)
09409                         break;
09410         case dns_zone_slave:
09411         case dns_zone_stub:
09412                 LOCK_ZONE(zone);
09413                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
09414                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
09415                         zone_expire(zone);
09416                         zone->refreshtime = now;
09417                 }
09418                 UNLOCK_ZONE(zone);
09419                 break;
09420         default:
09421                 break;
09422         }
09423 
09424         /*
09425          * Up to date check.
09426          */
09427         switch (zone->type) {
09428         case dns_zone_redirect:
09429                 if (zone->masters == NULL)
09430                         break;
09431         case dns_zone_slave:
09432         case dns_zone_stub:
09433                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
09434                     isc_time_compare(&now, &zone->refreshtime) >= 0)
09435                         dns_zone_refresh(zone);
09436                 break;
09437         default:
09438                 break;
09439         }
09440 
09441         /*
09442          * Slaves send notifies before backing up to disk, masters after.
09443          */
09444         if (zone->type == dns_zone_slave &&
09445             (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
09446              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
09447             isc_time_compare(&now, &zone->notifytime) >= 0)
09448                 zone_notify(zone, &now);
09449 
09450         /*
09451          * Do we need to consolidate the backing store?
09452          */
09453         switch (zone->type) {
09454         case dns_zone_master:
09455         case dns_zone_slave:
09456         case dns_zone_key:
09457         case dns_zone_redirect:
09458         case dns_zone_stub:
09459                 LOCK_ZONE(zone);
09460                 if (zone->masterfile != NULL &&
09461                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
09462                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
09463                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
09464                         dumping = was_dumping(zone);
09465                 } else
09466                         dumping = ISC_TRUE;
09467                 UNLOCK_ZONE(zone);
09468                 if (!dumping) {
09469                         result = zone_dump(zone, ISC_TRUE); /* task locked */
09470                         if (result != ISC_R_SUCCESS)
09471                                 dns_zone_log(zone, ISC_LOG_WARNING,
09472                                              "dump failed: %s",
09473                                              dns_result_totext(result));
09474                 }
09475                 break;
09476         default:
09477                 break;
09478         }
09479 
09480         /*
09481          * Master/redirect zones send notifies now, if needed
09482          */
09483         switch (zone->type) {
09484         case dns_zone_master:
09485         case dns_zone_redirect:
09486                 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
09487                      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
09488                     isc_time_compare(&now, &zone->notifytime) >= 0)
09489                         zone_notify(zone, &now);
09490         default:
09491                 break;
09492         }
09493 
09494         /*
09495          * Do we need to refresh keys?
09496          */
09497         switch (zone->type) {
09498         case dns_zone_key:
09499                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
09500                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
09501                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
09502                                 zone_refreshkeys(zone);
09503                         }
09504                 }
09505                 break;
09506         case dns_zone_master:
09507                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
09508                     isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
09509                     zone->rss_event == NULL)
09510                         zone_rekey(zone);
09511         default:
09512                 break;
09513         }
09514 
09515         switch (zone->type) {
09516         case dns_zone_master:
09517         case dns_zone_redirect:
09518         case dns_zone_slave:
09519                 /*
09520                  * Do we need to sign/resign some RRsets?
09521                  */
09522                 if (zone->rss_event != NULL)
09523                         break;
09524                 if (!isc_time_isepoch(&zone->signingtime) &&
09525                     isc_time_compare(&now, &zone->signingtime) >= 0)
09526                         zone_sign(zone);
09527                 else if (!isc_time_isepoch(&zone->resigntime) &&
09528                     isc_time_compare(&now, &zone->resigntime) >= 0)
09529                         zone_resigninc(zone);
09530                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
09531                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
09532                         zone_nsec3chain(zone);
09533                 /*
09534                  * Do we need to issue a key expiry warning?
09535                  */
09536                 if (!isc_time_isepoch(&zone->keywarntime) &&
09537                     isc_time_compare(&now, &zone->keywarntime) >= 0)
09538                         set_key_expiry_warning(zone, zone->key_expiry,
09539                                                isc_time_seconds(&now));
09540                 break;
09541 
09542         default:
09543                 break;
09544         }
09545         zone_settimer(zone, &now);
09546 }
09547 
09548 void
09549 dns_zone_markdirty(dns_zone_t *zone) {
09550         isc_uint32_t serial;
09551         isc_result_t result = ISC_R_SUCCESS;
09552         dns_zone_t *secure = NULL;
09553 
09554         /*
09555          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
09556          * could result in a deadlock due to a LOR so we will spin if we
09557          * can't obtain the both locks.
09558          */
09559  again:
09560         LOCK_ZONE(zone);
09561         if (zone->type == dns_zone_master) {
09562                 if (inline_raw(zone)) {
09563                         unsigned int soacount;
09564                         secure = zone->secure;
09565                         INSIST(secure != zone);
09566                         TRYLOCK_ZONE(result, secure);
09567                         if (result != ISC_R_SUCCESS) {
09568                                 UNLOCK_ZONE(zone);
09569                                 secure = NULL;
09570 #ifdef ISC_PLATFORM_USETHREADS
09571                                 isc_thread_yield();
09572 #endif
09573                                 goto again;
09574                         }
09575 
09576                         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
09577                         if (zone->db != NULL) {
09578                                 result = zone_get_from_db(zone, zone->db, NULL,
09579                                                           &soacount, &serial,
09580                                                           NULL, NULL, NULL,
09581                                                           NULL, NULL);
09582                         } else
09583                                 result = DNS_R_NOTLOADED;
09584                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
09585                         if (result == ISC_R_SUCCESS && soacount > 0U)
09586                                 zone_send_secureserial(zone, serial);
09587                 }
09588 
09589                 /* XXXMPA make separate call back */
09590                 if (result == ISC_R_SUCCESS)
09591                         set_resigntime(zone);
09592         }
09593         if (secure != NULL)
09594                 UNLOCK_ZONE(secure);
09595         zone_needdump(zone, DNS_DUMP_DELAY);
09596         UNLOCK_ZONE(zone);
09597 }
09598 
09599 void
09600 dns_zone_expire(dns_zone_t *zone) {
09601         REQUIRE(DNS_ZONE_VALID(zone));
09602 
09603         LOCK_ZONE(zone);
09604         zone_expire(zone);
09605         UNLOCK_ZONE(zone);
09606 }
09607 
09608 static void
09609 zone_expire(dns_zone_t *zone) {
09610         /*
09611          * 'zone' locked by caller.
09612          */
09613 
09614         REQUIRE(LOCKED_ZONE(zone));
09615 
09616         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
09617 
09618         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
09619         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
09620         zone->retry = DNS_ZONE_DEFAULTRETRY;
09621         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
09622         zone_unload(zone);
09623 }
09624 
09625 void
09626 dns_zone_refresh(dns_zone_t *zone) {
09627         isc_interval_t i;
09628         isc_uint32_t oldflags;
09629         unsigned int j;
09630         isc_result_t result;
09631 
09632         REQUIRE(DNS_ZONE_VALID(zone));
09633 
09634         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
09635                 return;
09636 
09637         /*
09638          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
09639          * in progress at a time.
09640          */
09641 
09642         LOCK_ZONE(zone);
09643         oldflags = zone->flags;
09644         if (zone->masterscnt == 0) {
09645                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
09646                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
09647                         dns_zone_log(zone, ISC_LOG_ERROR,
09648                                      "cannot refresh: no masters");
09649                 goto unlock;
09650         }
09651         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
09652         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
09653         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
09654         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
09655                 goto unlock;
09656 
09657         /*
09658          * Set the next refresh time as if refresh check has failed.
09659          * Setting this to the retry time will do that.  XXXMLG
09660          * If we are successful it will be reset using zone->refresh.
09661          */
09662         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
09663                          0);
09664         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
09665         if (result != ISC_R_SUCCESS)
09666                 dns_zone_log(zone, ISC_LOG_WARNING,
09667                              "isc_time_nowplusinterval() failed: %s",
09668                              dns_result_totext(result));
09669 
09670         /*
09671          * When lacking user-specified timer values from the SOA,
09672          * do exponential backoff of the retry time up to a
09673          * maximum of six hours.
09674          */
09675         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
09676                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
09677 
09678         zone->curmaster = 0;
09679         for (j = 0; j < zone->masterscnt; j++)
09680                 zone->mastersok[j] = ISC_FALSE;
09681         /* initiate soa query */
09682         queue_soa_query(zone);
09683  unlock:
09684         UNLOCK_ZONE(zone);
09685 }
09686 
09687 isc_result_t
09688 dns_zone_flush(dns_zone_t *zone) {
09689         isc_result_t result = ISC_R_SUCCESS;
09690         isc_boolean_t dumping;
09691 
09692         REQUIRE(DNS_ZONE_VALID(zone));
09693 
09694         LOCK_ZONE(zone);
09695         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
09696         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
09697             zone->masterfile != NULL) {
09698                 result = ISC_R_ALREADYRUNNING;
09699                 dumping = was_dumping(zone);
09700         } else
09701                 dumping = ISC_TRUE;
09702         UNLOCK_ZONE(zone);
09703         if (!dumping)
09704                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
09705         return (result);
09706 }
09707 
09708 isc_result_t
09709 dns_zone_dump(dns_zone_t *zone) {
09710         isc_result_t result = ISC_R_ALREADYRUNNING;
09711         isc_boolean_t dumping;
09712 
09713         REQUIRE(DNS_ZONE_VALID(zone));
09714 
09715         LOCK_ZONE(zone);
09716         dumping = was_dumping(zone);
09717         UNLOCK_ZONE(zone);
09718         if (!dumping)
09719                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
09720         return (result);
09721 }
09722 
09723 static void
09724 zone_needdump(dns_zone_t *zone, unsigned int delay) {
09725         const char me[] = "zone_needdump";
09726         isc_time_t dumptime;
09727         isc_time_t now;
09728 
09729         /*
09730          * 'zone' locked by caller
09731          */
09732 
09733         REQUIRE(DNS_ZONE_VALID(zone));
09734         REQUIRE(LOCKED_ZONE(zone));
09735         ENTER;
09736 
09737         /*
09738          * Do we have a place to dump to and are we loaded?
09739          */
09740         if (zone->masterfile == NULL ||
09741             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
09742                 return;
09743 
09744         TIME_NOW(&now);
09745         /* add some noise */
09746         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
09747 
09748         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
09749         if (isc_time_isepoch(&zone->dumptime) ||
09750             isc_time_compare(&zone->dumptime, &dumptime) > 0)
09751                 zone->dumptime = dumptime;
09752         if (zone->task != NULL)
09753                 zone_settimer(zone, &now);
09754 }
09755 
09756 static void
09757 dump_done(void *arg, isc_result_t result) {
09758         const char me[] = "dump_done";
09759         dns_zone_t *zone = arg;
09760         dns_db_t *db;
09761         dns_dbversion_t *version;
09762         isc_boolean_t again = ISC_FALSE;
09763         isc_boolean_t compact = ISC_FALSE;
09764         isc_uint32_t serial;
09765         isc_result_t tresult;
09766 
09767         REQUIRE(DNS_ZONE_VALID(zone));
09768 
09769         ENTER;
09770 
09771         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
09772             zone->journalsize != -1) {
09773 
09774                 /*
09775                  * We don't own these, zone->dctx must stay valid.
09776                  */
09777                 db = dns_dumpctx_db(zone->dctx);
09778                 version = dns_dumpctx_version(zone->dctx);
09779 
09780                 tresult = dns_db_getsoaserial(db, version, &serial);
09781                 /*
09782                  * If there is a secure version of this zone
09783                  * use its serial if it is less than ours.
09784                  */
09785                 if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
09786                     zone->secure->db != NULL)
09787                 {
09788                         isc_uint32_t sserial;
09789                         isc_result_t mresult;
09790 
09791                         mresult = dns_db_getsoaserial(zone->secure->db,
09792                                                       NULL, &sserial);
09793                         if (mresult == ISC_R_SUCCESS &&
09794                             isc_serial_lt(sserial, serial))
09795                                 serial = sserial;
09796                 }
09797                 /*
09798                  * Note: we are task locked here so we can test
09799                  * zone->xfr safely.
09800                  */
09801                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
09802                         tresult = dns_journal_compact(zone->mctx,
09803                                                       zone->journal,
09804                                                       serial,
09805                                                       zone->journalsize);
09806                         switch (tresult) {
09807                         case ISC_R_SUCCESS:
09808                         case ISC_R_NOSPACE:
09809                         case ISC_R_NOTFOUND:
09810                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
09811                                              "dns_journal_compact: %s",
09812                                              dns_result_totext(tresult));
09813                                 break;
09814                         default:
09815                                 dns_zone_log(zone, ISC_LOG_ERROR,
09816                                              "dns_journal_compact failed: %s",
09817                                              dns_result_totext(tresult));
09818                                 break;
09819                         }
09820                 } else if (tresult == ISC_R_SUCCESS) {
09821                         compact = ISC_TRUE;
09822                         zone->compact_serial = serial;
09823                 }
09824         }
09825 
09826         LOCK_ZONE(zone);
09827         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
09828         if (compact)
09829                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
09830         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
09831                 /*
09832                  * Try again in a short while.
09833                  */
09834                 zone_needdump(zone, DNS_DUMP_DELAY);
09835         } else if (result == ISC_R_SUCCESS &&
09836                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
09837                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
09838                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
09839                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
09840                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
09841                 isc_time_settoepoch(&zone->dumptime);
09842                 again = ISC_TRUE;
09843         } else if (result == ISC_R_SUCCESS)
09844                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
09845 
09846         if (zone->dctx != NULL)
09847                 dns_dumpctx_detach(&zone->dctx);
09848         zonemgr_putio(&zone->writeio);
09849         UNLOCK_ZONE(zone);
09850         if (again)
09851                 (void)zone_dump(zone, ISC_FALSE);
09852         dns_zone_idetach(&zone);
09853 }
09854 
09855 static isc_result_t
09856 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
09857         const char me[] = "zone_dump";
09858         isc_result_t result;
09859         dns_dbversion_t *version = NULL;
09860         isc_boolean_t again;
09861         dns_db_t *db = NULL;
09862         char *masterfile = NULL;
09863         dns_masterformat_t masterformat = dns_masterformat_none;
09864 
09865 /*
09866  * 'compact' MUST only be set if we are task locked.
09867  */
09868 
09869         REQUIRE(DNS_ZONE_VALID(zone));
09870         ENTER;
09871 
09872  redo:
09873         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
09874         if (zone->db != NULL)
09875                 dns_db_attach(zone->db, &db);
09876         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
09877         LOCK_ZONE(zone);
09878         if (zone->masterfile != NULL) {
09879                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
09880                 masterformat = zone->masterformat;
09881         }
09882         UNLOCK_ZONE(zone);
09883         if (db == NULL) {
09884                 result = DNS_R_NOTLOADED;
09885                 goto fail;
09886         }
09887         if (masterfile == NULL) {
09888                 result = DNS_R_NOMASTERFILE;
09889                 goto fail;
09890         }
09891 
09892         if (compact && zone->type != dns_zone_stub) {
09893                 dns_zone_t *dummy = NULL;
09894                 LOCK_ZONE(zone);
09895                 zone_iattach(zone, &dummy);
09896                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
09897                                        zone_gotwritehandle, zone,
09898                                        &zone->writeio);
09899                 if (result != ISC_R_SUCCESS)
09900                         zone_idetach(&dummy);
09901                 else
09902                         result = DNS_R_CONTINUE;
09903                 UNLOCK_ZONE(zone);
09904         } else {
09905                 const dns_master_style_t *output_style;
09906 
09907                 dns_masterrawheader_t rawdata;
09908                 dns_db_currentversion(db, &version);
09909                 dns_master_initrawheader(&rawdata);
09910                 if (inline_secure(zone))
09911                         get_raw_serial(zone->raw, &rawdata);
09912                 if (zone->type == dns_zone_key)
09913                         output_style = &dns_master_style_keyzone;
09914                 else
09915                         output_style = &dns_master_style_default;
09916                 result = dns_master_dump3(zone->mctx, db, version,
09917                                           output_style, masterfile,
09918                                           masterformat, &rawdata);
09919                 dns_db_closeversion(db, &version, ISC_FALSE);
09920         }
09921  fail:
09922         if (db != NULL)
09923                 dns_db_detach(&db);
09924         if (masterfile != NULL)
09925                 isc_mem_free(zone->mctx, masterfile);
09926         masterfile = NULL;
09927 
09928         if (result == DNS_R_CONTINUE)
09929                 return (ISC_R_SUCCESS); /* XXXMPA */
09930 
09931         again = ISC_FALSE;
09932         LOCK_ZONE(zone);
09933         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
09934         if (result != ISC_R_SUCCESS) {
09935                 /*
09936                  * Try again in a short while.
09937                  */
09938                 zone_needdump(zone, DNS_DUMP_DELAY);
09939         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
09940                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
09941                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
09942                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
09943                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
09944                 isc_time_settoepoch(&zone->dumptime);
09945                 again = ISC_TRUE;
09946         } else
09947                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
09948         UNLOCK_ZONE(zone);
09949         if (again)
09950                 goto redo;
09951 
09952         return (result);
09953 }
09954 
09955 static isc_result_t
09956 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
09957              dns_masterformat_t format, const isc_uint32_t rawversion)
09958 {
09959         isc_result_t result;
09960         dns_dbversion_t *version = NULL;
09961         dns_db_t *db = NULL;
09962         dns_masterrawheader_t rawdata;
09963 
09964         REQUIRE(DNS_ZONE_VALID(zone));
09965 
09966         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
09967         if (zone->db != NULL)
09968                 dns_db_attach(zone->db, &db);
09969         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
09970         if (db == NULL)
09971                 return (DNS_R_NOTLOADED);
09972 
09973         dns_db_currentversion(db, &version);
09974         dns_master_initrawheader(&rawdata);
09975         if (rawversion == 0)
09976                 rawdata.flags |= DNS_MASTERRAW_COMPAT;
09977         else if (inline_secure(zone))
09978                 get_raw_serial(zone->raw, &rawdata);
09979         else if (zone->sourceserialset) {
09980                 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
09981                 rawdata.sourceserial = zone->sourceserial;
09982         }
09983         result = dns_master_dumptostream3(zone->mctx, db, version, style,
09984                                           format, &rawdata, fd);
09985         dns_db_closeversion(db, &version, ISC_FALSE);
09986         dns_db_detach(&db);
09987         return (result);
09988 }
09989 
09990 isc_result_t
09991 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
09992                        const dns_master_style_t *style,
09993                        const isc_uint32_t rawversion)
09994 {
09995         return (dumptostream(zone, fd, style, format, rawversion));
09996 }
09997 
09998 isc_result_t
09999 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
10000                        const dns_master_style_t *style) {
10001         return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
10002 }
10003 
10004 isc_result_t
10005 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
10006         return (dumptostream(zone, fd, &dns_master_style_default,
10007                              dns_masterformat_text, 0));
10008 }
10009 
10010 isc_result_t
10011 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
10012         return (dumptostream(zone, fd, &dns_master_style_full,
10013                              dns_masterformat_text, 0));
10014 }
10015 
10016 void
10017 dns_zone_unload(dns_zone_t *zone) {
10018         REQUIRE(DNS_ZONE_VALID(zone));
10019 
10020         LOCK_ZONE(zone);
10021         zone_unload(zone);
10022         UNLOCK_ZONE(zone);
10023 }
10024 
10025 static void
10026 notify_cancel(dns_zone_t *zone) {
10027         dns_notify_t *notify;
10028 
10029         /*
10030          * 'zone' locked by caller.
10031          */
10032 
10033         REQUIRE(LOCKED_ZONE(zone));
10034 
10035         for (notify = ISC_LIST_HEAD(zone->notifies);
10036              notify != NULL;
10037              notify = ISC_LIST_NEXT(notify, link)) {
10038                 if (notify->find != NULL)
10039                         dns_adb_cancelfind(notify->find);
10040                 if (notify->request != NULL)
10041                         dns_request_cancel(notify->request);
10042         }
10043 }
10044 
10045 static void
10046 forward_cancel(dns_zone_t *zone) {
10047         dns_forward_t *forward;
10048 
10049         /*
10050          * 'zone' locked by caller.
10051          */
10052 
10053         REQUIRE(LOCKED_ZONE(zone));
10054 
10055         for (forward = ISC_LIST_HEAD(zone->forwards);
10056              forward != NULL;
10057              forward = ISC_LIST_NEXT(forward, link)) {
10058                 if (forward->request != NULL)
10059                         dns_request_cancel(forward->request);
10060         }
10061 }
10062 
10063 static void
10064 zone_unload(dns_zone_t *zone) {
10065         /*
10066          * 'zone' locked by caller.
10067          */
10068 
10069         REQUIRE(LOCKED_ZONE(zone));
10070 
10071         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10072             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10073                 if (zone->writeio != NULL)
10074                         zonemgr_cancelio(zone->writeio);
10075 
10076                 if (zone->dctx != NULL)
10077                         dns_dumpctx_cancel(zone->dctx);
10078         }
10079         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10080         zone_detachdb(zone);
10081         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10082         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
10083         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10084 }
10085 
10086 void
10087 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
10088         REQUIRE(DNS_ZONE_VALID(zone));
10089         REQUIRE(val > 0);
10090 
10091         zone->minrefresh = val;
10092 }
10093 
10094 void
10095 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
10096         REQUIRE(DNS_ZONE_VALID(zone));
10097         REQUIRE(val > 0);
10098 
10099         zone->maxrefresh = val;
10100 }
10101 
10102 void
10103 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
10104         REQUIRE(DNS_ZONE_VALID(zone));
10105         REQUIRE(val > 0);
10106 
10107         zone->minretry = val;
10108 }
10109 
10110 void
10111 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
10112         REQUIRE(DNS_ZONE_VALID(zone));
10113         REQUIRE(val > 0);
10114 
10115         zone->maxretry = val;
10116 }
10117 
10118 static isc_boolean_t
10119 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
10120                 isc_sockaddr_t *addr, dns_tsigkey_t *key)
10121 {
10122         dns_notify_t *notify;
10123         dns_zonemgr_t *zmgr;
10124         isc_result_t result;
10125 
10126         for (notify = ISC_LIST_HEAD(zone->notifies);
10127              notify != NULL;
10128              notify = ISC_LIST_NEXT(notify, link)) {
10129                 if (notify->request != NULL)
10130                         continue;
10131                 if ((flags & DNS_NOTIFY_STARTUP) == 0)
10132                         notify->flags &= ~DNS_NOTIFY_STARTUP;
10133                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
10134                     dns_name_equal(name, &notify->ns))
10135                         goto requeue;
10136                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
10137                     notify->key == key)
10138                         goto requeue;
10139         }
10140         return (ISC_FALSE);
10141 
10142 requeue:
10143         /*
10144          * If we are enqueued on the startup ratelimiter and this is
10145          * not a startup notify, re-enqueue on the normal notify
10146          * ratelimiter.
10147          */
10148         if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0) {
10149                 zmgr = notify->zone->zmgr;
10150                 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
10151                                                  notify->event);
10152                 if (result != ISC_R_SUCCESS)
10153                         return (ISC_TRUE);
10154                 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
10155                                                  notify->zone->task,
10156                                                  &notify->event);
10157                 if (result != ISC_R_SUCCESS) {
10158                         isc_event_free(&notify->event);
10159                         return (ISC_FALSE);
10160                 }
10161         }
10162 
10163         return (ISC_TRUE);
10164 }
10165 
10166 static isc_boolean_t
10167 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
10168         dns_tsigkey_t *key = NULL;
10169         isc_sockaddr_t src;
10170         isc_sockaddr_t any;
10171         isc_boolean_t isself;
10172         isc_netaddr_t dstaddr;
10173         isc_result_t result;
10174 
10175         if (zone->view == NULL || zone->isself == NULL)
10176                 return (ISC_FALSE);
10177 
10178         switch (isc_sockaddr_pf(dst)) {
10179         case PF_INET:
10180                 src = zone->notifysrc4;
10181                 isc_sockaddr_any(&any);
10182                 break;
10183         case PF_INET6:
10184                 src = zone->notifysrc6;
10185                 isc_sockaddr_any6(&any);
10186                 break;
10187         default:
10188                 return (ISC_FALSE);
10189         }
10190 
10191         /*
10192          * When sending from any the kernel will assign a source address
10193          * that matches the destination address.
10194          */
10195         if (isc_sockaddr_eqaddr(&any, &src))
10196                 src = *dst;
10197 
10198         isc_netaddr_fromsockaddr(&dstaddr, dst);
10199         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
10200         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
10201                 return (ISC_FALSE);
10202         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
10203                                 zone->isselfarg);
10204         if (key != NULL)
10205                 dns_tsigkey_detach(&key);
10206         return (isself);
10207 }
10208 
10209 static void
10210 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
10211         isc_mem_t *mctx;
10212 
10213         REQUIRE(DNS_NOTIFY_VALID(notify));
10214 
10215         if (notify->zone != NULL) {
10216                 if (!locked)
10217                         LOCK_ZONE(notify->zone);
10218                 REQUIRE(LOCKED_ZONE(notify->zone));
10219                 if (ISC_LINK_LINKED(notify, link))
10220                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
10221                 if (!locked)
10222                         UNLOCK_ZONE(notify->zone);
10223                 if (locked)
10224                         zone_idetach(&notify->zone);
10225                 else
10226                         dns_zone_idetach(&notify->zone);
10227         }
10228         if (notify->find != NULL)
10229                 dns_adb_destroyfind(&notify->find);
10230         if (notify->request != NULL)
10231                 dns_request_destroy(&notify->request);
10232         if (dns_name_dynamic(&notify->ns))
10233                 dns_name_free(&notify->ns, notify->mctx);
10234         if (notify->key != NULL)
10235                 dns_tsigkey_detach(&notify->key);
10236         mctx = notify->mctx;
10237         isc_mem_put(notify->mctx, notify, sizeof(*notify));
10238         isc_mem_detach(&mctx);
10239 }
10240 
10241 static isc_result_t
10242 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
10243         dns_notify_t *notify;
10244 
10245         REQUIRE(notifyp != NULL && *notifyp == NULL);
10246 
10247         notify = isc_mem_get(mctx, sizeof(*notify));
10248         if (notify == NULL)
10249                 return (ISC_R_NOMEMORY);
10250 
10251         notify->mctx = NULL;
10252         isc_mem_attach(mctx, &notify->mctx);
10253         notify->flags = flags;
10254         notify->zone = NULL;
10255         notify->find = NULL;
10256         notify->request = NULL;
10257         notify->key = NULL;
10258         notify->event = NULL;
10259         isc_sockaddr_any(&notify->dst);
10260         dns_name_init(&notify->ns, NULL);
10261         ISC_LINK_INIT(notify, link);
10262         notify->magic = NOTIFY_MAGIC;
10263         *notifyp = notify;
10264         return (ISC_R_SUCCESS);
10265 }
10266 
10267 /*
10268  * XXXAG should check for DNS_ZONEFLG_EXITING
10269  */
10270 static void
10271 process_adb_event(isc_task_t *task, isc_event_t *ev) {
10272         dns_notify_t *notify;
10273         isc_eventtype_t result;
10274 
10275         UNUSED(task);
10276 
10277         notify = ev->ev_arg;
10278         REQUIRE(DNS_NOTIFY_VALID(notify));
10279         INSIST(task == notify->zone->task);
10280         result = ev->ev_type;
10281         isc_event_free(&ev);
10282         if (result == DNS_EVENT_ADBMOREADDRESSES) {
10283                 dns_adb_destroyfind(&notify->find);
10284                 notify_find_address(notify);
10285                 return;
10286         }
10287         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
10288                 LOCK_ZONE(notify->zone);
10289                 notify_send(notify);
10290                 UNLOCK_ZONE(notify->zone);
10291         }
10292         notify_destroy(notify, ISC_FALSE);
10293 }
10294 
10295 static void
10296 notify_find_address(dns_notify_t *notify) {
10297         isc_result_t result;
10298         unsigned int options;
10299 
10300         REQUIRE(DNS_NOTIFY_VALID(notify));
10301         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
10302                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
10303 
10304         if (notify->zone->view->adb == NULL)
10305                 goto destroy;
10306 
10307         result = dns_adb_createfind(notify->zone->view->adb,
10308                                     notify->zone->task,
10309                                     process_adb_event, notify,
10310                                     &notify->ns, dns_rootname, 0,
10311                                     options, 0, NULL,
10312                                     notify->zone->view->dstport,
10313                                     &notify->find);
10314 
10315         /* Something failed? */
10316         if (result != ISC_R_SUCCESS)
10317                 goto destroy;
10318 
10319         /* More addresses pending? */
10320         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
10321                 return;
10322 
10323         /* We have as many addresses as we can get. */
10324         LOCK_ZONE(notify->zone);
10325         notify_send(notify);
10326         UNLOCK_ZONE(notify->zone);
10327 
10328  destroy:
10329         notify_destroy(notify, ISC_FALSE);
10330 }
10331 
10332 
10333 static isc_result_t
10334 notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) {
10335         isc_event_t *e;
10336         isc_result_t result;
10337 
10338         INSIST(notify->event == NULL);
10339         e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
10340                                notify_send_toaddr, notify, sizeof(isc_event_t));
10341         if (e == NULL)
10342                 return (ISC_R_NOMEMORY);
10343         if (startup)
10344                 notify->event = e;
10345         e->ev_arg = notify;
10346         e->ev_sender = NULL;
10347         result = isc_ratelimiter_enqueue(startup
10348                                           ? notify->zone->zmgr->startupnotifyrl
10349                                           : notify->zone->zmgr->notifyrl,
10350                                          notify->zone->task, &e);
10351         if (result != ISC_R_SUCCESS) {
10352                 isc_event_free(&e);
10353                 notify->event = NULL;
10354         }
10355         return (result);
10356 }
10357 
10358 static void
10359 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
10360         dns_notify_t *notify;
10361         isc_result_t result;
10362         dns_message_t *message = NULL;
10363         isc_netaddr_t dstip;
10364         dns_tsigkey_t *key = NULL;
10365         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
10366         isc_sockaddr_t src;
10367         unsigned int options, timeout;
10368         isc_boolean_t have_notifysource = ISC_FALSE;
10369         isc_boolean_t have_notifydscp = ISC_FALSE;
10370         isc_dscp_t dscp = -1;
10371 
10372         notify = event->ev_arg;
10373         REQUIRE(DNS_NOTIFY_VALID(notify));
10374 
10375         UNUSED(task);
10376 
10377         LOCK_ZONE(notify->zone);
10378 
10379         notify->event = NULL;
10380 
10381         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
10382                 result = ISC_R_CANCELED;
10383                 goto cleanup;
10384         }
10385 
10386         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
10387             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
10388             notify->zone->view->requestmgr == NULL ||
10389             notify->zone->db == NULL) {
10390                 result = ISC_R_CANCELED;
10391                 goto cleanup;
10392         }
10393 
10394         /*
10395          * The raw IPv4 address should also exist.  Don't send to the
10396          * mapped form.
10397          */
10398         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
10399             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
10400                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
10401                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
10402                            "notify: ignoring IPv6 mapped IPV4 address: %s",
10403                            addrbuf);
10404                 result = ISC_R_CANCELED;
10405                 goto cleanup;
10406         }
10407 
10408         result = notify_createmessage(notify->zone, notify->flags, &message);
10409         if (result != ISC_R_SUCCESS)
10410                 goto cleanup;
10411 
10412         if (notify->key != NULL) {
10413                 /* Transfer ownership of key */
10414                 key = notify->key;
10415                 notify->key = NULL;
10416         } else {
10417                 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
10418                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
10419                 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
10420                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10421                         notify_log(notify->zone, ISC_LOG_ERROR,
10422                                    "NOTIFY to %s not sent. "
10423                                    "Peer TSIG key lookup failure.", addrbuf);
10424                         goto cleanup_message;
10425                 }
10426         }
10427 
10428         /* XXX: should we log the tsig key too? */
10429         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
10430                    addrbuf);
10431         options = 0;
10432         if (notify->zone->view->peers != NULL) {
10433                 dns_peer_t *peer = NULL;
10434                 isc_boolean_t usetcp = ISC_FALSE;
10435                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
10436                                                  &dstip, &peer);
10437                 if (result == ISC_R_SUCCESS) {
10438                         result = dns_peer_getnotifysource(peer, &src);
10439                         if (result == ISC_R_SUCCESS)
10440                                 have_notifysource = ISC_TRUE;
10441                         dns_peer_getnotifydscp(peer, &dscp);
10442                         if (dscp != -1)
10443                                 have_notifydscp = ISC_TRUE;
10444                         result = dns_peer_getforcetcp(peer, &usetcp);
10445                         if (result == ISC_R_SUCCESS && usetcp)
10446                                 options |= DNS_FETCHOPT_TCP;
10447                 }
10448         }
10449         switch (isc_sockaddr_pf(&notify->dst)) {
10450         case PF_INET:
10451                 if (!have_notifysource)
10452                         src = notify->zone->notifysrc4;
10453                 if (!have_notifydscp)
10454                         dscp = notify->zone->notifysrc4dscp;
10455                 break;
10456         case PF_INET6:
10457                 if (!have_notifysource)
10458                         src = notify->zone->notifysrc6;
10459                 if (!have_notifydscp)
10460                         dscp = notify->zone->notifysrc6dscp;
10461                 break;
10462         default:
10463                 result = ISC_R_NOTIMPLEMENTED;
10464                 goto cleanup_key;
10465         }
10466         timeout = 15;
10467         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
10468                 timeout = 30;
10469         result = dns_request_createvia4(notify->zone->view->requestmgr,
10470                                         message, &src, &notify->dst, dscp,
10471                                         options, key, timeout * 3, timeout,
10472                                         0, notify->zone->task, notify_done,
10473                                         notify, &notify->request);
10474         if (result == ISC_R_SUCCESS) {
10475                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
10476                         inc_stats(notify->zone,
10477                                   dns_zonestatscounter_notifyoutv4);
10478                 } else {
10479                         inc_stats(notify->zone,
10480                                   dns_zonestatscounter_notifyoutv6);
10481                 }
10482         }
10483 
10484  cleanup_key:
10485         if (key != NULL)
10486                 dns_tsigkey_detach(&key);
10487  cleanup_message:
10488         dns_message_destroy(&message);
10489  cleanup:
10490         UNLOCK_ZONE(notify->zone);
10491         isc_event_free(&event);
10492         if (result != ISC_R_SUCCESS)
10493                 notify_destroy(notify, ISC_FALSE);
10494 }
10495 
10496 static void
10497 notify_send(dns_notify_t *notify) {
10498         dns_adbaddrinfo_t *ai;
10499         isc_sockaddr_t dst;
10500         isc_result_t result;
10501         dns_notify_t *new = NULL;
10502         unsigned int flags;
10503         isc_boolean_t startup;
10504 
10505         /*
10506          * Zone lock held by caller.
10507          */
10508         REQUIRE(DNS_NOTIFY_VALID(notify));
10509         REQUIRE(LOCKED_ZONE(notify->zone));
10510 
10511         for (ai = ISC_LIST_HEAD(notify->find->list);
10512              ai != NULL;
10513              ai = ISC_LIST_NEXT(ai, publink)) {
10514                 dst = ai->sockaddr;
10515                 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
10516                                     NULL))
10517                         continue;
10518                 if (notify_isself(notify->zone, &dst))
10519                         continue;
10520                 new = NULL;
10521                 flags = notify->flags & DNS_NOTIFY_NOSOA;
10522                 result = notify_create(notify->mctx, flags, &new);
10523                 if (result != ISC_R_SUCCESS)
10524                         goto cleanup;
10525                 zone_iattach(notify->zone, &new->zone);
10526                 ISC_LIST_APPEND(new->zone->notifies, new, link);
10527                 new->dst = dst;
10528                 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
10529                 result = notify_send_queue(new, startup);
10530                 if (result != ISC_R_SUCCESS)
10531                         goto cleanup;
10532                 new = NULL;
10533         }
10534 
10535  cleanup:
10536         if (new != NULL)
10537                 notify_destroy(new, ISC_TRUE);
10538 }
10539 
10540 void
10541 dns_zone_notify(dns_zone_t *zone) {
10542         isc_time_t now;
10543 
10544         REQUIRE(DNS_ZONE_VALID(zone));
10545 
10546         LOCK_ZONE(zone);
10547         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10548 
10549         TIME_NOW(&now);
10550         zone_settimer(zone, &now);
10551         UNLOCK_ZONE(zone);
10552 }
10553 
10554 static void
10555 zone_notify(dns_zone_t *zone, isc_time_t *now) {
10556         dns_dbnode_t *node = NULL;
10557         dns_db_t *zonedb = NULL;
10558         dns_dbversion_t *version = NULL;
10559         dns_name_t *origin = NULL;
10560         dns_name_t master;
10561         dns_rdata_ns_t ns;
10562         dns_rdata_soa_t soa;
10563         isc_uint32_t serial;
10564         dns_rdata_t rdata = DNS_RDATA_INIT;
10565         dns_rdataset_t nsrdset;
10566         dns_rdataset_t soardset;
10567         isc_result_t result;
10568         unsigned int i;
10569         isc_sockaddr_t dst;
10570         isc_boolean_t isqueued;
10571         dns_notifytype_t notifytype;
10572         unsigned int flags = 0;
10573         isc_boolean_t loggednotify = ISC_FALSE;
10574         isc_boolean_t startup;
10575 
10576         REQUIRE(DNS_ZONE_VALID(zone));
10577 
10578         LOCK_ZONE(zone);
10579         startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10580         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10581         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
10582         notifytype = zone->notifytype;
10583         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
10584         UNLOCK_ZONE(zone);
10585 
10586         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
10587                 return;
10588 
10589         if (notifytype == dns_notifytype_no)
10590                 return;
10591 
10592         if (notifytype == dns_notifytype_masteronly &&
10593             zone->type != dns_zone_master)
10594                 return;
10595 
10596         origin = &zone->origin;
10597 
10598         /*
10599          * If the zone is dialup we are done as we don't want to send
10600          * the current soa so as to force a refresh query.
10601          */
10602         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
10603                 flags |= DNS_NOTIFY_NOSOA;
10604 
10605         /*
10606          * Record that this was a notify due to starting up.
10607          */
10608         if (startup)
10609                 flags |= DNS_NOTIFY_STARTUP;
10610 
10611         /*
10612          * Get SOA RRset.
10613          */
10614         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10615         if (zone->db != NULL)
10616                 dns_db_attach(zone->db, &zonedb);
10617         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10618         if (zonedb == NULL)
10619                 return;
10620         dns_db_currentversion(zonedb, &version);
10621         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
10622         if (result != ISC_R_SUCCESS)
10623                 goto cleanup1;
10624 
10625         dns_rdataset_init(&soardset);
10626         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
10627                                      dns_rdatatype_none, 0, &soardset, NULL);
10628         if (result != ISC_R_SUCCESS)
10629                 goto cleanup2;
10630 
10631         /*
10632          * Find serial and master server's name.
10633          */
10634         dns_name_init(&master, NULL);
10635         result = dns_rdataset_first(&soardset);
10636         if (result != ISC_R_SUCCESS)
10637                 goto cleanup3;
10638         dns_rdataset_current(&soardset, &rdata);
10639         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10640         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10641         dns_rdata_reset(&rdata);
10642         result = dns_name_dup(&soa.origin, zone->mctx, &master);
10643         serial = soa.serial;
10644         dns_rdataset_disassociate(&soardset);
10645         if (result != ISC_R_SUCCESS)
10646                 goto cleanup3;
10647 
10648         /*
10649          * Enqueue notify requests for 'also-notify' servers.
10650          */
10651         LOCK_ZONE(zone);
10652         for (i = 0; i < zone->notifycnt; i++) {
10653                 dns_tsigkey_t *key = NULL;
10654                 dns_notify_t *notify = NULL;
10655 
10656                 if ((zone->notifykeynames != NULL) &&
10657                     (zone->notifykeynames[i] != NULL)) {
10658                         dns_view_t *view = dns_zone_getview(zone);
10659                         dns_name_t *keyname = zone->notifykeynames[i];
10660                         (void)dns_view_gettsig(view, keyname, &key);
10661                 }
10662 
10663                 dst = zone->notify[i];
10664                 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
10665                         if (key != NULL)
10666                                 dns_tsigkey_detach(&key);
10667                         continue;
10668                 }
10669 
10670                 result = notify_create(zone->mctx, flags, &notify);
10671                 if (result != ISC_R_SUCCESS) {
10672                         if (key != NULL)
10673                                 dns_tsigkey_detach(&key);
10674                         continue;
10675                 }
10676 
10677                 zone_iattach(zone, &notify->zone);
10678                 notify->dst = dst;
10679 
10680                 INSIST(notify->key == NULL);
10681 
10682                 if (key != NULL) {
10683                         notify->key = key;
10684                         key = NULL;
10685                 }
10686 
10687                 ISC_LIST_APPEND(zone->notifies, notify, link);
10688                 result = notify_send_queue(notify, startup);
10689                 if (result != ISC_R_SUCCESS)
10690                         notify_destroy(notify, ISC_TRUE);
10691                 if (!loggednotify) {
10692                         notify_log(zone, ISC_LOG_INFO,
10693                                    "sending notifies (serial %u)",
10694                                    serial);
10695                         loggednotify = ISC_TRUE;
10696                 }
10697         }
10698         UNLOCK_ZONE(zone);
10699 
10700         if (notifytype == dns_notifytype_explicit)
10701                 goto cleanup3;
10702 
10703         /*
10704          * Process NS RRset to generate notifies.
10705          */
10706 
10707         dns_rdataset_init(&nsrdset);
10708         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10709                                      dns_rdatatype_none, 0, &nsrdset, NULL);
10710         if (result != ISC_R_SUCCESS)
10711                 goto cleanup3;
10712 
10713         result = dns_rdataset_first(&nsrdset);
10714         while (result == ISC_R_SUCCESS) {
10715                 dns_notify_t *notify = NULL;
10716 
10717                 dns_rdataset_current(&nsrdset, &rdata);
10718                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10719                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10720                 dns_rdata_reset(&rdata);
10721                 /*
10722                  * Don't notify the master server unless explicitly
10723                  * configured to do so.
10724                  */
10725                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10726                     dns_name_compare(&master, &ns.name) == 0) {
10727                         result = dns_rdataset_next(&nsrdset);
10728                         continue;
10729                 }
10730 
10731                 if (!loggednotify) {
10732                         notify_log(zone, ISC_LOG_INFO,
10733                                    "sending notifies (serial %u)",
10734                                    serial);
10735                         loggednotify = ISC_TRUE;
10736                 }
10737 
10738                 LOCK_ZONE(zone);
10739                 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
10740                 UNLOCK_ZONE(zone);
10741                 if (isqueued) {
10742                         result = dns_rdataset_next(&nsrdset);
10743                         continue;
10744                 }
10745                 result = notify_create(zone->mctx, flags, &notify);
10746                 if (result != ISC_R_SUCCESS)
10747                         continue;
10748                 dns_zone_iattach(zone, &notify->zone);
10749                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10750                 if (result != ISC_R_SUCCESS) {
10751                         LOCK_ZONE(zone);
10752                         notify_destroy(notify, ISC_TRUE);
10753                         UNLOCK_ZONE(zone);
10754                         continue;
10755                 }
10756                 LOCK_ZONE(zone);
10757                 ISC_LIST_APPEND(zone->notifies, notify, link);
10758                 UNLOCK_ZONE(zone);
10759                 notify_find_address(notify);
10760                 result = dns_rdataset_next(&nsrdset);
10761         }
10762         dns_rdataset_disassociate(&nsrdset);
10763 
10764  cleanup3:
10765         if (dns_name_dynamic(&master))
10766                 dns_name_free(&master, zone->mctx);
10767  cleanup2:
10768         dns_db_detachnode(zonedb, &node);
10769  cleanup1:
10770         dns_db_closeversion(zonedb, &version, ISC_FALSE);
10771         dns_db_detach(&zonedb);
10772 }
10773 
10774 /***
10775  *** Private
10776  ***/
10777 
10778 static inline isc_result_t
10779 save_nsrrset(dns_message_t *message, dns_name_t *name,
10780              dns_db_t *db, dns_dbversion_t *version)
10781 {
10782         dns_rdataset_t *nsrdataset = NULL;
10783         dns_rdataset_t *rdataset = NULL;
10784         dns_dbnode_t *node = NULL;
10785         dns_rdata_ns_t ns;
10786         isc_result_t result;
10787         dns_rdata_t rdata = DNS_RDATA_INIT;
10788 
10789         /*
10790          * Extract NS RRset from message.
10791          */
10792         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10793                                       dns_rdatatype_ns, dns_rdatatype_none,
10794                                       NULL, &nsrdataset);
10795         if (result != ISC_R_SUCCESS)
10796                 goto fail;
10797 
10798         /*
10799          * Add NS rdataset.
10800          */
10801         result = dns_db_findnode(db, name, ISC_TRUE, &node);
10802         if (result != ISC_R_SUCCESS)
10803                 goto fail;
10804         result = dns_db_addrdataset(db, node, version, 0,
10805                                     nsrdataset, 0, NULL);
10806         dns_db_detachnode(db, &node);
10807         if (result != ISC_R_SUCCESS)
10808                 goto fail;
10809         /*
10810          * Add glue rdatasets.
10811          */
10812         for (result = dns_rdataset_first(nsrdataset);
10813              result == ISC_R_SUCCESS;
10814              result = dns_rdataset_next(nsrdataset)) {
10815                 dns_rdataset_current(nsrdataset, &rdata);
10816                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10817                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10818                 dns_rdata_reset(&rdata);
10819                 if (!dns_name_issubdomain(&ns.name, name))
10820                         continue;
10821                 rdataset = NULL;
10822                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10823                                               &ns.name, dns_rdatatype_aaaa,
10824                                               dns_rdatatype_none, NULL,
10825                                               &rdataset);
10826                 if (result == ISC_R_SUCCESS) {
10827                         result = dns_db_findnode(db, &ns.name,
10828                                                  ISC_TRUE, &node);
10829                         if (result != ISC_R_SUCCESS)
10830                                 goto fail;
10831                         result = dns_db_addrdataset(db, node, version, 0,
10832                                                     rdataset, 0, NULL);
10833                         dns_db_detachnode(db, &node);
10834                         if (result != ISC_R_SUCCESS)
10835                                 goto fail;
10836                 }
10837                 rdataset = NULL;
10838                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10839                                               &ns.name, dns_rdatatype_a,
10840                                               dns_rdatatype_none, NULL,
10841                                               &rdataset);
10842                 if (result == ISC_R_SUCCESS) {
10843                         result = dns_db_findnode(db, &ns.name,
10844                                                  ISC_TRUE, &node);
10845                         if (result != ISC_R_SUCCESS)
10846                                 goto fail;
10847                         result = dns_db_addrdataset(db, node, version, 0,
10848                                                     rdataset, 0, NULL);
10849                         dns_db_detachnode(db, &node);
10850                         if (result != ISC_R_SUCCESS)
10851                                 goto fail;
10852                 }
10853         }
10854         if (result != ISC_R_NOMORE)
10855                 goto fail;
10856 
10857         return (ISC_R_SUCCESS);
10858 
10859 fail:
10860         return (result);
10861 }
10862 
10863 static void
10864 stub_callback(isc_task_t *task, isc_event_t *event) {
10865         const char me[] = "stub_callback";
10866         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10867         dns_stub_t *stub = NULL;
10868         dns_message_t *msg = NULL;
10869         dns_zone_t *zone = NULL;
10870         char master[ISC_SOCKADDR_FORMATSIZE];
10871         char source[ISC_SOCKADDR_FORMATSIZE];
10872         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10873         isc_result_t result;
10874         isc_time_t now;
10875         isc_boolean_t exiting = ISC_FALSE;
10876         isc_interval_t i;
10877         unsigned int j, soacount;
10878 
10879         stub = revent->ev_arg;
10880         INSIST(DNS_STUB_VALID(stub));
10881 
10882         UNUSED(task);
10883 
10884         zone = stub->zone;
10885 
10886         ENTER;
10887 
10888         TIME_NOW(&now);
10889 
10890         LOCK_ZONE(zone);
10891 
10892         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10893                 zone_debuglog(zone, me, 1, "exiting");
10894                 exiting = ISC_TRUE;
10895                 goto next_master;
10896         }
10897 
10898         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10899         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10900 
10901         if (revent->result != ISC_R_SUCCESS) {
10902                 if (revent->result == ISC_R_TIMEDOUT &&
10903                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10904                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10905                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10906                                      "refreshing stub: timeout retrying "
10907                                      " without EDNS master %s (source %s)",
10908                                      master, source);
10909                         goto same_master;
10910                 }
10911                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10912                                            &zone->sourceaddr, &now);
10913                 dns_zone_log(zone, ISC_LOG_INFO,
10914                              "could not refresh stub from master %s"
10915                              " (source %s): %s", master, source,
10916                              dns_result_totext(revent->result));
10917                 goto next_master;
10918         }
10919 
10920         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10921         if (result != ISC_R_SUCCESS)
10922                 goto next_master;
10923 
10924         result = dns_request_getresponse(revent->request, msg, 0);
10925         if (result != ISC_R_SUCCESS)
10926                 goto next_master;
10927 
10928         /*
10929          * Unexpected rcode.
10930          */
10931         if (msg->rcode != dns_rcode_noerror) {
10932                 char rcode[128];
10933                 isc_buffer_t rb;
10934 
10935                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10936                 (void)dns_rcode_totext(msg->rcode, &rb);
10937 
10938                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10939                     (msg->rcode == dns_rcode_servfail ||
10940                      msg->rcode == dns_rcode_notimp ||
10941                      msg->rcode == dns_rcode_formerr)) {
10942                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10943                                      "refreshing stub: rcode (%.*s) retrying "
10944                                      "without EDNS master %s (source %s)",
10945                                      (int)rb.used, rcode, master, source);
10946                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10947                         goto same_master;
10948                 }
10949 
10950                 dns_zone_log(zone, ISC_LOG_INFO,
10951                              "refreshing stub: "
10952                              "unexpected rcode (%.*s) from %s (source %s)",
10953                              (int)rb.used, rcode, master, source);
10954                 goto next_master;
10955         }
10956 
10957         /*
10958          * We need complete messages.
10959          */
10960         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10961                 if (dns_request_usedtcp(revent->request)) {
10962                         dns_zone_log(zone, ISC_LOG_INFO,
10963                                      "refreshing stub: truncated TCP "
10964                                      "response from master %s (source %s)",
10965                                      master, source);
10966                         goto next_master;
10967                 }
10968                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10969                 goto same_master;
10970         }
10971 
10972         /*
10973          * If non-auth log and next master.
10974          */
10975         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10976                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10977                              "non-authoritative answer from "
10978                              "master %s (source %s)", master, source);
10979                 goto next_master;
10980         }
10981 
10982         /*
10983          * Sanity checks.
10984          */
10985         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10986         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10987 
10988         if (cnamecnt != 0) {
10989                 dns_zone_log(zone, ISC_LOG_INFO,
10990                              "refreshing stub: unexpected CNAME response "
10991                              "from master %s (source %s)", master, source);
10992                 goto next_master;
10993         }
10994 
10995         if (nscnt == 0) {
10996                 dns_zone_log(zone, ISC_LOG_INFO,
10997                              "refreshing stub: no NS records in response "
10998                              "from master %s (source %s)", master, source);
10999                 goto next_master;
11000         }
11001 
11002         /*
11003          * Save answer.
11004          */
11005         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
11006         if (result != ISC_R_SUCCESS) {
11007                 dns_zone_log(zone, ISC_LOG_INFO,
11008                              "refreshing stub: unable to save NS records "
11009                              "from master %s (source %s)", master, source);
11010                 goto next_master;
11011         }
11012 
11013         /*
11014          * Tidy up.
11015          */
11016         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
11017         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11018         if (zone->db == NULL)
11019                 zone_attachdb(zone, stub->db);
11020         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
11021                                   &refresh, &retry, &expire, NULL, NULL);
11022         if (result == ISC_R_SUCCESS && soacount > 0U) {
11023                 zone->refresh = RANGE(refresh, zone->minrefresh,
11024                                       zone->maxrefresh);
11025                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
11026                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
11027                                      DNS_MAX_EXPIRE);
11028                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11029         }
11030         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11031         dns_db_detach(&stub->db);
11032 
11033         dns_message_destroy(&msg);
11034         isc_event_free(&event);
11035         dns_request_destroy(&zone->request);
11036 
11037         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11038         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11039         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
11040         isc_interval_set(&i, zone->expire, 0);
11041         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
11042 
11043         if (zone->masterfile != NULL)
11044                 zone_needdump(zone, 0);
11045 
11046         zone_settimer(zone, &now);
11047         goto free_stub;
11048 
11049  next_master:
11050         if (stub->version != NULL)
11051                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
11052         if (stub->db != NULL)
11053                 dns_db_detach(&stub->db);
11054         if (msg != NULL)
11055                 dns_message_destroy(&msg);
11056         isc_event_free(&event);
11057         dns_request_destroy(&zone->request);
11058         /*
11059          * Skip to next failed / untried master.
11060          */
11061         do {
11062                 zone->curmaster++;
11063         } while (zone->curmaster < zone->masterscnt &&
11064                  zone->mastersok[zone->curmaster]);
11065         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11066         if (exiting || zone->curmaster >= zone->masterscnt) {
11067                 isc_boolean_t done = ISC_TRUE;
11068                 if (!exiting &&
11069                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11070                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11071                         /*
11072                          * Did we get a good answer from all the masters?
11073                          */
11074                         for (j = 0; j < zone->masterscnt; j++)
11075                                 if (zone->mastersok[j] == ISC_FALSE) {
11076                                         done = ISC_FALSE;
11077                                         break;
11078                                 }
11079                 } else
11080                         done = ISC_TRUE;
11081                 if (!done) {
11082                         zone->curmaster = 0;
11083                         /*
11084                          * Find the next failed master.
11085                          */
11086                         while (zone->curmaster < zone->masterscnt &&
11087                                zone->mastersok[zone->curmaster])
11088                                 zone->curmaster++;
11089                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11090                 } else {
11091                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11092 
11093                         zone_settimer(zone, &now);
11094                         goto free_stub;
11095                 }
11096         }
11097         queue_soa_query(zone);
11098         goto free_stub;
11099 
11100  same_master:
11101         if (msg != NULL)
11102                 dns_message_destroy(&msg);
11103         isc_event_free(&event);
11104         dns_request_destroy(&zone->request);
11105         ns_query(zone, NULL, stub);
11106         UNLOCK_ZONE(zone);
11107         goto done;
11108 
11109  free_stub:
11110         UNLOCK_ZONE(zone);
11111         stub->magic = 0;
11112         dns_zone_idetach(&stub->zone);
11113         INSIST(stub->db == NULL);
11114         INSIST(stub->version == NULL);
11115         isc_mem_put(stub->mctx, stub, sizeof(*stub));
11116 
11117  done:
11118         INSIST(event == NULL);
11119         return;
11120 }
11121 
11122 /*
11123  * Get the EDNS EXPIRE option from the response and if it exists trim
11124  * expire to be not more than it.
11125  */
11126 static void
11127 get_edns_expire(dns_zone_t * zone, dns_message_t *message,
11128                 isc_uint32_t *expirep)
11129 {
11130         isc_result_t result;
11131         isc_uint32_t expire;
11132         dns_rdata_t rdata = DNS_RDATA_INIT;
11133         isc_buffer_t optbuf;
11134         isc_uint16_t optcode;
11135         isc_uint16_t optlen;
11136 
11137         REQUIRE(expirep != NULL);
11138         REQUIRE(message != NULL);
11139 
11140         if (message->opt == NULL)
11141                 return;
11142 
11143         result = dns_rdataset_first(message->opt);
11144         if (result == ISC_R_SUCCESS) {
11145                 dns_rdataset_current(message->opt, &rdata);
11146                 isc_buffer_init(&optbuf, rdata.data, rdata.length);
11147                 isc_buffer_add(&optbuf, rdata.length);
11148                 while (isc_buffer_remaininglength(&optbuf) >= 4) {
11149                         optcode = isc_buffer_getuint16(&optbuf);
11150                         optlen = isc_buffer_getuint16(&optbuf);
11151                         /*
11152                          * A EDNS EXPIRE response has a length of 4.
11153                          */
11154                         if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
11155                                 isc_buffer_forward(&optbuf, optlen);
11156                                 continue;
11157                         }
11158                         expire = isc_buffer_getuint32(&optbuf);
11159                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
11160                                      "got EDNS EXPIRE of %u\n", expire);
11161                         /*
11162                          * Trim *expirep?
11163                          */
11164                         if (expire < *expirep)
11165                                 *expirep = expire;
11166                         break;
11167                 }
11168         }
11169 }
11170 
11171 /*
11172  * Set the file modification time zone->expire seconds before expiretime.
11173  */
11174 static void
11175 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
11176         isc_result_t result;
11177         isc_time_t when;
11178         isc_interval_t i;
11179 
11180         isc_interval_set(&i, zone->expire, 0);
11181         result = isc_time_subtract(expiretime, &i, &when);
11182         if (result != ISC_R_SUCCESS)
11183                 return;
11184 
11185         result = ISC_R_FAILURE;
11186         if (zone->journal != NULL)
11187                 result = isc_file_settime(zone->journal, &when);
11188         if (result == ISC_R_SUCCESS &&
11189             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11190             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11191                 result = isc_file_settime(zone->masterfile, &when);
11192         else if (result != ISC_R_SUCCESS)
11193                 result = isc_file_settime(zone->masterfile, &when);
11194 
11195         /*
11196          * Someone removed the file from underneath us!
11197          */
11198         if (result == ISC_R_FILENOTFOUND) {
11199                 zone_needdump(zone, DNS_DUMP_DELAY);
11200         } else if (result != ISC_R_SUCCESS)
11201                 dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
11202                              "file modification time of '%s': %s",
11203                              zone->masterfile, dns_result_totext(result));
11204 }
11205 
11206 /*
11207  * An SOA query has finished (successfully or not).
11208  */
11209 static void
11210 refresh_callback(isc_task_t *task, isc_event_t *event) {
11211         const char me[] = "refresh_callback";
11212         dns_requestevent_t *revent = (dns_requestevent_t *)event;
11213         dns_zone_t *zone;
11214         dns_message_t *msg = NULL;
11215         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
11216         isc_time_t now;
11217         char master[ISC_SOCKADDR_FORMATSIZE];
11218         char source[ISC_SOCKADDR_FORMATSIZE];
11219         dns_rdataset_t *rdataset = NULL;
11220         dns_rdata_t rdata = DNS_RDATA_INIT;
11221         dns_rdata_soa_t soa;
11222         isc_result_t result;
11223         isc_uint32_t serial, oldserial = 0;
11224         unsigned int j;
11225         isc_boolean_t do_queue_xfrin = ISC_FALSE;
11226 
11227         zone = revent->ev_arg;
11228         INSIST(DNS_ZONE_VALID(zone));
11229 
11230         UNUSED(task);
11231 
11232         ENTER;
11233 
11234         TIME_NOW(&now);
11235 
11236         LOCK_ZONE(zone);
11237 
11238         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11239                 isc_event_free(&event);
11240                 dns_request_destroy(&zone->request);
11241                 goto detach;
11242         }
11243 
11244         /*
11245          * if timeout log and next master;
11246          */
11247 
11248         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11249         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11250 
11251         if (revent->result != ISC_R_SUCCESS) {
11252                 if (revent->result == ISC_R_TIMEDOUT &&
11253                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11254                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11255                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
11256                                      "refresh: timeout retrying without EDNS "
11257                                      "master %s (source %s)", master, source);
11258                         goto same_master;
11259                 }
11260                 if (revent->result == ISC_R_TIMEDOUT &&
11261                     !dns_request_usedtcp(revent->request)) {
11262                         dns_zone_log(zone, ISC_LOG_INFO,
11263                                      "refresh: retry limit for "
11264                                      "master %s exceeded (source %s)",
11265                                      master, source);
11266                         /* Try with slave with TCP. */
11267                         if ((zone->type == dns_zone_slave ||
11268                              zone->type == dns_zone_redirect) &&
11269                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
11270                                 if (!dns_zonemgr_unreachable(zone->zmgr,
11271                                                              &zone->masteraddr,
11272                                                              &zone->sourceaddr,
11273                                                              &now))
11274                                 {
11275                                         DNS_ZONE_SETFLAG(zone,
11276                                                      DNS_ZONEFLG_SOABEFOREAXFR);
11277                                         goto tcp_transfer;
11278                                 }
11279                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11280                                              "refresh: skipped tcp fallback "
11281                                              "as master %s (source %s) is "
11282                                              "unreachable (cached)",
11283                                               master, source);
11284                         }
11285                 } else
11286                         dns_zone_log(zone, ISC_LOG_INFO,
11287                                      "refresh: failure trying master "
11288                                      "%s (source %s): %s", master, source,
11289                                      dns_result_totext(revent->result));
11290                 goto next_master;
11291         }
11292 
11293         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
11294         if (result != ISC_R_SUCCESS)
11295                 goto next_master;
11296         result = dns_request_getresponse(revent->request, msg, 0);
11297         if (result != ISC_R_SUCCESS) {
11298                 dns_zone_log(zone, ISC_LOG_INFO,
11299                              "refresh: failure trying master "
11300                              "%s (source %s): %s", master, source,
11301                              dns_result_totext(result));
11302                 goto next_master;
11303         }
11304 
11305         /*
11306          * Unexpected rcode.
11307          */
11308         if (msg->rcode != dns_rcode_noerror) {
11309                 char rcode[128];
11310                 isc_buffer_t rb;
11311 
11312                 isc_buffer_init(&rb, rcode, sizeof(rcode));
11313                 (void)dns_rcode_totext(msg->rcode, &rb);
11314 
11315                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11316                     (msg->rcode == dns_rcode_servfail ||
11317                      msg->rcode == dns_rcode_notimp ||
11318                      msg->rcode == dns_rcode_formerr)) {
11319                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
11320                                      "refresh: rcode (%.*s) retrying without "
11321                                      "EDNS master %s (source %s)",
11322                                      (int)rb.used, rcode, master, source);
11323                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11324                         goto same_master;
11325                 }
11326                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11327                     msg->rcode == dns_rcode_badvers) {
11328                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
11329                                      "refresh: rcode (%.*s) retrying without "
11330                                      "EDNS EXPIRE OPTION master %s (source %s)",
11331                                      (int)rb.used, rcode, master, source);
11332                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11333                         goto same_master;
11334                 }
11335                 dns_zone_log(zone, ISC_LOG_INFO,
11336                              "refresh: unexpected rcode (%.*s) from "
11337                              "master %s (source %s)", (int)rb.used, rcode,
11338                              master, source);
11339                 /*
11340                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
11341                  */
11342                 if (msg->rcode == dns_rcode_refused &&
11343                     (zone->type == dns_zone_slave ||
11344                      zone->type == dns_zone_redirect))
11345                         goto tcp_transfer;
11346                 goto next_master;
11347         }
11348 
11349         /*
11350          * If truncated punt to zone transfer which will query again.
11351          */
11352         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
11353                 if (zone->type == dns_zone_slave ||
11354                     zone->type == dns_zone_redirect) {
11355                         dns_zone_log(zone, ISC_LOG_INFO,
11356                                      "refresh: truncated UDP answer, "
11357                                      "initiating TCP zone xfer "
11358                                      "for master %s (source %s)",
11359                                      master, source);
11360                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
11361                         goto tcp_transfer;
11362                 } else {
11363                         INSIST(zone->type == dns_zone_stub);
11364                         if (dns_request_usedtcp(revent->request)) {
11365                                 dns_zone_log(zone, ISC_LOG_INFO,
11366                                              "refresh: truncated TCP response "
11367                                              "from master %s (source %s)",
11368                                              master, source);
11369                                 goto next_master;
11370                         }
11371                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
11372                         goto same_master;
11373                 }
11374         }
11375 
11376         /*
11377          * if non-auth log and next master;
11378          */
11379         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
11380                 dns_zone_log(zone, ISC_LOG_INFO,
11381                              "refresh: non-authoritative answer from "
11382                              "master %s (source %s)", master, source);
11383                 goto next_master;
11384         }
11385 
11386         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
11387         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
11388         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
11389         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
11390                                  dns_rdatatype_soa);
11391 
11392         /*
11393          * There should not be a CNAME record at top of zone.
11394          */
11395         if (cnamecnt != 0) {
11396                 dns_zone_log(zone, ISC_LOG_INFO,
11397                              "refresh: CNAME at top of zone "
11398                              "in master %s (source %s)", master, source);
11399                 goto next_master;
11400         }
11401 
11402         /*
11403          * if referral log and next master;
11404          */
11405         if (soacnt == 0 && soacount == 0 && nscount != 0) {
11406                 dns_zone_log(zone, ISC_LOG_INFO,
11407                              "refresh: referral response "
11408                              "from master %s (source %s)", master, source);
11409                 goto next_master;
11410         }
11411 
11412         /*
11413          * if nodata log and next master;
11414          */
11415         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
11416                 dns_zone_log(zone, ISC_LOG_INFO,
11417                              "refresh: NODATA response "
11418                              "from master %s (source %s)", master, source);
11419                 goto next_master;
11420         }
11421 
11422         /*
11423          * Only one soa at top of zone.
11424          */
11425         if (soacnt != 1) {
11426                 dns_zone_log(zone, ISC_LOG_INFO,
11427                              "refresh: answer SOA count (%d) != 1 "
11428                              "from master %s (source %s)",
11429                              soacnt, master, source);
11430                 goto next_master;
11431         }
11432 
11433         /*
11434          * Extract serial
11435          */
11436         rdataset = NULL;
11437         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
11438                                       dns_rdatatype_soa, dns_rdatatype_none,
11439                                       NULL, &rdataset);
11440         if (result != ISC_R_SUCCESS) {
11441                 dns_zone_log(zone, ISC_LOG_INFO,
11442                              "refresh: unable to get SOA record "
11443                              "from master %s (source %s)", master, source);
11444                 goto next_master;
11445         }
11446 
11447         result = dns_rdataset_first(rdataset);
11448         if (result != ISC_R_SUCCESS) {
11449                 dns_zone_log(zone, ISC_LOG_INFO,
11450                              "refresh: dns_rdataset_first() failed");
11451                 goto next_master;
11452         }
11453 
11454         dns_rdataset_current(rdataset, &rdata);
11455         result = dns_rdata_tostruct(&rdata, &soa, NULL);
11456         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11457 
11458         serial = soa.serial;
11459         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
11460                 unsigned int dbsoacount;
11461                 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
11462                                           &oldserial, NULL, NULL, NULL, NULL,
11463                                           NULL);
11464                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11465                 RUNTIME_CHECK(dbsoacount > 0U);
11466                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
11467                               serial, oldserial);
11468         } else
11469                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
11470                               serial);
11471 
11472         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
11473             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
11474             isc_serial_gt(serial, oldserial)) {
11475                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
11476                                             &zone->sourceaddr, &now))
11477                 {
11478                         dns_zone_log(zone, ISC_LOG_INFO,
11479                                      "refresh: skipping %s as master %s "
11480                                      "(source %s) is unreachable (cached)",
11481                                      (zone->type == dns_zone_slave ||
11482                                       zone->type == dns_zone_redirect) ?
11483                                      "zone transfer" : "NS query",
11484                                      master, source);
11485                         goto next_master;
11486                 }
11487  tcp_transfer:
11488                 isc_event_free(&event);
11489                 dns_request_destroy(&zone->request);
11490                 if (zone->type == dns_zone_slave ||
11491                     zone->type == dns_zone_redirect) {
11492                         do_queue_xfrin = ISC_TRUE;
11493                 } else {
11494                         INSIST(zone->type == dns_zone_stub);
11495                         ns_query(zone, rdataset, NULL);
11496                 }
11497                 if (msg != NULL)
11498                         dns_message_destroy(&msg);
11499         } else if (isc_serial_eq(soa.serial, oldserial)) {
11500                 isc_time_t expiretime;
11501                 isc_uint32_t expire;
11502 
11503                 /*
11504                  * Compute the new expire time based on this response.
11505                  */
11506                 expire = zone->expire;
11507                 get_edns_expire(zone, msg, &expire);
11508                 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
11509 
11510                 /*
11511                  * Has the expire time improved?
11512                  */
11513                 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
11514                         zone->expiretime = expiretime;
11515                         if (zone->masterfile != NULL)
11516                                 setmodtime(zone, &expiretime);
11517                 }
11518 
11519                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
11520                 zone->mastersok[zone->curmaster] = ISC_TRUE;
11521                 goto next_master;
11522         } else {
11523                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
11524                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
11525                                      "received from master %s < ours (%u)",
11526                                      soa.serial, master, oldserial);
11527                 else
11528                         zone_debuglog(zone, me, 1, "ahead");
11529                 zone->mastersok[zone->curmaster] = ISC_TRUE;
11530                 goto next_master;
11531         }
11532         if (msg != NULL)
11533                 dns_message_destroy(&msg);
11534         goto detach;
11535 
11536  next_master:
11537         if (msg != NULL)
11538                 dns_message_destroy(&msg);
11539         isc_event_free(&event);
11540         dns_request_destroy(&zone->request);
11541         /*
11542          * Skip to next failed / untried master.
11543          */
11544         do {
11545                 zone->curmaster++;
11546         } while (zone->curmaster < zone->masterscnt &&
11547                  zone->mastersok[zone->curmaster]);
11548         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11549         if (zone->curmaster >= zone->masterscnt) {
11550                 isc_boolean_t done = ISC_TRUE;
11551                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11552                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11553                         /*
11554                          * Did we get a good answer from all the masters?
11555                          */
11556                         for (j = 0; j < zone->masterscnt; j++)
11557                                 if (zone->mastersok[j] == ISC_FALSE) {
11558                                         done = ISC_FALSE;
11559                                         break;
11560                                 }
11561                 } else
11562                         done = ISC_TRUE;
11563                 if (!done) {
11564                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11565                         zone->curmaster = 0;
11566                         /*
11567                          * Find the next failed master.
11568                          */
11569                         while (zone->curmaster < zone->masterscnt &&
11570                                zone->mastersok[zone->curmaster])
11571                                 zone->curmaster++;
11572                         goto requeue;
11573                 }
11574                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11575                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11576                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11577                         zone->refreshtime = now;
11578                 }
11579                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11580                 zone_settimer(zone, &now);
11581                 goto detach;
11582         }
11583 
11584  requeue:
11585         queue_soa_query(zone);
11586         goto detach;
11587 
11588  same_master:
11589         if (msg != NULL)
11590                 dns_message_destroy(&msg);
11591         isc_event_free(&event);
11592         dns_request_destroy(&zone->request);
11593         queue_soa_query(zone);
11594 
11595  detach:
11596         UNLOCK_ZONE(zone);
11597         if (do_queue_xfrin)
11598                 queue_xfrin(zone);
11599         dns_zone_idetach(&zone);
11600         return;
11601 }
11602 
11603 static void
11604 queue_soa_query(dns_zone_t *zone) {
11605         const char me[] = "queue_soa_query";
11606         isc_event_t *e;
11607         dns_zone_t *dummy = NULL;
11608         isc_result_t result;
11609 
11610         ENTER;
11611         /*
11612          * Locked by caller
11613          */
11614         REQUIRE(LOCKED_ZONE(zone));
11615 
11616         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11617                 cancel_refresh(zone);
11618                 return;
11619         }
11620 
11621         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11622                                soa_query, zone, sizeof(isc_event_t));
11623         if (e == NULL) {
11624                 cancel_refresh(zone);
11625                 return;
11626         }
11627 
11628         /*
11629          * Attach so that we won't clean up
11630          * until the event is delivered.
11631          */
11632         zone_iattach(zone, &dummy);
11633 
11634         e->ev_arg = zone;
11635         e->ev_sender = NULL;
11636         result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
11637         if (result != ISC_R_SUCCESS) {
11638                 zone_idetach(&dummy);
11639                 isc_event_free(&e);
11640                 cancel_refresh(zone);
11641         }
11642 }
11643 
11644 static inline isc_result_t
11645 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
11646              dns_message_t **messagep)
11647 {
11648         dns_message_t *message = NULL;
11649         dns_name_t *qname = NULL;
11650         dns_rdataset_t *qrdataset = NULL;
11651         isc_result_t result;
11652 
11653         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11654                                     &message);
11655         if (result != ISC_R_SUCCESS)
11656                 goto cleanup;
11657 
11658         message->opcode = dns_opcode_query;
11659         message->rdclass = zone->rdclass;
11660 
11661         result = dns_message_gettempname(message, &qname);
11662         if (result != ISC_R_SUCCESS)
11663                 goto cleanup;
11664 
11665         result = dns_message_gettemprdataset(message, &qrdataset);
11666         if (result != ISC_R_SUCCESS)
11667                 goto cleanup;
11668 
11669         /*
11670          * Make question.
11671          */
11672         dns_name_init(qname, NULL);
11673         dns_name_clone(&zone->origin, qname);
11674         dns_rdataset_init(qrdataset);
11675         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
11676         ISC_LIST_APPEND(qname->list, qrdataset, link);
11677         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
11678 
11679         *messagep = message;
11680         return (ISC_R_SUCCESS);
11681 
11682  cleanup:
11683         if (qname != NULL)
11684                 dns_message_puttempname(message, &qname);
11685         if (qrdataset != NULL)
11686                 dns_message_puttemprdataset(message, &qrdataset);
11687         if (message != NULL)
11688                 dns_message_destroy(&message);
11689         return (result);
11690 }
11691 
11692 static isc_result_t
11693 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid,
11694         isc_boolean_t reqexpire)
11695 {
11696         isc_result_t result;
11697         dns_rdataset_t *rdataset = NULL;
11698         dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
11699         int count = 0;
11700 
11701         /* Set EDNS options if applicable */
11702         if (reqnsid) {
11703                 INSIST(count < DNS_EDNSOPTIONS);
11704                 ednsopts[count].code = DNS_OPT_NSID;
11705                 ednsopts[count].length = 0;
11706                 ednsopts[count].value = NULL;
11707                 count++;
11708         }
11709         if (reqexpire) {
11710                 INSIST(count < DNS_EDNSOPTIONS);
11711                 ednsopts[count].code = DNS_OPT_EXPIRE;
11712                 ednsopts[count].length = 0;
11713                 ednsopts[count].value = NULL;
11714                 count++;
11715         }
11716         result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
11717                                       ednsopts, count);
11718         if (result != ISC_R_SUCCESS)
11719                 return (result);
11720 
11721         return (dns_message_setopt(message, rdataset));
11722 }
11723 
11724 static void
11725 soa_query(isc_task_t *task, isc_event_t *event) {
11726         const char me[] = "soa_query";
11727         isc_result_t result = ISC_R_FAILURE;
11728         dns_message_t *message = NULL;
11729         dns_zone_t *zone = event->ev_arg;
11730         dns_zone_t *dummy = NULL;
11731         isc_netaddr_t masterip;
11732         dns_tsigkey_t *key = NULL;
11733         isc_uint32_t options;
11734         isc_boolean_t cancel = ISC_TRUE;
11735         int timeout;
11736         isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
11737         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11738         isc_dscp_t dscp = -1;
11739 
11740         REQUIRE(DNS_ZONE_VALID(zone));
11741 
11742         UNUSED(task);
11743 
11744         ENTER;
11745 
11746         LOCK_ZONE(zone);
11747         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11748             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11749             zone->view->requestmgr == NULL) {
11750                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11751                         cancel = ISC_FALSE;
11752                 goto cleanup;
11753         }
11754 
11755  again:
11756         result = create_query(zone, dns_rdatatype_soa, &message);
11757         if (result != ISC_R_SUCCESS)
11758                 goto cleanup;
11759 
11760         INSIST(zone->masterscnt > 0);
11761         INSIST(zone->curmaster < zone->masterscnt);
11762 
11763         zone->masteraddr = zone->masters[zone->curmaster];
11764 
11765         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11766         /*
11767          * First, look for a tsig key in the master statement, then
11768          * try for a server key.
11769          */
11770         if ((zone->masterkeynames != NULL) &&
11771             (zone->masterkeynames[zone->curmaster] != NULL)) {
11772                 dns_view_t *view = dns_zone_getview(zone);
11773                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11774                 result = dns_view_gettsig(view, keyname, &key);
11775                 if (result != ISC_R_SUCCESS) {
11776                         char namebuf[DNS_NAME_FORMATSIZE];
11777                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11778                         dns_zone_log(zone, ISC_LOG_ERROR,
11779                                      "unable to find key: %s", namebuf);
11780                         goto skip_master;
11781                 }
11782         }
11783         if (key == NULL) {
11784                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
11785                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11786                         char addrbuf[ISC_NETADDR_FORMATSIZE];
11787                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11788                         dns_zone_log(zone, ISC_LOG_ERROR,
11789                                      "unable to find TSIG key for %s", addrbuf);
11790                         goto skip_master;
11791                 }
11792         }
11793 
11794         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11795                   DNS_REQUESTOPT_TCP : 0;
11796         have_xfrsource = have_xfrdscp = ISC_FALSE;
11797         reqnsid = zone->view->requestnsid;
11798         reqexpire = zone->requestexpire;
11799         if (zone->view->peers != NULL) {
11800                 dns_peer_t *peer = NULL;
11801                 isc_boolean_t edns, usetcp;
11802                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11803                                                  &masterip, &peer);
11804                 if (result == ISC_R_SUCCESS) {
11805                         result = dns_peer_getsupportedns(peer, &edns);
11806                         if (result == ISC_R_SUCCESS && !edns)
11807                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11808                         result = dns_peer_gettransfersource(peer,
11809                                                             &zone->sourceaddr);
11810                         if (result == ISC_R_SUCCESS)
11811                                 have_xfrsource = ISC_TRUE;
11812                         (void)dns_peer_gettransferdscp(peer, &dscp);
11813                         if (dscp != -1)
11814                                 have_xfrdscp = ISC_TRUE;
11815                         if (zone->view->resolver != NULL)
11816                                 udpsize =
11817                                   dns_resolver_getudpsize(zone->view->resolver);
11818                         (void)dns_peer_getudpsize(peer, &udpsize);
11819                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11820                         (void)dns_peer_getrequestexpire(peer, &reqexpire);
11821                         result = dns_peer_getforcetcp(peer, &usetcp);
11822                         if (result == ISC_R_SUCCESS && usetcp)
11823                                 options |= DNS_REQUESTOPT_TCP;
11824                 }
11825         }
11826 
11827         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11828         case PF_INET:
11829                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11830                         if (isc_sockaddr_equal(&zone->altxfrsource4,
11831                                                &zone->xfrsource4))
11832                                 goto skip_master;
11833                         zone->sourceaddr = zone->altxfrsource4;
11834                         if (!have_xfrdscp)
11835                                 dscp = zone->altxfrsource4dscp;
11836                 } else if (!have_xfrsource) {
11837                         zone->sourceaddr = zone->xfrsource4;
11838                         if (!have_xfrdscp)
11839                                 dscp = zone->xfrsource4dscp;
11840                 }
11841                 break;
11842         case PF_INET6:
11843                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11844                         if (isc_sockaddr_equal(&zone->altxfrsource6,
11845                                                &zone->xfrsource6))
11846                                 goto skip_master;
11847                         zone->sourceaddr = zone->altxfrsource6;
11848                         if (!have_xfrdscp)
11849                                 dscp = zone->altxfrsource6dscp;
11850                 } else if (!have_xfrsource) {
11851                         zone->sourceaddr = zone->xfrsource6;
11852                         if (!have_xfrdscp)
11853                                 dscp = zone->xfrsource6dscp;
11854                 }
11855                 break;
11856         default:
11857                 result = ISC_R_NOTIMPLEMENTED;
11858                 goto cleanup;
11859         }
11860 
11861         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11862                 result = add_opt(message, udpsize, reqnsid, reqexpire);
11863                 if (result != ISC_R_SUCCESS)
11864                         zone_debuglog(zone, me, 1,
11865                                       "unable to add opt record: %s",
11866                                       dns_result_totext(result));
11867         }
11868 
11869         zone_iattach(zone, &dummy);
11870         timeout = 15;
11871         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11872                 timeout = 30;
11873         result = dns_request_createvia4(zone->view->requestmgr, message,
11874                                         &zone->sourceaddr, &zone->masteraddr,
11875                                         dscp, options, key, timeout * 3,
11876                                         timeout, 0, zone->task,
11877                                         refresh_callback, zone, &zone->request);
11878         if (result != ISC_R_SUCCESS) {
11879                 zone_idetach(&dummy);
11880                 zone_debuglog(zone, me, 1,
11881                               "dns_request_createvia4() failed: %s",
11882                               dns_result_totext(result));
11883                 goto skip_master;
11884         } else {
11885                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11886                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
11887                 else
11888                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
11889         }
11890         cancel = ISC_FALSE;
11891 
11892  cleanup:
11893         if (key != NULL)
11894                 dns_tsigkey_detach(&key);
11895         if (result != ISC_R_SUCCESS)
11896                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11897         if (message != NULL)
11898                 dns_message_destroy(&message);
11899         if (cancel)
11900                 cancel_refresh(zone);
11901         isc_event_free(&event);
11902         UNLOCK_ZONE(zone);
11903         dns_zone_idetach(&zone);
11904         return;
11905 
11906  skip_master:
11907         if (key != NULL)
11908                 dns_tsigkey_detach(&key);
11909         dns_message_destroy(&message);
11910         /*
11911          * Skip to next failed / untried master.
11912          */
11913         do {
11914                 zone->curmaster++;
11915         } while (zone->curmaster < zone->masterscnt &&
11916                  zone->mastersok[zone->curmaster]);
11917         if (zone->curmaster < zone->masterscnt)
11918                 goto again;
11919         zone->curmaster = 0;
11920         goto cleanup;
11921 }
11922 
11923 static void
11924 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11925         const char me[] = "ns_query";
11926         isc_result_t result;
11927         dns_message_t *message = NULL;
11928         isc_netaddr_t masterip;
11929         dns_tsigkey_t *key = NULL;
11930         dns_dbnode_t *node = NULL;
11931         int timeout;
11932         isc_boolean_t have_xfrsource = ISC_FALSE, have_xfrdscp = ISC_FALSE;
11933         isc_boolean_t reqnsid;
11934         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11935         isc_dscp_t dscp = -1;
11936 
11937         REQUIRE(DNS_ZONE_VALID(zone));
11938         REQUIRE(LOCKED_ZONE(zone));
11939         REQUIRE((soardataset != NULL && stub == NULL) ||
11940                 (soardataset == NULL && stub != NULL));
11941         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11942 
11943         ENTER;
11944 
11945         if (stub == NULL) {
11946                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
11947                 if (stub == NULL)
11948                         goto cleanup;
11949                 stub->magic = STUB_MAGIC;
11950                 stub->mctx = zone->mctx;
11951                 stub->zone = NULL;
11952                 stub->db = NULL;
11953                 stub->version = NULL;
11954 
11955                 /*
11956                  * Attach so that the zone won't disappear from under us.
11957                  */
11958                 zone_iattach(zone, &stub->zone);
11959 
11960                 /*
11961                  * If a db exists we will update it, otherwise we create a
11962                  * new one and attach it to the zone once we have the NS
11963                  * RRset and glue.
11964                  */
11965                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11966                 if (zone->db != NULL) {
11967                         dns_db_attach(zone->db, &stub->db);
11968                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11969                 } else {
11970                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11971 
11972                         INSIST(zone->db_argc >= 1);
11973                         result = dns_db_create(zone->mctx, zone->db_argv[0],
11974                                                &zone->origin, dns_dbtype_stub,
11975                                                zone->rdclass,
11976                                                zone->db_argc - 1,
11977                                                zone->db_argv + 1,
11978                                                &stub->db);
11979                         if (result != ISC_R_SUCCESS) {
11980                                 dns_zone_log(zone, ISC_LOG_ERROR,
11981                                              "refreshing stub: "
11982                                              "could not create "
11983                                              "database: %s",
11984                                              dns_result_totext(result));
11985                                 goto cleanup;
11986                         }
11987                         dns_db_settask(stub->db, zone->task);
11988                 }
11989 
11990                 result = dns_db_newversion(stub->db, &stub->version);
11991                 if (result != ISC_R_SUCCESS) {
11992                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11993                                      "dns_db_newversion() failed: %s",
11994                                      dns_result_totext(result));
11995                         goto cleanup;
11996                 }
11997 
11998                 /*
11999                  * Update SOA record.
12000                  */
12001                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
12002                                          &node);
12003                 if (result != ISC_R_SUCCESS) {
12004                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
12005                                      "dns_db_findnode() failed: %s",
12006                                      dns_result_totext(result));
12007                         goto cleanup;
12008                 }
12009 
12010                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
12011                                             soardataset, 0, NULL);
12012                 dns_db_detachnode(stub->db, &node);
12013                 if (result != ISC_R_SUCCESS) {
12014                         dns_zone_log(zone, ISC_LOG_INFO,
12015                                      "refreshing stub: "
12016                                      "dns_db_addrdataset() failed: %s",
12017                                      dns_result_totext(result));
12018                         goto cleanup;
12019                 }
12020         }
12021 
12022         /*
12023          * XXX Optimisation: Create message when zone is setup and reuse.
12024          */
12025         result = create_query(zone, dns_rdatatype_ns, &message);
12026         INSIST(result == ISC_R_SUCCESS);
12027 
12028         INSIST(zone->masterscnt > 0);
12029         INSIST(zone->curmaster < zone->masterscnt);
12030         zone->masteraddr = zone->masters[zone->curmaster];
12031 
12032         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12033         /*
12034          * First, look for a tsig key in the master statement, then
12035          * try for a server key.
12036          */
12037         if ((zone->masterkeynames != NULL) &&
12038             (zone->masterkeynames[zone->curmaster] != NULL)) {
12039                 dns_view_t *view = dns_zone_getview(zone);
12040                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12041                 result = dns_view_gettsig(view, keyname, &key);
12042                 if (result != ISC_R_SUCCESS) {
12043                         char namebuf[DNS_NAME_FORMATSIZE];
12044                         dns_name_format(keyname, namebuf, sizeof(namebuf));
12045                         dns_zone_log(zone, ISC_LOG_ERROR,
12046                                      "unable to find key: %s", namebuf);
12047                 }
12048         }
12049         if (key == NULL)
12050                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
12051 
12052         reqnsid = zone->view->requestnsid;
12053         if (zone->view->peers != NULL) {
12054                 dns_peer_t *peer = NULL;
12055                 isc_boolean_t edns;
12056                 result = dns_peerlist_peerbyaddr(zone->view->peers,
12057                                                  &masterip, &peer);
12058                 if (result == ISC_R_SUCCESS) {
12059                         result = dns_peer_getsupportedns(peer, &edns);
12060                         if (result == ISC_R_SUCCESS && !edns)
12061                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12062                         result = dns_peer_gettransfersource(peer,
12063                                                             &zone->sourceaddr);
12064                         if (result == ISC_R_SUCCESS)
12065                                 have_xfrsource = ISC_TRUE;
12066                         result = dns_peer_gettransferdscp(peer, &dscp);
12067                         if (result == ISC_R_SUCCESS && dscp != -1)
12068                                 have_xfrdscp = ISC_TRUE;
12069                         if (zone->view->resolver != NULL)
12070                                 udpsize =
12071                                   dns_resolver_getudpsize(zone->view->resolver);
12072                         (void)dns_peer_getudpsize(peer, &udpsize);
12073                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
12074                 }
12075 
12076         }
12077         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12078                 result = add_opt(message, udpsize, reqnsid, ISC_FALSE);
12079                 if (result != ISC_R_SUCCESS)
12080                         zone_debuglog(zone, me, 1,
12081                                       "unable to add opt record: %s",
12082                                       dns_result_totext(result));
12083         }
12084 
12085         /*
12086          * Always use TCP so that we shouldn't truncate in additional section.
12087          */
12088         switch (isc_sockaddr_pf(&zone->masteraddr)) {
12089         case PF_INET:
12090                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12091                         zone->sourceaddr = zone->altxfrsource4;
12092                         if (!have_xfrdscp)
12093                                 dscp = zone->altxfrsource4dscp;
12094                 } else if (!have_xfrsource) {
12095                         zone->sourceaddr = zone->xfrsource4;
12096                         if (!have_xfrdscp)
12097                                 dscp = zone->xfrsource4dscp;
12098                 }
12099                 break;
12100         case PF_INET6:
12101                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12102                         zone->sourceaddr = zone->altxfrsource6;
12103                         if (!have_xfrdscp)
12104                                 dscp = zone->altxfrsource6dscp;
12105                 } else if (!have_xfrsource) {
12106                         zone->sourceaddr = zone->xfrsource6;
12107                         if (!have_xfrdscp)
12108                                 dscp = zone->xfrsource6dscp;
12109                 }
12110                 break;
12111         default:
12112                 result = ISC_R_NOTIMPLEMENTED;
12113                 POST(result);
12114                 goto cleanup;
12115         }
12116         timeout = 15;
12117         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
12118                 timeout = 30;
12119         result = dns_request_createvia4(zone->view->requestmgr, message,
12120                                         &zone->sourceaddr, &zone->masteraddr,
12121                                         dscp, DNS_REQUESTOPT_TCP, key,
12122                                         timeout * 3, timeout, 0, zone->task,
12123                                         stub_callback, stub, &zone->request);
12124         if (result != ISC_R_SUCCESS) {
12125                 zone_debuglog(zone, me, 1,
12126                               "dns_request_createvia() failed: %s",
12127                               dns_result_totext(result));
12128                 goto cleanup;
12129         }
12130         dns_message_destroy(&message);
12131         goto unlock;
12132 
12133  cleanup:
12134         cancel_refresh(zone);
12135         if (stub != NULL) {
12136                 stub->magic = 0;
12137                 if (stub->version != NULL)
12138                         dns_db_closeversion(stub->db, &stub->version,
12139                                             ISC_FALSE);
12140                 if (stub->db != NULL)
12141                         dns_db_detach(&stub->db);
12142                 if (stub->zone != NULL)
12143                         zone_idetach(&stub->zone);
12144                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12145         }
12146         if (message != NULL)
12147                 dns_message_destroy(&message);
12148  unlock:
12149         if (key != NULL)
12150                 dns_tsigkey_detach(&key);
12151         return;
12152 }
12153 
12154 /*
12155  * Handle the control event.  Note that although this event causes the zone
12156  * to shut down, it is not a shutdown event in the sense of the task library.
12157  */
12158 static void
12159 zone_shutdown(isc_task_t *task, isc_event_t *event) {
12160         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
12161         isc_boolean_t free_needed, linked = ISC_FALSE;
12162         dns_zone_t *raw = NULL, *secure = NULL;
12163 
12164         UNUSED(task);
12165         REQUIRE(DNS_ZONE_VALID(zone));
12166         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
12167         INSIST(isc_refcount_current(&zone->erefs) == 0);
12168 
12169         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
12170 
12171         /*
12172          * Stop things being restarted after we cancel them below.
12173          */
12174         LOCK_ZONE(zone);
12175         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
12176         UNLOCK_ZONE(zone);
12177 
12178         /*
12179          * If we were waiting for xfrin quota, step out of
12180          * the queue.
12181          * If there's no zone manager, we can't be waiting for the
12182          * xfrin quota
12183          */
12184         if (zone->zmgr != NULL) {
12185                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12186                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
12187                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
12188                                         statelink);
12189                         linked = ISC_TRUE;
12190                         zone->statelist = NULL;
12191                 }
12192                 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
12193                         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
12194                                         statelink);
12195                         zone->statelist = NULL;
12196                         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12197                 }
12198                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12199         }
12200 
12201         /*
12202          * In task context, no locking required.  See zone_xfrdone().
12203          */
12204         if (zone->xfr != NULL)
12205                 dns_xfrin_shutdown(zone->xfr);
12206 
12207         /* Safe to release the zone now */
12208         if (zone->zmgr != NULL)
12209                 dns_zonemgr_releasezone(zone->zmgr, zone);
12210 
12211         LOCK_ZONE(zone);
12212         INSIST(zone != zone->raw);
12213         if (linked) {
12214                 INSIST(zone->irefs > 0);
12215                 zone->irefs--;
12216         }
12217         if (zone->request != NULL) {
12218                 dns_request_cancel(zone->request);
12219         }
12220 
12221         if (zone->readio != NULL)
12222                 zonemgr_cancelio(zone->readio);
12223 
12224         if (zone->lctx != NULL)
12225                 dns_loadctx_cancel(zone->lctx);
12226 
12227         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12228             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12229                 if (zone->writeio != NULL)
12230                         zonemgr_cancelio(zone->writeio);
12231 
12232                 if (zone->dctx != NULL)
12233                         dns_dumpctx_cancel(zone->dctx);
12234         }
12235 
12236         notify_cancel(zone);
12237 
12238         forward_cancel(zone);
12239 
12240         if (zone->timer != NULL) {
12241                 isc_timer_detach(&zone->timer);
12242                 INSIST(zone->irefs > 0);
12243                 zone->irefs--;
12244         }
12245 
12246         if (zone->view != NULL)
12247                 dns_view_weakdetach(&zone->view);
12248 
12249         /*
12250          * We have now canceled everything set the flag to allow exit_check()
12251          * to succeed.  We must not unlock between setting this flag and
12252          * calling exit_check().
12253          */
12254         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
12255         free_needed = exit_check(zone);
12256         if (inline_secure(zone)) {
12257                 raw = zone->raw;
12258                 zone->raw = NULL;
12259         }
12260         if (inline_raw(zone)) {
12261                 secure = zone->secure;
12262                 zone->secure = NULL;
12263         }
12264         UNLOCK_ZONE(zone);
12265         if (raw != NULL)
12266                 dns_zone_detach(&raw);
12267         if (secure != NULL)
12268                 dns_zone_idetach(&secure);
12269         if (free_needed)
12270                 zone_free(zone);
12271 }
12272 
12273 static void
12274 zone_timer(isc_task_t *task, isc_event_t *event) {
12275         const char me[] = "zone_timer";
12276         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
12277 
12278         UNUSED(task);
12279         REQUIRE(DNS_ZONE_VALID(zone));
12280 
12281         ENTER;
12282 
12283         zone_maintenance(zone);
12284 
12285         isc_event_free(&event);
12286 }
12287 
12288 static void
12289 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
12290         const char me[] = "zone_settimer";
12291         isc_time_t next;
12292         isc_result_t result;
12293 
12294         ENTER;
12295         REQUIRE(DNS_ZONE_VALID(zone));
12296         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12297                 return;
12298 
12299         isc_time_settoepoch(&next);
12300 
12301         switch (zone->type) {
12302         case dns_zone_redirect:
12303                 if (zone->masters != NULL)
12304                         goto treat_as_slave;
12305                 /* FALLTHROUGH */
12306 
12307         case dns_zone_master:
12308                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
12309                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
12310                         next = zone->notifytime;
12311                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12312                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12313                         INSIST(!isc_time_isepoch(&zone->dumptime));
12314                         if (isc_time_isepoch(&next) ||
12315                             isc_time_compare(&zone->dumptime, &next) < 0)
12316                                 next = zone->dumptime;
12317                 }
12318                 if (zone->type == dns_zone_redirect)
12319                         break;
12320                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
12321                     !isc_time_isepoch(&zone->refreshkeytime)) {
12322                         if (isc_time_isepoch(&next) ||
12323                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
12324                                 next = zone->refreshkeytime;
12325                 }
12326                 if (!isc_time_isepoch(&zone->resigntime)) {
12327                         if (isc_time_isepoch(&next) ||
12328                             isc_time_compare(&zone->resigntime, &next) < 0)
12329                                 next = zone->resigntime;
12330                 }
12331                 if (!isc_time_isepoch(&zone->keywarntime)) {
12332                         if (isc_time_isepoch(&next) ||
12333                             isc_time_compare(&zone->keywarntime, &next) < 0)
12334                                 next = zone->keywarntime;
12335                 }
12336                 if (!isc_time_isepoch(&zone->signingtime)) {
12337                         if (isc_time_isepoch(&next) ||
12338                             isc_time_compare(&zone->signingtime, &next) < 0)
12339                                 next = zone->signingtime;
12340                 }
12341                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
12342                         if (isc_time_isepoch(&next) ||
12343                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
12344                                 next = zone->nsec3chaintime;
12345                 }
12346                 break;
12347 
12348         case dns_zone_slave:
12349         treat_as_slave:
12350                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
12351                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
12352                         next = zone->notifytime;
12353                 /* FALLTHROUGH */
12354 
12355         case dns_zone_stub:
12356                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
12357                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
12358                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
12359                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
12360                         INSIST(!isc_time_isepoch(&zone->refreshtime));
12361                         if (isc_time_isepoch(&next) ||
12362                             isc_time_compare(&zone->refreshtime, &next) < 0)
12363                                 next = zone->refreshtime;
12364                 }
12365                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
12366                     !isc_time_isepoch(&zone->expiretime)) {
12367                         if (isc_time_isepoch(&next) ||
12368                              isc_time_compare(&zone->expiretime, &next) < 0)
12369                                 next = zone->expiretime;
12370                 }
12371                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12372                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12373                         INSIST(!isc_time_isepoch(&zone->dumptime));
12374                         if (isc_time_isepoch(&next) ||
12375                             isc_time_compare(&zone->dumptime, &next) < 0)
12376                                 next = zone->dumptime;
12377                 }
12378                 break;
12379 
12380         case dns_zone_key:
12381                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12382                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12383                         INSIST(!isc_time_isepoch(&zone->dumptime));
12384                         if (isc_time_isepoch(&next) ||
12385                             isc_time_compare(&zone->dumptime, &next) < 0)
12386                                 next = zone->dumptime;
12387                 }
12388                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
12389                         if (isc_time_isepoch(&next) ||
12390                             (!isc_time_isepoch(&zone->refreshkeytime) &&
12391                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
12392                                 next = zone->refreshkeytime;
12393                 }
12394                 break;
12395 
12396         default:
12397                 break;
12398         }
12399 
12400         if (isc_time_isepoch(&next)) {
12401                 zone_debuglog(zone, me, 10, "settimer inactive");
12402                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
12403                                           NULL, NULL, ISC_TRUE);
12404                 if (result != ISC_R_SUCCESS)
12405                         dns_zone_log(zone, ISC_LOG_ERROR,
12406                                      "could not deactivate zone timer: %s",
12407                                      isc_result_totext(result));
12408         } else {
12409                 if (isc_time_compare(&next, now) <= 0)
12410                         next = *now;
12411                 result = isc_timer_reset(zone->timer, isc_timertype_once,
12412                                          &next, NULL, ISC_TRUE);
12413                 if (result != ISC_R_SUCCESS)
12414                         dns_zone_log(zone, ISC_LOG_ERROR,
12415                                      "could not reset zone timer: %s",
12416                                      isc_result_totext(result));
12417         }
12418 }
12419 
12420 static void
12421 cancel_refresh(dns_zone_t *zone) {
12422         const char me[] = "cancel_refresh";
12423         isc_time_t now;
12424 
12425         /*
12426          * 'zone' locked by caller.
12427          */
12428 
12429         REQUIRE(DNS_ZONE_VALID(zone));
12430         REQUIRE(LOCKED_ZONE(zone));
12431 
12432         ENTER;
12433 
12434         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12435         TIME_NOW(&now);
12436         zone_settimer(zone, &now);
12437 }
12438 
12439 static isc_result_t
12440 notify_createmessage(dns_zone_t *zone, unsigned int flags,
12441                      dns_message_t **messagep)
12442 {
12443         dns_db_t *zonedb = NULL;
12444         dns_dbnode_t *node = NULL;
12445         dns_dbversion_t *version = NULL;
12446         dns_message_t *message = NULL;
12447         dns_rdataset_t rdataset;
12448         dns_rdata_t rdata = DNS_RDATA_INIT;
12449 
12450         dns_name_t *tempname = NULL;
12451         dns_rdata_t *temprdata = NULL;
12452         dns_rdatalist_t *temprdatalist = NULL;
12453         dns_rdataset_t *temprdataset = NULL;
12454 
12455         isc_result_t result;
12456         isc_region_t r;
12457         isc_buffer_t *b = NULL;
12458 
12459         REQUIRE(DNS_ZONE_VALID(zone));
12460         REQUIRE(messagep != NULL && *messagep == NULL);
12461 
12462         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
12463                                     &message);
12464         if (result != ISC_R_SUCCESS)
12465                 return (result);
12466 
12467         message->opcode = dns_opcode_notify;
12468         message->flags |= DNS_MESSAGEFLAG_AA;
12469         message->rdclass = zone->rdclass;
12470 
12471         result = dns_message_gettempname(message, &tempname);
12472         if (result != ISC_R_SUCCESS)
12473                 goto cleanup;
12474 
12475         result = dns_message_gettemprdataset(message, &temprdataset);
12476         if (result != ISC_R_SUCCESS)
12477                 goto cleanup;
12478 
12479         /*
12480          * Make question.
12481          */
12482         dns_name_init(tempname, NULL);
12483         dns_name_clone(&zone->origin, tempname);
12484         dns_rdataset_init(temprdataset);
12485         dns_rdataset_makequestion(temprdataset, zone->rdclass,
12486                                   dns_rdatatype_soa);
12487         ISC_LIST_APPEND(tempname->list, temprdataset, link);
12488         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
12489         tempname = NULL;
12490         temprdataset = NULL;
12491 
12492         if ((flags & DNS_NOTIFY_NOSOA) != 0)
12493                 goto done;
12494 
12495         result = dns_message_gettempname(message, &tempname);
12496         if (result != ISC_R_SUCCESS)
12497                 goto soa_cleanup;
12498         result = dns_message_gettemprdata(message, &temprdata);
12499         if (result != ISC_R_SUCCESS)
12500                 goto soa_cleanup;
12501         result = dns_message_gettemprdataset(message, &temprdataset);
12502         if (result != ISC_R_SUCCESS)
12503                 goto soa_cleanup;
12504         result = dns_message_gettemprdatalist(message, &temprdatalist);
12505         if (result != ISC_R_SUCCESS)
12506                 goto soa_cleanup;
12507 
12508         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12509         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
12510         dns_db_attach(zone->db, &zonedb);
12511         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12512 
12513         dns_name_init(tempname, NULL);
12514         dns_name_clone(&zone->origin, tempname);
12515         dns_db_currentversion(zonedb, &version);
12516         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
12517         if (result != ISC_R_SUCCESS)
12518                 goto soa_cleanup;
12519 
12520         dns_rdataset_init(&rdataset);
12521         result = dns_db_findrdataset(zonedb, node, version,
12522                                      dns_rdatatype_soa,
12523                                      dns_rdatatype_none, 0, &rdataset,
12524                                      NULL);
12525         if (result != ISC_R_SUCCESS)
12526                 goto soa_cleanup;
12527         result = dns_rdataset_first(&rdataset);
12528         if (result != ISC_R_SUCCESS)
12529                 goto soa_cleanup;
12530         dns_rdataset_current(&rdataset, &rdata);
12531         dns_rdata_toregion(&rdata, &r);
12532         result = isc_buffer_allocate(zone->mctx, &b, r.length);
12533         if (result != ISC_R_SUCCESS)
12534                 goto soa_cleanup;
12535         isc_buffer_putmem(b, r.base, r.length);
12536         isc_buffer_usedregion(b, &r);
12537         dns_rdata_init(temprdata);
12538         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
12539         dns_message_takebuffer(message, &b);
12540         result = dns_rdataset_next(&rdataset);
12541         dns_rdataset_disassociate(&rdataset);
12542         if (result != ISC_R_NOMORE)
12543                 goto soa_cleanup;
12544         temprdatalist->rdclass = rdata.rdclass;
12545         temprdatalist->type = rdata.type;
12546         temprdatalist->ttl = rdataset.ttl;
12547         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
12548 
12549         dns_rdataset_init(temprdataset);
12550         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
12551         if (result != ISC_R_SUCCESS)
12552                 goto soa_cleanup;
12553 
12554         ISC_LIST_APPEND(tempname->list, temprdataset, link);
12555         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
12556         temprdatalist = NULL;
12557         temprdataset = NULL;
12558         temprdata = NULL;
12559         tempname = NULL;
12560 
12561  soa_cleanup:
12562         if (node != NULL)
12563                 dns_db_detachnode(zonedb, &node);
12564         if (version != NULL)
12565                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
12566         if (zonedb != NULL)
12567                 dns_db_detach(&zonedb);
12568         if (tempname != NULL)
12569                 dns_message_puttempname(message, &tempname);
12570         if (temprdata != NULL)
12571                 dns_message_puttemprdata(message, &temprdata);
12572         if (temprdataset != NULL)
12573                 dns_message_puttemprdataset(message, &temprdataset);
12574         if (temprdatalist != NULL)
12575                 dns_message_puttemprdatalist(message, &temprdatalist);
12576 
12577  done:
12578         *messagep = message;
12579         return (ISC_R_SUCCESS);
12580 
12581  cleanup:
12582         if (tempname != NULL)
12583                 dns_message_puttempname(message, &tempname);
12584         if (temprdataset != NULL)
12585                 dns_message_puttemprdataset(message, &temprdataset);
12586         dns_message_destroy(&message);
12587         return (result);
12588 }
12589 
12590 isc_result_t
12591 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
12592                        dns_message_t *msg)
12593 {
12594         unsigned int i;
12595         dns_rdata_soa_t soa;
12596         dns_rdataset_t *rdataset = NULL;
12597         dns_rdata_t rdata = DNS_RDATA_INIT;
12598         isc_result_t result;
12599         char fromtext[ISC_SOCKADDR_FORMATSIZE];
12600         int match = 0;
12601         isc_netaddr_t netaddr;
12602         isc_sockaddr_t local, remote;
12603         isc_uint32_t serial = 0;
12604         isc_boolean_t have_serial = ISC_FALSE;
12605         dns_tsigkey_t *tsigkey;
12606         dns_name_t *tsig;
12607 
12608         REQUIRE(DNS_ZONE_VALID(zone));
12609 
12610         /*
12611          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
12612          * ROLLOVER.
12613          *
12614          * SOA: RFC1996
12615          * Check that 'from' is a valid notify source, (zone->masters).
12616          *      Return DNS_R_REFUSED if not.
12617          *
12618          * If the notify message contains a serial number check it
12619          * against the zones serial and return if <= current serial
12620          *
12621          * If a refresh check is progress, if so just record the
12622          * fact we received a NOTIFY and from where and return.
12623          * We will perform a new refresh check when the current one
12624          * completes. Return ISC_R_SUCCESS.
12625          *
12626          * Otherwise initiate a refresh check using 'from' as the
12627          * first address to check.  Return ISC_R_SUCCESS.
12628          */
12629 
12630         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
12631 
12632         /*
12633          * Notify messages are processed by the raw zone.
12634          */
12635         LOCK_ZONE(zone);
12636         INSIST(zone != zone->raw);
12637         if (inline_secure(zone)) {
12638                 result = dns_zone_notifyreceive(zone->raw, from, msg);
12639                 UNLOCK_ZONE(zone);
12640                 return (result);
12641         }
12642         /*
12643          *  We only handle NOTIFY (SOA) at the present.
12644          */
12645         if (isc_sockaddr_pf(from) == PF_INET)
12646                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
12647         else
12648                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
12649         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
12650             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
12651                                  dns_rdatatype_soa, dns_rdatatype_none,
12652                                  NULL, NULL) != ISC_R_SUCCESS) {
12653                 UNLOCK_ZONE(zone);
12654                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
12655                         dns_zone_log(zone, ISC_LOG_NOTICE,
12656                                      "NOTIFY with no "
12657                                      "question section from: %s", fromtext);
12658                         return (DNS_R_FORMERR);
12659                 }
12660                 dns_zone_log(zone, ISC_LOG_NOTICE,
12661                              "NOTIFY zone does not match");
12662                 return (DNS_R_NOTIMP);
12663         }
12664 
12665         /*
12666          * If we are a master zone just succeed.
12667          */
12668         if (zone->type == dns_zone_master) {
12669                 UNLOCK_ZONE(zone);
12670                 return (ISC_R_SUCCESS);
12671         }
12672 
12673         isc_netaddr_fromsockaddr(&netaddr, from);
12674         for (i = 0; i < zone->masterscnt; i++) {
12675                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
12676                         break;
12677                 if (zone->view->aclenv.match_mapped &&
12678                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
12679                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
12680                         isc_netaddr_t na1, na2;
12681                         isc_netaddr_fromv4mapped(&na1, &netaddr);
12682                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
12683                         if (isc_netaddr_equal(&na1, &na2))
12684                                 break;
12685                 }
12686         }
12687 
12688         /*
12689          * Accept notify requests from non masters if they are on
12690          * 'zone->notify_acl'.
12691          */
12692         tsigkey = dns_message_gettsigkey(msg);
12693         tsig = dns_tsigkey_identity(tsigkey);
12694         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
12695             dns_acl_match(&netaddr, tsig, zone->notify_acl,
12696                           &zone->view->aclenv,
12697                           &match, NULL) == ISC_R_SUCCESS &&
12698             match > 0)
12699         {
12700                 /* Accept notify. */
12701         } else if (i >= zone->masterscnt) {
12702                 UNLOCK_ZONE(zone);
12703                 dns_zone_log(zone, ISC_LOG_INFO,
12704                              "refused notify from non-master: %s", fromtext);
12705                 inc_stats(zone, dns_zonestatscounter_notifyrej);
12706                 return (DNS_R_REFUSED);
12707         }
12708 
12709         /*
12710          * If the zone is loaded and there are answers check the serial
12711          * to see if we need to do a refresh.  Do not worry about this
12712          * check if we are a dialup zone as we use the notify request
12713          * to trigger a refresh check.
12714          */
12715         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
12716             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
12717             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
12718                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
12719                                               &zone->origin,
12720                                               dns_rdatatype_soa,
12721                                               dns_rdatatype_none, NULL,
12722                                               &rdataset);
12723                 if (result == ISC_R_SUCCESS)
12724                         result = dns_rdataset_first(rdataset);
12725                 if (result == ISC_R_SUCCESS) {
12726                         isc_uint32_t oldserial;
12727                         unsigned int soacount;
12728 
12729                         dns_rdataset_current(rdataset, &rdata);
12730                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
12731                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12732                         serial = soa.serial;
12733                         have_serial = ISC_TRUE;
12734                         /*
12735                          * The following should safely be performed without DB
12736                          * lock and succeed in this context.
12737                          */
12738                         result = zone_get_from_db(zone, zone->db, NULL,
12739                                                   &soacount, &oldserial, NULL,
12740                                                   NULL, NULL, NULL, NULL);
12741                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12742                         RUNTIME_CHECK(soacount > 0U);
12743                         if (isc_serial_le(serial, oldserial)) {
12744                                 dns_zone_log(zone,
12745                                              ISC_LOG_INFO,
12746                                              "notify from %s: "
12747                                              "zone is up to date",
12748                                              fromtext);
12749                                 UNLOCK_ZONE(zone);
12750                                 return (ISC_R_SUCCESS);
12751                         }
12752                 }
12753         }
12754 
12755         /*
12756          * If we got this far and there was a refresh in progress just
12757          * let it complete.  Record where we got the notify from so we
12758          * can perform a refresh check when the current one completes
12759          */
12760         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
12761                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12762                 zone->notifyfrom = *from;
12763                 UNLOCK_ZONE(zone);
12764                 if (have_serial)
12765                         dns_zone_log(zone, ISC_LOG_INFO,
12766                                      "notify from %s: serial %u: refresh in "
12767                                      "progress, refresh check queued",
12768                                       fromtext, serial);
12769                 else
12770                         dns_zone_log(zone, ISC_LOG_INFO,
12771                                      "notify from %s: refresh in progress, "
12772                                      "refresh check queued", fromtext);
12773                 return (ISC_R_SUCCESS);
12774         }
12775         if (have_serial)
12776                 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
12777                              fromtext, serial);
12778         else
12779                 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
12780                              fromtext);
12781         zone->notifyfrom = *from;
12782         local = zone->masteraddr;
12783         remote = zone->sourceaddr;
12784         UNLOCK_ZONE(zone);
12785         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
12786         dns_zone_refresh(zone);
12787         return (ISC_R_SUCCESS);
12788 }
12789 
12790 void
12791 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12792 
12793         REQUIRE(DNS_ZONE_VALID(zone));
12794 
12795         LOCK_ZONE(zone);
12796         if (zone->notify_acl != NULL)
12797                 dns_acl_detach(&zone->notify_acl);
12798         dns_acl_attach(acl, &zone->notify_acl);
12799         UNLOCK_ZONE(zone);
12800 }
12801 
12802 void
12803 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12804 
12805         REQUIRE(DNS_ZONE_VALID(zone));
12806 
12807         LOCK_ZONE(zone);
12808         if (zone->query_acl != NULL)
12809                 dns_acl_detach(&zone->query_acl);
12810         dns_acl_attach(acl, &zone->query_acl);
12811         UNLOCK_ZONE(zone);
12812 }
12813 
12814 void
12815 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12816 
12817         REQUIRE(DNS_ZONE_VALID(zone));
12818 
12819         LOCK_ZONE(zone);
12820         if (zone->queryon_acl != NULL)
12821                 dns_acl_detach(&zone->queryon_acl);
12822         dns_acl_attach(acl, &zone->queryon_acl);
12823         UNLOCK_ZONE(zone);
12824 }
12825 
12826 void
12827 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12828 
12829         REQUIRE(DNS_ZONE_VALID(zone));
12830 
12831         LOCK_ZONE(zone);
12832         if (zone->update_acl != NULL)
12833                 dns_acl_detach(&zone->update_acl);
12834         dns_acl_attach(acl, &zone->update_acl);
12835         UNLOCK_ZONE(zone);
12836 }
12837 
12838 void
12839 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12840 
12841         REQUIRE(DNS_ZONE_VALID(zone));
12842 
12843         LOCK_ZONE(zone);
12844         if (zone->forward_acl != NULL)
12845                 dns_acl_detach(&zone->forward_acl);
12846         dns_acl_attach(acl, &zone->forward_acl);
12847         UNLOCK_ZONE(zone);
12848 }
12849 
12850 void
12851 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12852 
12853         REQUIRE(DNS_ZONE_VALID(zone));
12854 
12855         LOCK_ZONE(zone);
12856         if (zone->xfr_acl != NULL)
12857                 dns_acl_detach(&zone->xfr_acl);
12858         dns_acl_attach(acl, &zone->xfr_acl);
12859         UNLOCK_ZONE(zone);
12860 }
12861 
12862 dns_acl_t *
12863 dns_zone_getnotifyacl(dns_zone_t *zone) {
12864 
12865         REQUIRE(DNS_ZONE_VALID(zone));
12866 
12867         return (zone->notify_acl);
12868 }
12869 
12870 dns_acl_t *
12871 dns_zone_getqueryacl(dns_zone_t *zone) {
12872 
12873         REQUIRE(DNS_ZONE_VALID(zone));
12874 
12875         return (zone->query_acl);
12876 }
12877 
12878 dns_acl_t *
12879 dns_zone_getqueryonacl(dns_zone_t *zone) {
12880 
12881         REQUIRE(DNS_ZONE_VALID(zone));
12882 
12883         return (zone->queryon_acl);
12884 }
12885 
12886 dns_acl_t *
12887 dns_zone_getupdateacl(dns_zone_t *zone) {
12888 
12889         REQUIRE(DNS_ZONE_VALID(zone));
12890 
12891         return (zone->update_acl);
12892 }
12893 
12894 dns_acl_t *
12895 dns_zone_getforwardacl(dns_zone_t *zone) {
12896 
12897         REQUIRE(DNS_ZONE_VALID(zone));
12898 
12899         return (zone->forward_acl);
12900 }
12901 
12902 dns_acl_t *
12903 dns_zone_getxfracl(dns_zone_t *zone) {
12904 
12905         REQUIRE(DNS_ZONE_VALID(zone));
12906 
12907         return (zone->xfr_acl);
12908 }
12909 
12910 void
12911 dns_zone_clearupdateacl(dns_zone_t *zone) {
12912 
12913         REQUIRE(DNS_ZONE_VALID(zone));
12914 
12915         LOCK_ZONE(zone);
12916         if (zone->update_acl != NULL)
12917                 dns_acl_detach(&zone->update_acl);
12918         UNLOCK_ZONE(zone);
12919 }
12920 
12921 void
12922 dns_zone_clearforwardacl(dns_zone_t *zone) {
12923 
12924         REQUIRE(DNS_ZONE_VALID(zone));
12925 
12926         LOCK_ZONE(zone);
12927         if (zone->forward_acl != NULL)
12928                 dns_acl_detach(&zone->forward_acl);
12929         UNLOCK_ZONE(zone);
12930 }
12931 
12932 void
12933 dns_zone_clearnotifyacl(dns_zone_t *zone) {
12934 
12935         REQUIRE(DNS_ZONE_VALID(zone));
12936 
12937         LOCK_ZONE(zone);
12938         if (zone->notify_acl != NULL)
12939                 dns_acl_detach(&zone->notify_acl);
12940         UNLOCK_ZONE(zone);
12941 }
12942 
12943 void
12944 dns_zone_clearqueryacl(dns_zone_t *zone) {
12945 
12946         REQUIRE(DNS_ZONE_VALID(zone));
12947 
12948         LOCK_ZONE(zone);
12949         if (zone->query_acl != NULL)
12950                 dns_acl_detach(&zone->query_acl);
12951         UNLOCK_ZONE(zone);
12952 }
12953 
12954 void
12955 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12956 
12957         REQUIRE(DNS_ZONE_VALID(zone));
12958 
12959         LOCK_ZONE(zone);
12960         if (zone->queryon_acl != NULL)
12961                 dns_acl_detach(&zone->queryon_acl);
12962         UNLOCK_ZONE(zone);
12963 }
12964 
12965 void
12966 dns_zone_clearxfracl(dns_zone_t *zone) {
12967 
12968         REQUIRE(DNS_ZONE_VALID(zone));
12969 
12970         LOCK_ZONE(zone);
12971         if (zone->xfr_acl != NULL)
12972                 dns_acl_detach(&zone->xfr_acl);
12973         UNLOCK_ZONE(zone);
12974 }
12975 
12976 isc_boolean_t
12977 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12978         REQUIRE(DNS_ZONE_VALID(zone));
12979         return (zone->update_disabled);
12980 
12981 }
12982 
12983 void
12984 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12985         REQUIRE(DNS_ZONE_VALID(zone));
12986         zone->update_disabled = state;
12987 }
12988 
12989 isc_boolean_t
12990 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12991         REQUIRE(DNS_ZONE_VALID(zone));
12992         return (zone->zero_no_soa_ttl);
12993 
12994 }
12995 
12996 void
12997 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12998         REQUIRE(DNS_ZONE_VALID(zone));
12999         zone->zero_no_soa_ttl = state;
13000 }
13001 
13002 void
13003 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
13004 
13005         REQUIRE(DNS_ZONE_VALID(zone));
13006 
13007         zone->check_names = severity;
13008 }
13009 
13010 dns_severity_t
13011 dns_zone_getchecknames(dns_zone_t *zone) {
13012 
13013         REQUIRE(DNS_ZONE_VALID(zone));
13014 
13015         return (zone->check_names);
13016 }
13017 
13018 void
13019 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
13020 
13021         REQUIRE(DNS_ZONE_VALID(zone));
13022 
13023         zone->journalsize = size;
13024 }
13025 
13026 isc_int32_t
13027 dns_zone_getjournalsize(dns_zone_t *zone) {
13028 
13029         REQUIRE(DNS_ZONE_VALID(zone));
13030 
13031         return (zone->journalsize);
13032 }
13033 
13034 static void
13035 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
13036         isc_result_t result = ISC_R_FAILURE;
13037         isc_buffer_t buffer;
13038 
13039         REQUIRE(buf != NULL);
13040         REQUIRE(length > 1U);
13041 
13042         /*
13043          * Leave space for terminating '\0'.
13044          */
13045         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13046         if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
13047                 if (dns_name_dynamic(&zone->origin))
13048                         result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
13049                 if (result != ISC_R_SUCCESS &&
13050                     isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
13051                         isc_buffer_putstr(&buffer, "<UNKNOWN>");
13052 
13053                 if (isc_buffer_availablelength(&buffer) > 0)
13054                         isc_buffer_putstr(&buffer, "/");
13055                 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
13056         }
13057 
13058         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
13059             strcmp(zone->view->name, "_default") != 0 &&
13060             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
13061                 isc_buffer_putstr(&buffer, "/");
13062                 isc_buffer_putstr(&buffer, zone->view->name);
13063         }
13064         if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
13065                 isc_buffer_putstr(&buffer, " (signed)");
13066         if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
13067                 isc_buffer_putstr(&buffer, " (unsigned)");
13068 
13069         buf[isc_buffer_usedlength(&buffer)] = '\0';
13070 }
13071 
13072 static void
13073 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
13074         isc_result_t result = ISC_R_FAILURE;
13075         isc_buffer_t buffer;
13076 
13077         REQUIRE(buf != NULL);
13078         REQUIRE(length > 1U);
13079 
13080         /*
13081          * Leave space for terminating '\0'.
13082          */
13083         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13084         if (dns_name_dynamic(&zone->origin))
13085                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
13086         if (result != ISC_R_SUCCESS &&
13087             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
13088                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
13089 
13090         buf[isc_buffer_usedlength(&buffer)] = '\0';
13091 }
13092 
13093 static void
13094 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
13095         isc_buffer_t buffer;
13096 
13097         REQUIRE(buf != NULL);
13098         REQUIRE(length > 1U);
13099 
13100         /*
13101          * Leave space for terminating '\0'.
13102          */
13103         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13104         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
13105 
13106         buf[isc_buffer_usedlength(&buffer)] = '\0';
13107 }
13108 
13109 static void
13110 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
13111         isc_buffer_t buffer;
13112 
13113         REQUIRE(buf != NULL);
13114         REQUIRE(length > 1U);
13115 
13116 
13117         /*
13118          * Leave space for terminating '\0'.
13119          */
13120         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13121 
13122         if (zone->view == NULL) {
13123                 isc_buffer_putstr(&buffer, "_none");
13124         } else if (strlen(zone->view->name)
13125                    < isc_buffer_availablelength(&buffer)) {
13126                 isc_buffer_putstr(&buffer, zone->view->name);
13127         } else {
13128                 isc_buffer_putstr(&buffer, "_toolong");
13129         }
13130 
13131         buf[isc_buffer_usedlength(&buffer)] = '\0';
13132 }
13133 
13134 void
13135 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
13136         REQUIRE(DNS_ZONE_VALID(zone));
13137         REQUIRE(buf != NULL);
13138         zone_namerd_tostr(zone, buf, length);
13139 }
13140 
13141 static void
13142 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
13143         va_list ap;
13144         char message[4096];
13145 
13146         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13147                 return;
13148 
13149         va_start(ap, fmt);
13150         vsnprintf(message, sizeof(message), fmt, ap);
13151         va_end(ap);
13152         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
13153                       level, "zone %s: %s", zone->strnamerd, message);
13154 }
13155 
13156 void
13157 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
13158               int level, const char *fmt, ...) {
13159         va_list ap;
13160         char message[4096];
13161 
13162         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13163                 return;
13164 
13165         va_start(ap, fmt);
13166         vsnprintf(message, sizeof(message), fmt, ap);
13167         va_end(ap);
13168         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
13169                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
13170                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
13171                       "redirect-zone" : "zone ", zone->strnamerd, message);
13172 }
13173 
13174 void
13175 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
13176         va_list ap;
13177         char message[4096];
13178 
13179         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13180                 return;
13181 
13182         va_start(ap, fmt);
13183         vsnprintf(message, sizeof(message), fmt, ap);
13184         va_end(ap);
13185         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13186                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
13187                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
13188                       "redirect-zone" : "zone ", zone->strnamerd, message);
13189 }
13190 
13191 static void
13192 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
13193               const char *fmt, ...)
13194 {
13195         va_list ap;
13196         char message[4096];
13197         int level = ISC_LOG_DEBUG(debuglevel);
13198         const char *zstr;
13199 
13200         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13201                 return;
13202 
13203         va_start(ap, fmt);
13204         vsnprintf(message, sizeof(message), fmt, ap);
13205         va_end(ap);
13206 
13207         switch (zone->type) {
13208         case dns_zone_key:
13209                 zstr = "managed-keys-zone";
13210                 break;
13211         case dns_zone_redirect:
13212                 zstr = "redirect-zone";
13213                 break;
13214         default:
13215                 zstr = "zone";
13216         }
13217 
13218         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13219                       level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
13220                       message);
13221 }
13222 
13223 static int
13224 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
13225 {
13226         isc_result_t result;
13227         dns_name_t *name;
13228         dns_rdataset_t *curr;
13229         int count = 0;
13230 
13231         result = dns_message_firstname(msg, section);
13232         while (result == ISC_R_SUCCESS) {
13233                 name = NULL;
13234                 dns_message_currentname(msg, section, &name);
13235 
13236                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
13237                      curr = ISC_LIST_PREV(curr, link)) {
13238                         if (curr->type == type)
13239                                 count++;
13240                 }
13241                 result = dns_message_nextname(msg, section);
13242         }
13243 
13244         return (count);
13245 }
13246 
13247 void
13248 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
13249         REQUIRE(DNS_ZONE_VALID(zone));
13250 
13251         zone->maxxfrin = maxxfrin;
13252 }
13253 
13254 isc_uint32_t
13255 dns_zone_getmaxxfrin(dns_zone_t *zone) {
13256         REQUIRE(DNS_ZONE_VALID(zone));
13257 
13258         return (zone->maxxfrin);
13259 }
13260 
13261 void
13262 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
13263         REQUIRE(DNS_ZONE_VALID(zone));
13264         zone->maxxfrout = maxxfrout;
13265 }
13266 
13267 isc_uint32_t
13268 dns_zone_getmaxxfrout(dns_zone_t *zone) {
13269         REQUIRE(DNS_ZONE_VALID(zone));
13270 
13271         return (zone->maxxfrout);
13272 }
13273 
13274 dns_zonetype_t
13275 dns_zone_gettype(dns_zone_t *zone) {
13276         REQUIRE(DNS_ZONE_VALID(zone));
13277 
13278         return (zone->type);
13279 }
13280 
13281 dns_name_t *
13282 dns_zone_getorigin(dns_zone_t *zone) {
13283         REQUIRE(DNS_ZONE_VALID(zone));
13284 
13285         return (&zone->origin);
13286 }
13287 
13288 void
13289 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
13290         REQUIRE(DNS_ZONE_VALID(zone));
13291 
13292         LOCK_ZONE(zone);
13293         if (zone->task != NULL)
13294                 isc_task_detach(&zone->task);
13295         isc_task_attach(task, &zone->task);
13296         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13297         if (zone->db != NULL)
13298                 dns_db_settask(zone->db, zone->task);
13299         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13300         UNLOCK_ZONE(zone);
13301 }
13302 
13303 void
13304 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
13305         REQUIRE(DNS_ZONE_VALID(zone));
13306         isc_task_attach(zone->task, target);
13307 }
13308 
13309 void
13310 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
13311         REQUIRE(DNS_ZONE_VALID(zone));
13312 
13313         if (idlein == 0)
13314                 idlein = DNS_DEFAULT_IDLEIN;
13315         zone->idlein = idlein;
13316 }
13317 
13318 isc_uint32_t
13319 dns_zone_getidlein(dns_zone_t *zone) {
13320         REQUIRE(DNS_ZONE_VALID(zone));
13321 
13322         return (zone->idlein);
13323 }
13324 
13325 void
13326 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
13327         REQUIRE(DNS_ZONE_VALID(zone));
13328 
13329         zone->idleout = idleout;
13330 }
13331 
13332 isc_uint32_t
13333 dns_zone_getidleout(dns_zone_t *zone) {
13334         REQUIRE(DNS_ZONE_VALID(zone));
13335 
13336         return (zone->idleout);
13337 }
13338 
13339 static void
13340 notify_done(isc_task_t *task, isc_event_t *event) {
13341         dns_requestevent_t *revent = (dns_requestevent_t *)event;
13342         dns_notify_t *notify;
13343         isc_result_t result;
13344         dns_message_t *message = NULL;
13345         isc_buffer_t buf;
13346         char rcode[128];
13347         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
13348 
13349         UNUSED(task);
13350 
13351         notify = event->ev_arg;
13352         REQUIRE(DNS_NOTIFY_VALID(notify));
13353         INSIST(task == notify->zone->task);
13354 
13355         isc_buffer_init(&buf, rcode, sizeof(rcode));
13356         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
13357 
13358         result = revent->result;
13359         if (result == ISC_R_SUCCESS)
13360                 result = dns_message_create(notify->zone->mctx,
13361                                             DNS_MESSAGE_INTENTPARSE, &message);
13362         if (result == ISC_R_SUCCESS)
13363                 result = dns_request_getresponse(revent->request, message,
13364                                         DNS_MESSAGEPARSE_PRESERVEORDER);
13365         if (result == ISC_R_SUCCESS)
13366                 result = dns_rcode_totext(message->rcode, &buf);
13367         if (result == ISC_R_SUCCESS)
13368                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
13369                            "notify response from %s: %.*s",
13370                            addrbuf, (int)buf.used, rcode);
13371         else
13372                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
13373                            "notify to %s failed: %s", addrbuf,
13374                            dns_result_totext(result));
13375 
13376         /*
13377          * Old bind's return formerr if they see a soa record.  Retry w/o
13378          * the soa if we see a formerr and had sent a SOA.
13379          */
13380         isc_event_free(&event);
13381         if (message != NULL && message->rcode == dns_rcode_formerr &&
13382             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
13383                 isc_boolean_t startup;
13384 
13385                 notify->flags |= DNS_NOTIFY_NOSOA;
13386                 dns_request_destroy(&notify->request);
13387                 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
13388                 result = notify_send_queue(notify, startup);
13389                 if (result != ISC_R_SUCCESS)
13390                         notify_destroy(notify, ISC_FALSE);
13391         } else {
13392                 if (result == ISC_R_TIMEDOUT)
13393                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
13394                                    "notify to %s: retries exceeded", addrbuf);
13395                 notify_destroy(notify, ISC_FALSE);
13396         }
13397         if (message != NULL)
13398                 dns_message_destroy(&message);
13399 }
13400 
13401 struct secure_event {
13402         isc_event_t e;
13403         dns_db_t *db;
13404         isc_uint32_t serial;
13405 };
13406 
13407 static void
13408 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
13409         UNUSED(arg);
13410         dns_zone_log(zone, level, "%s", message);
13411 }
13412 
13413 static isc_result_t
13414 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
13415                     isc_uint32_t start, isc_uint32_t end,
13416                     dns_difftuple_t **soatuplep, dns_diff_t *diff)
13417 {
13418         isc_result_t result;
13419         dns_difftuple_t *tuple = NULL;
13420         dns_diffop_t op = DNS_DIFFOP_ADD;
13421         int n_soa = 0;
13422 
13423         REQUIRE(soatuplep != NULL);
13424 
13425         if (start == end)
13426                 return (DNS_R_UNCHANGED);
13427 
13428         CHECK(dns_journal_iter_init(journal, start, end));
13429         for (result = dns_journal_first_rr(journal);
13430              result == ISC_R_SUCCESS;
13431              result = dns_journal_next_rr(journal))
13432         {
13433                 dns_name_t *name = NULL;
13434                 isc_uint32_t ttl;
13435                 dns_rdata_t *rdata = NULL;
13436                 dns_journal_current_rr(journal, &name, &ttl, &rdata);
13437 
13438                 if (rdata->type == dns_rdatatype_soa) {
13439                         n_soa++;
13440                         if (n_soa == 2) {
13441                                 /*
13442                                  * Save the latest raw SOA record.
13443                                  */
13444                                 if (*soatuplep != NULL)
13445                                         dns_difftuple_free(soatuplep);
13446                                 CHECK(dns_difftuple_create(diff->mctx,
13447                                                            DNS_DIFFOP_ADD,
13448                                                            name, ttl, rdata,
13449                                                            soatuplep));
13450                         }
13451                         if (n_soa == 3)
13452                                 n_soa = 1;
13453                         continue;
13454                 }
13455 
13456                 /* Sanity. */
13457                 if (n_soa == 0) {
13458                         dns_zone_log(raw, ISC_LOG_ERROR,
13459                                      "corrupt journal file: '%s'\n",
13460                                      raw->journal);
13461                         return (ISC_R_FAILURE);
13462                 }
13463 
13464                 if (zone->privatetype != 0 &&
13465                     rdata->type == zone->privatetype)
13466                         continue;
13467 
13468                 if (rdata->type == dns_rdatatype_nsec ||
13469                     rdata->type == dns_rdatatype_rrsig ||
13470                     rdata->type == dns_rdatatype_nsec3 ||
13471                     rdata->type == dns_rdatatype_dnskey ||
13472                     rdata->type == dns_rdatatype_nsec3param)
13473                         continue;
13474 
13475                 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
13476 
13477                 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
13478                                            &tuple));
13479                 dns_diff_appendminimal(diff, &tuple);
13480         }
13481         if (result == ISC_R_NOMORE)
13482                 result = ISC_R_SUCCESS;
13483 
13484  failure:
13485         return(result);
13486 }
13487 
13488 static isc_result_t
13489 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
13490                dns_dbversion_t *secver, dns_difftuple_t **soatuple,
13491                dns_diff_t *diff)
13492 {
13493         isc_result_t result;
13494         dns_db_t *rawdb = NULL;
13495         dns_dbversion_t *rawver = NULL;
13496         dns_difftuple_t *tuple = NULL, *next;
13497         dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
13498         dns_rdata_soa_t oldsoa, newsoa;
13499 
13500         REQUIRE(DNS_ZONE_VALID(seczone));
13501         REQUIRE(soatuple != NULL && *soatuple == NULL);
13502 
13503         if (!seczone->sourceserialset)
13504                 return (DNS_R_UNCHANGED);
13505 
13506         dns_db_attach(raw->db, &rawdb);
13507         dns_db_currentversion(rawdb, &rawver);
13508         result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
13509         dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
13510         dns_db_detach(&rawdb);
13511 
13512         if (result != ISC_R_SUCCESS)
13513                 return (result);
13514 
13515         for (tuple = ISC_LIST_HEAD(diff->tuples);
13516              tuple != NULL;
13517              tuple = next)
13518         {
13519                 next = ISC_LIST_NEXT(tuple, link);
13520                 if (tuple->rdata.type == dns_rdatatype_nsec ||
13521                     tuple->rdata.type == dns_rdatatype_rrsig ||
13522                     tuple->rdata.type == dns_rdatatype_dnskey ||
13523                     tuple->rdata.type == dns_rdatatype_nsec3 ||
13524                     tuple->rdata.type == dns_rdatatype_nsec3param)
13525                 {
13526                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
13527                         dns_difftuple_free(&tuple);
13528                         continue;
13529                 }
13530                 if (tuple->rdata.type == dns_rdatatype_soa) {
13531                         if (tuple->op == DNS_DIFFOP_DEL) {
13532                                 INSIST(oldtuple == NULL);
13533                                 oldtuple = tuple;
13534                         }
13535                         if (tuple->op == DNS_DIFFOP_ADD) {
13536                                 INSIST(newtuple == NULL);
13537                                 newtuple = tuple;
13538                         }
13539                 }
13540         }
13541 
13542         if (oldtuple != NULL && newtuple != NULL) {
13543 
13544                 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
13545                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13546 
13547                 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
13548                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13549 
13550                 /*
13551                  * If the SOA records are the same except for the serial
13552                  * remove them from the diff.
13553                  */
13554                 if (oldsoa.refresh == newsoa.refresh &&
13555                     oldsoa.retry == newsoa.retry &&
13556                     oldsoa.minimum == newsoa.minimum &&
13557                     oldsoa.expire == newsoa.expire &&
13558                     dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
13559                     dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
13560                         ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
13561                         dns_difftuple_free(&oldtuple);
13562                         ISC_LIST_UNLINK(diff->tuples, newtuple, link);
13563                         dns_difftuple_free(&newtuple);
13564                 }
13565         }
13566 
13567         if (ISC_LIST_EMPTY(diff->tuples))
13568                 return (DNS_R_UNCHANGED);
13569 
13570         /*
13571          * If there are still SOA records in the diff they can now be removed
13572          * saving the new SOA record.
13573          */
13574         if (oldtuple != NULL) {
13575                 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
13576                 dns_difftuple_free(&oldtuple);
13577         }
13578 
13579         if (newtuple != NULL) {
13580                 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
13581                 *soatuple = newtuple;
13582         }
13583 
13584         return (ISC_R_SUCCESS);
13585 }
13586 
13587 static void
13588 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
13589         static char me[] = "receive_secure_serial";
13590         isc_result_t result = ISC_R_SUCCESS;
13591         dns_journal_t *rjournal = NULL;
13592         dns_journal_t *sjournal = NULL;
13593         isc_uint32_t start, end;
13594         dns_zone_t *zone;
13595         dns_difftuple_t *tuple = NULL, *soatuple = NULL;
13596         dns_update_log_t log = { update_log_cb, NULL };
13597         isc_time_t timenow;
13598 
13599         UNUSED(task);
13600 
13601         zone = event->ev_arg;
13602         end = ((struct secure_event *)event)->serial;
13603 
13604         ENTER;
13605 
13606         LOCK_ZONE(zone);
13607 
13608         /*
13609          * If we are already processing a receive secure serial event
13610          * for the zone, just queue the new one and exit.
13611          */
13612         if (zone->rss_event != NULL && zone->rss_event != event) {
13613                 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
13614                 UNLOCK_ZONE(zone);
13615                 return;
13616         }
13617 
13618  nextevent:
13619         if (zone->rss_event != NULL) {
13620                 INSIST(zone->rss_event == event);
13621                 UNLOCK_ZONE(zone);
13622         } else {
13623                 zone->rss_event = event;
13624                 dns_diff_init(zone->mctx, &zone->rss_diff);
13625 
13626                 /*
13627                  * zone->db may be NULL, if the load from disk failed.
13628                  */
13629                 result = ISC_R_SUCCESS;
13630                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13631                 if (zone->db != NULL)
13632                         dns_db_attach(zone->db, &zone->rss_db);
13633                 else
13634                         result = ISC_R_FAILURE;
13635                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13636 
13637                 if (result == ISC_R_SUCCESS && zone->raw != NULL)
13638                         dns_zone_attach(zone->raw, &zone->rss_raw);
13639                 else
13640                         result = ISC_R_FAILURE;
13641 
13642                 UNLOCK_ZONE(zone);
13643 
13644                 CHECK(result);
13645 
13646                 /*
13647                  * We first attempt to sync the raw zone to the secure zone
13648                  * by using the raw zone's journal, applying all the deltas
13649                  * from the latest source-serial of the secure zone up to
13650                  * the current serial number of the raw zone.
13651                  *
13652                  * If that fails, then we'll fall back to a direct comparison
13653                  * between raw and secure zones.
13654                  */
13655                 CHECK(dns_journal_open(zone->rss_raw->mctx,
13656                                        zone->rss_raw->journal,
13657                                        DNS_JOURNAL_WRITE, &rjournal));
13658 
13659                 result = dns_journal_open(zone->mctx, zone->journal,
13660                                           DNS_JOURNAL_READ, &sjournal);
13661                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
13662                         goto failure;
13663 
13664                 if (!dns_journal_get_sourceserial(rjournal, &start)) {
13665                         start = dns_journal_first_serial(rjournal);
13666                         dns_journal_set_sourceserial(rjournal, start);
13667                 }
13668                 if (sjournal != NULL) {
13669                         isc_uint32_t serial;
13670                         /*
13671                          * We read the secure journal first, if that
13672                          * exists use its value provided it is greater
13673                          * that from the raw journal.
13674                          */
13675                         if (dns_journal_get_sourceserial(sjournal, &serial)) {
13676                                 if (isc_serial_gt(serial, start))
13677                                         start = serial;
13678                         }
13679                         dns_journal_destroy(&sjournal);
13680                 }
13681 
13682                 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
13683                 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
13684 
13685                 /*
13686                  * Try to apply diffs from the raw zone's journal to the secure
13687                  * zone.  If that fails, we recover by syncing up the databases
13688                  * directly.
13689                  */
13690                 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
13691                                              start, end, &soatuple,
13692                                              &zone->rss_diff);
13693                 if (result == DNS_R_UNCHANGED)
13694                         goto failure;
13695                 else if (result != ISC_R_SUCCESS)
13696                         CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
13697                                              zone->rss_oldver, &soatuple,
13698                                              &zone->rss_diff));
13699 
13700                 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
13701                                      zone->rss_newver));
13702 
13703                 if (soatuple != NULL) {
13704                         isc_uint32_t oldserial, newserial, desired;
13705 
13706                         CHECK(dns_db_createsoatuple(zone->rss_db,
13707                                                     zone->rss_oldver,
13708                                                     zone->rss_diff.mctx,
13709                                                     DNS_DIFFOP_DEL, &tuple));
13710                         oldserial = dns_soa_getserial(&tuple->rdata);
13711                         newserial = desired =
13712                                     dns_soa_getserial(&soatuple->rdata);
13713                         if (!isc_serial_gt(newserial, oldserial)) {
13714                                 newserial = oldserial + 1;
13715                                 if (newserial == 0)
13716                                         newserial++;
13717                                 dns_soa_setserial(newserial, &soatuple->rdata);
13718                         }
13719                         CHECK(do_one_tuple(&tuple, zone->rss_db,
13720                                            zone->rss_newver, &zone->rss_diff));
13721                         CHECK(do_one_tuple(&soatuple, zone->rss_db,
13722                                            zone->rss_newver, &zone->rss_diff));
13723                         dns_zone_log(zone, ISC_LOG_INFO,
13724                                      "serial %u (unsigned %u)",
13725                                      newserial, desired);
13726                 } else
13727                         CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
13728                                                 &zone->rss_diff, zone->mctx,
13729                                                 zone->updatemethod));
13730 
13731         }
13732         result = dns_update_signaturesinc(&log, zone, zone->rss_db,
13733                                           zone->rss_oldver, zone->rss_newver,
13734                                           &zone->rss_diff,
13735                                           zone->sigvalidityinterval,
13736                                           &zone->rss_state);
13737         if (result == DNS_R_CONTINUE) {
13738                 if (rjournal != NULL)
13739                         dns_journal_destroy(&rjournal);
13740                 isc_task_send(task, &event);
13741                 fprintf(stderr, "looping on dns_update_signaturesinc\n");
13742                 return;
13743         }
13744         if (result != ISC_R_SUCCESS)
13745                 goto failure;
13746 
13747         if (rjournal == NULL)
13748                 CHECK(dns_journal_open(zone->rss_raw->mctx,
13749                                        zone->rss_raw->journal,
13750                                        DNS_JOURNAL_WRITE, &rjournal));
13751         CHECK(zone_journal(zone, &zone->rss_diff, &end,
13752                            "receive_secure_serial"));
13753 
13754         dns_journal_set_sourceserial(rjournal, end);
13755         dns_journal_commit(rjournal);
13756 
13757         LOCK_ZONE(zone);
13758         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13759 
13760         zone->sourceserial = end;
13761         zone->sourceserialset = ISC_TRUE;
13762         zone_needdump(zone, DNS_DUMP_DELAY);
13763 
13764         TIME_NOW(&timenow);
13765         zone_settimer(zone, &timenow);
13766         UNLOCK_ZONE(zone);
13767 
13768         dns_db_closeversion(zone->rss_db, &zone->rss_oldver, ISC_FALSE);
13769         dns_db_closeversion(zone->rss_db, &zone->rss_newver, ISC_TRUE);
13770 
13771  failure:
13772         isc_event_free(&zone->rss_event);
13773         event = ISC_LIST_HEAD(zone->rss_events);
13774 
13775         if (zone->rss_raw != NULL)
13776                 dns_zone_detach(&zone->rss_raw);
13777         if (result != ISC_R_SUCCESS)
13778                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
13779                              dns_result_totext(result));
13780         if (tuple != NULL)
13781                 dns_difftuple_free(&tuple);
13782         if (soatuple != NULL)
13783                 dns_difftuple_free(&soatuple);
13784         if (zone->rss_db != NULL) {
13785                 if (zone->rss_oldver != NULL)
13786                         dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
13787                                             ISC_FALSE);
13788                 if (zone->rss_newver != NULL)
13789                         dns_db_closeversion(zone->rss_db, &zone->rss_newver,
13790                                             ISC_FALSE);
13791                 dns_db_detach(&zone->rss_db);
13792         }
13793         INSIST(zone->rss_oldver == NULL);
13794         INSIST(zone->rss_newver == NULL);
13795         if (rjournal != NULL)
13796                 dns_journal_destroy(&rjournal);
13797         dns_diff_clear(&zone->rss_diff);
13798 
13799         if (event != NULL) {
13800                 LOCK_ZONE(zone);
13801                 INSIST(zone->irefs > 1);
13802                 zone->irefs--;
13803                 goto nextevent;
13804         }
13805         dns_zone_idetach(&zone);
13806 }
13807 
13808 static isc_result_t
13809 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
13810         isc_event_t *e;
13811         dns_zone_t *dummy = NULL;
13812 
13813         e = isc_event_allocate(zone->secure->mctx, zone,
13814                                DNS_EVENT_ZONESECURESERIAL,
13815                                receive_secure_serial, zone->secure,
13816                                sizeof(struct secure_event));
13817         if (e == NULL)
13818                 return (ISC_R_NOMEMORY);
13819         ((struct secure_event *)e)->serial = serial;
13820         INSIST(LOCKED_ZONE(zone->secure));
13821         zone_iattach(zone->secure, &dummy);
13822         isc_task_send(zone->secure->task, &e);
13823 
13824         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13825         return (ISC_R_SUCCESS);
13826 }
13827 
13828 static isc_result_t
13829 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
13830                dns_rdataset_t *rdataset, isc_uint32_t oldserial)
13831 {
13832         dns_rdata_soa_t soa;
13833         dns_rdata_t rdata = DNS_RDATA_INIT;
13834         dns_rdatalist_t temprdatalist;
13835         dns_rdataset_t temprdataset;
13836         isc_buffer_t b;
13837         isc_result_t result;
13838         unsigned char buf[DNS_SOA_BUFFERSIZE];
13839         dns_fixedname_t fixed;
13840         dns_name_t *name;
13841 
13842         result = dns_rdataset_first(rdataset);
13843         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13844         dns_rdataset_current(rdataset, &rdata);
13845         result = dns_rdata_tostruct(&rdata, &soa, NULL);
13846         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13847 
13848         if (isc_serial_gt(soa.serial, oldserial))
13849                 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13850                                            NULL));
13851         /*
13852          * Always bump the serial.
13853          */
13854         oldserial++;
13855         if (oldserial == 0)
13856                 oldserial++;
13857         soa.serial = oldserial;
13858 
13859         /*
13860          * Construct a replacement rdataset.
13861          */
13862         dns_rdata_reset(&rdata);
13863         isc_buffer_init(&b, buf, sizeof(buf));
13864         result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13865                                       dns_rdatatype_soa, &soa, &b);
13866         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13867         dns_rdatalist_init(&temprdatalist);
13868         temprdatalist.rdclass = rdata.rdclass;
13869         temprdatalist.type = rdata.type;
13870         temprdatalist.ttl = rdataset->ttl;
13871         ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13872 
13873         dns_rdataset_init(&temprdataset);
13874         result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13875         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13876         dns_fixedname_init(&fixed);
13877         name = dns_fixedname_name(&fixed);
13878         dns_rbtnode_nodename(node, name);
13879         dns_rdataset_getownercase(rdataset, name);
13880         dns_rdataset_setownercase(&temprdataset, name);
13881         return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13882                                    0, NULL));
13883 }
13884 
13885 /*
13886  * This function should populate an nsec3paramlist_t with the
13887  * nsecparam_t data from a zone.
13888  */
13889 static isc_result_t
13890 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13891         isc_result_t result;
13892         dns_dbnode_t *node = NULL;
13893         dns_rdataset_t rdataset, prdataset;
13894         dns_dbversion_t *version = NULL;
13895         nsec3param_t *nsec3param = NULL;
13896         nsec3param_t *nsec3p = NULL;
13897         nsec3param_t *next;
13898         dns_db_t *db = NULL;
13899         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13900 
13901         REQUIRE(DNS_ZONE_VALID(zone));
13902         REQUIRE(nsec3list != NULL);
13903         REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13904 
13905         dns_rdataset_init(&rdataset);
13906         dns_rdataset_init(&prdataset);
13907 
13908         dns_db_attach(zone->db, &db);
13909         CHECK(dns_db_getoriginnode(db, &node));
13910 
13911         dns_db_currentversion(db, &version);
13912         result = dns_db_findrdataset(db, node, version,
13913                                      dns_rdatatype_nsec3param,
13914                                      dns_rdatatype_none, 0, &rdataset, NULL);
13915 
13916         if (result != ISC_R_SUCCESS)
13917                 goto getprivate;
13918 
13919         /*
13920          * walk nsec3param rdataset making a list of parameters (note that
13921          * multiple simultaneous nsec3 chains are annoyingly legal -- this
13922          * is why we use an nsec3list, even tho we will usually only have
13923          * one)
13924          */
13925         for (result = dns_rdataset_first(&rdataset);
13926              result == ISC_R_SUCCESS;
13927              result = dns_rdataset_next(&rdataset))
13928         {
13929                 dns_rdata_t rdata = DNS_RDATA_INIT;
13930                 dns_rdata_t private = DNS_RDATA_INIT;
13931 
13932                 dns_rdataset_current(&rdataset, &rdata);
13933                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13934                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13935                               "looping through nsec3param data");
13936                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13937                 if (nsec3param == NULL)
13938                         CHECK(ISC_R_NOMEMORY);
13939                 ISC_LINK_INIT(nsec3param, link);
13940 
13941                 /*
13942                  * now transfer the data from the rdata to
13943                  * the nsec3param
13944                  */
13945                 dns_nsec3param_toprivate(&rdata, &private,
13946                                          zone->privatetype, nsec3param->data,
13947                                          sizeof(nsec3param->data));
13948                 nsec3param->length = private.length;
13949                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13950         }
13951 
13952  getprivate:
13953         result = dns_db_findrdataset(db, node, version, zone->privatetype,
13954                                      dns_rdatatype_none, 0, &prdataset, NULL);
13955         if (result != ISC_R_SUCCESS)
13956                 goto done;
13957 
13958         /*
13959          * walk private type records, converting them to nsec3 parameters
13960          * using dns_nsec3param_fromprivate(), do the right thing based on
13961          * CREATE and REMOVE flags
13962          */
13963         for (result = dns_rdataset_first(&prdataset);
13964              result == ISC_R_SUCCESS;
13965              result = dns_rdataset_next(&prdataset))
13966         {
13967                 dns_rdata_t rdata = DNS_RDATA_INIT;
13968                 dns_rdata_t private = DNS_RDATA_INIT;
13969 
13970                 dns_rdataset_current(&prdataset, &private);
13971                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13972                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13973                               "looping through nsec3param private data");
13974 
13975                 /*
13976                  * Do we have a valid private record?
13977                  */
13978                 if (!dns_nsec3param_fromprivate(&private, &rdata,
13979                                                 buf, sizeof(buf)))
13980                         continue;
13981 
13982                 /*
13983                  * Remove any NSEC3PARAM records scheduled to be removed.
13984                  */
13985                 if (NSEC3REMOVE(rdata.data[1])) {
13986                         /*
13987                          * Zero out the flags.
13988                          */
13989                         rdata.data[1] = 0;
13990 
13991                         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13992                              nsec3p != NULL;
13993                              nsec3p = next)
13994                         {
13995                                 next = ISC_LIST_NEXT(nsec3p, link);
13996 
13997                                 if (nsec3p->length == rdata.length + 1 &&
13998                                     memcmp(rdata.data, nsec3p->data + 1,
13999                                            nsec3p->length - 1) == 0) {
14000                                         ISC_LIST_UNLINK(*nsec3list,
14001                                                         nsec3p, link);
14002                                         isc_mem_put(zone->mctx, nsec3p,
14003                                                     sizeof(nsec3param_t));
14004                                 }
14005                         }
14006                         continue;
14007                 }
14008 
14009                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
14010                 if (nsec3param == NULL)
14011                         CHECK(ISC_R_NOMEMORY);
14012                 ISC_LINK_INIT(nsec3param, link);
14013 
14014                 /*
14015                  * Copy the remaining private records so the nsec/nsec3
14016                  * chain gets created.
14017                  */
14018                 INSIST(private.length <= sizeof(nsec3param->data));
14019                 memmove(nsec3param->data, private.data, private.length);
14020                 nsec3param->length = private.length;
14021                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
14022         }
14023 
14024  done:
14025         if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
14026                 result = ISC_R_SUCCESS;
14027 
14028  failure:
14029         if (node != NULL)
14030                 dns_db_detachnode(db, &node);
14031         if (version != NULL)
14032                 dns_db_closeversion(db, &version, ISC_FALSE);
14033         if (db != NULL)
14034                 dns_db_detach(&db);
14035         if (dns_rdataset_isassociated(&rdataset))
14036                 dns_rdataset_disassociate(&rdataset);
14037         if (dns_rdataset_isassociated(&prdataset))
14038                 dns_rdataset_disassociate(&prdataset);
14039         return (result);
14040 }
14041 
14042 /*
14043  * Walk the list of the nsec3 chains desired for the zone, converting
14044  * parameters to private type records using dns_nsec3param_toprivate(),
14045  * and insert them into the new zone db.
14046  */
14047 static isc_result_t
14048 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14049                    nsec3paramlist_t *nsec3list)
14050 {
14051         isc_result_t result;
14052         dns_diff_t diff;
14053         dns_rdata_t rdata;
14054         nsec3param_t *nsec3p = NULL;
14055         nsec3param_t *next;
14056 
14057         REQUIRE(DNS_ZONE_VALID(zone));
14058         REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
14059 
14060         dns_diff_init(zone->mctx, &diff);
14061 
14062         /*
14063          * Loop through the list of private-type records, set the INITIAL
14064          * and CREATE flags, and the add the record to the apex of the tree
14065          * in db.
14066          */
14067         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
14068              nsec3p != NULL;
14069              nsec3p = next)
14070         {
14071                 next = ISC_LIST_NEXT(nsec3p, link);
14072                 dns_rdata_init(&rdata);
14073                 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
14074                 rdata.length = nsec3p->length;
14075                 rdata.data = nsec3p->data;
14076                 rdata.type = zone->privatetype;
14077                 rdata.rdclass = zone->rdclass;
14078                 CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
14079                                     &zone->origin, 0, &rdata));
14080         }
14081 
14082         result = ISC_R_SUCCESS;
14083 
14084 failure:
14085         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
14086              nsec3p != NULL;
14087              nsec3p = next)
14088         {
14089                 next = ISC_LIST_NEXT(nsec3p, link);
14090                 ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
14091                 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
14092         }
14093 
14094         dns_diff_clear(&diff);
14095         return (result);
14096 }
14097 
14098 static void
14099 receive_secure_db(isc_task_t *task, isc_event_t *event) {
14100         isc_result_t result;
14101         dns_zone_t *zone;
14102         dns_db_t *rawdb, *db = NULL;
14103         dns_dbnode_t *rawnode = NULL, *node = NULL;
14104         dns_fixedname_t fname;
14105         dns_name_t *name;
14106         dns_dbiterator_t *dbiterator = NULL;
14107         dns_rdatasetiter_t *rdsit = NULL;
14108         dns_rdataset_t rdataset;
14109         dns_dbversion_t *version = NULL;
14110         isc_time_t loadtime;
14111         unsigned int oldserial = 0;
14112         isc_boolean_t have_oldserial = ISC_FALSE;
14113         nsec3paramlist_t nsec3list;
14114 
14115         UNUSED(task);
14116 
14117         ISC_LIST_INIT(nsec3list);
14118 
14119         zone = event->ev_arg;
14120         rawdb = ((struct secure_event *)event)->db;
14121         isc_event_free(&event);
14122 
14123         dns_fixedname_init(&fname);
14124         name = dns_fixedname_name(&fname);
14125         dns_rdataset_init(&rdataset);
14126 
14127         LOCK_ZONE(zone);
14128         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
14129                 result = ISC_R_SHUTTINGDOWN;
14130                 goto failure;
14131         }
14132 
14133         TIME_NOW(&loadtime);
14134         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14135         if (zone->db != NULL) {
14136                 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
14137                 if (result == ISC_R_SUCCESS)
14138                         have_oldserial = ISC_TRUE;
14139 
14140                 /*
14141                  * assemble nsec3parameters from the old zone, and set a flag
14142                  * if any are found
14143                  */
14144                 result = save_nsec3param(zone, &nsec3list);
14145                 if (result != ISC_R_SUCCESS) {
14146                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14147                         goto failure;
14148                 }
14149         }
14150         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14151 
14152         result = dns_db_create(zone->mctx, zone->db_argv[0],
14153                                &zone->origin, dns_dbtype_zone, zone->rdclass,
14154                                zone->db_argc - 1, zone->db_argv + 1, &db);
14155         if (result != ISC_R_SUCCESS)
14156                 goto failure;
14157 
14158         result = dns_db_newversion(db, &version);
14159         if (result != ISC_R_SUCCESS)
14160                 goto failure;
14161 
14162         result = dns_db_createiterator(rawdb, 0, &dbiterator);
14163         if (result != ISC_R_SUCCESS)
14164                 goto failure;
14165 
14166         for (result = dns_dbiterator_first(dbiterator);
14167              result == ISC_R_SUCCESS;
14168              result = dns_dbiterator_next(dbiterator)) {
14169                 result = dns_dbiterator_current(dbiterator, &rawnode, name);
14170                 if (result != ISC_R_SUCCESS)
14171                         continue;
14172 
14173                 result = dns_db_findnode(db, name, ISC_TRUE, &node);
14174                 if (result != ISC_R_SUCCESS)
14175                         goto failure;
14176 
14177                 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
14178                 if (result != ISC_R_SUCCESS)
14179                         goto failure;
14180 
14181                 for (result = dns_rdatasetiter_first(rdsit);
14182                      result == ISC_R_SUCCESS;
14183                      result = dns_rdatasetiter_next(rdsit)) {
14184                         dns_rdatasetiter_current(rdsit, &rdataset);
14185                         if (rdataset.type == dns_rdatatype_nsec ||
14186                             rdataset.type == dns_rdatatype_rrsig ||
14187                             rdataset.type == dns_rdatatype_nsec3 ||
14188                             rdataset.type == dns_rdatatype_dnskey ||
14189                             rdataset.type == dns_rdatatype_nsec3param) {
14190                                 dns_rdataset_disassociate(&rdataset);
14191                                 continue;
14192                         }
14193                         if (rdataset.type == dns_rdatatype_soa &&
14194                             have_oldserial) {
14195                                 result = checkandaddsoa(db, node, version,
14196                                                         &rdataset, oldserial);
14197                         } else
14198                                 result = dns_db_addrdataset(db, node, version,
14199                                                             0, &rdataset, 0,
14200                                                             NULL);
14201                         if (result != ISC_R_SUCCESS)
14202                                 goto failure;
14203 
14204                         dns_rdataset_disassociate(&rdataset);
14205                 }
14206                 dns_rdatasetiter_destroy(&rdsit);
14207                 dns_db_detachnode(rawdb, &rawnode);
14208                 dns_db_detachnode(db, &node);
14209         }
14210 
14211         /*
14212          * Call restore_nsec3param() to create private-type records from
14213          * the old nsec3 parameters and insert them into db
14214          */
14215         if (!ISC_LIST_EMPTY(nsec3list))
14216                 restore_nsec3param(zone, db, version, &nsec3list);
14217 
14218         dns_db_closeversion(db, &version, ISC_TRUE);
14219 
14220         /*
14221          * Lock hierarchy: zmgr, zone, raw.
14222          */
14223         INSIST(zone != zone->raw);
14224         LOCK_ZONE(zone->raw);
14225         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14226         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14227         zone_needdump(zone, 0); /* XXXMPA */
14228         UNLOCK_ZONE(zone->raw);
14229 
14230  failure:
14231         UNLOCK_ZONE(zone);
14232         if (result != ISC_R_SUCCESS)
14233                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
14234                              dns_result_totext(result));
14235 
14236         while (!ISC_LIST_EMPTY(nsec3list)) {
14237                 nsec3param_t *nsec3p;
14238                 nsec3p = ISC_LIST_HEAD(nsec3list);
14239                 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
14240                 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
14241         }
14242         if (dns_rdataset_isassociated(&rdataset))
14243                 dns_rdataset_disassociate(&rdataset);
14244         if (db != NULL) {
14245                 if (node != NULL)
14246                         dns_db_detachnode(db, &node);
14247                 if (version != NULL)
14248                         dns_db_closeversion(db, &version, ISC_FALSE);
14249                 dns_db_detach(&db);
14250         }
14251         if (rawnode != NULL)
14252                 dns_db_detachnode(rawdb, &rawnode);
14253         dns_db_detach(&rawdb);
14254         if (dbiterator != NULL)
14255                 dns_dbiterator_destroy(&dbiterator);
14256         dns_zone_idetach(&zone);
14257 
14258         INSIST(version == NULL);
14259 }
14260 
14261 static isc_result_t
14262 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
14263         isc_event_t *e;
14264         dns_db_t *dummy = NULL;
14265         dns_zone_t *secure = NULL;
14266 
14267         e = isc_event_allocate(zone->secure->mctx, zone,
14268                                DNS_EVENT_ZONESECUREDB,
14269                                receive_secure_db, zone->secure,
14270                                sizeof(struct secure_event));
14271         if (e == NULL)
14272                 return (ISC_R_NOMEMORY);
14273         dns_db_attach(db, &dummy);
14274         ((struct secure_event *)e)->db = dummy;
14275         INSIST(LOCKED_ZONE(zone->secure));
14276         zone_iattach(zone->secure, &secure);
14277         isc_task_send(zone->secure->task, &e);
14278         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
14279         return (ISC_R_SUCCESS);
14280 }
14281 
14282 isc_result_t
14283 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
14284         isc_result_t result;
14285         dns_zone_t *secure = NULL;
14286 
14287         REQUIRE(DNS_ZONE_VALID(zone));
14288  again:
14289         LOCK_ZONE(zone);
14290         if (inline_raw(zone)) {
14291                 secure = zone->secure;
14292                 INSIST(secure != zone);
14293                 TRYLOCK_ZONE(result, secure);
14294                 if (result != ISC_R_SUCCESS) {
14295                         UNLOCK_ZONE(zone);
14296                         secure = NULL;
14297 #if ISC_PLATFORM_USETHREADS
14298                         isc_thread_yield();
14299 #endif
14300                         goto again;
14301                 }
14302         }
14303         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
14304         result = zone_replacedb(zone, db, dump);
14305         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
14306         if (secure != NULL)
14307                 UNLOCK_ZONE(secure);
14308         UNLOCK_ZONE(zone);
14309         return (result);
14310 }
14311 
14312 static isc_result_t
14313 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
14314         dns_dbversion_t *ver;
14315         isc_result_t result;
14316         unsigned int soacount = 0;
14317         unsigned int nscount = 0;
14318 
14319         /*
14320          * 'zone' and 'zonedb' locked by caller.
14321          */
14322         REQUIRE(DNS_ZONE_VALID(zone));
14323         REQUIRE(LOCKED_ZONE(zone));
14324         if (inline_raw(zone))
14325                 REQUIRE(LOCKED_ZONE(zone->secure));
14326 
14327         result = dns_db_rpz_ready(db);
14328         if (result != ISC_R_SUCCESS)
14329                 return (result);
14330 
14331         result = zone_get_from_db(zone, db, &nscount, &soacount,
14332                                   NULL, NULL, NULL, NULL, NULL, NULL);
14333         if (result == ISC_R_SUCCESS) {
14334                 if (soacount != 1) {
14335                         dns_zone_log(zone, ISC_LOG_ERROR,
14336                                      "has %d SOA records", soacount);
14337                         result = DNS_R_BADZONE;
14338                 }
14339                 if (nscount == 0 && zone->type != dns_zone_key) {
14340                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
14341                         result = DNS_R_BADZONE;
14342                 }
14343                 if (result != ISC_R_SUCCESS)
14344                         return (result);
14345         } else {
14346                 dns_zone_log(zone, ISC_LOG_ERROR,
14347                             "retrieving SOA and NS records failed: %s",
14348                             dns_result_totext(result));
14349                 return (result);
14350         }
14351 
14352         result = check_nsec3param(zone, db);
14353         if (result != ISC_R_SUCCESS)
14354                 return (result);
14355 
14356         ver = NULL;
14357         dns_db_currentversion(db, &ver);
14358 
14359         /*
14360          * The initial version of a slave zone is always dumped;
14361          * subsequent versions may be journaled instead if this
14362          * is enabled in the configuration.
14363          */
14364         if (zone->db != NULL && zone->journal != NULL &&
14365             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
14366             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
14367         {
14368                 isc_uint32_t serial, oldserial;
14369 
14370                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
14371 
14372                 result = dns_db_getsoaserial(db, ver, &serial);
14373                 if (result != ISC_R_SUCCESS) {
14374                         dns_zone_log(zone, ISC_LOG_ERROR,
14375                                      "ixfr-from-differences: unable to get "
14376                                      "new serial");
14377                         goto fail;
14378                 }
14379 
14380                 /*
14381                  * This is checked in zone_postload() for master zones.
14382                  */
14383                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
14384                                           &oldserial, NULL, NULL, NULL, NULL,
14385                                           NULL);
14386                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14387                 RUNTIME_CHECK(soacount > 0U);
14388                 if ((zone->type == dns_zone_slave ||
14389                      (zone->type == dns_zone_redirect &&
14390                       zone->masters != NULL))
14391                     && !isc_serial_gt(serial, oldserial)) {
14392                         isc_uint32_t serialmin, serialmax;
14393                         serialmin = (oldserial + 1) & 0xffffffffU;
14394                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
14395                         dns_zone_log(zone, ISC_LOG_ERROR,
14396                                      "ixfr-from-differences: failed: "
14397                                      "new serial (%u) out of range [%u - %u]",
14398                                      serial, serialmin, serialmax);
14399                         result = ISC_R_RANGE;
14400                         goto fail;
14401                 }
14402 
14403                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
14404                                      zone->journal);
14405                 if (result != ISC_R_SUCCESS)
14406                         goto fail;
14407                 if (dump)
14408                         zone_needdump(zone, DNS_DUMP_DELAY);
14409                 else if (zone->journalsize != -1) {
14410                         result = dns_journal_compact(zone->mctx, zone->journal,
14411                                                      serial, zone->journalsize);
14412                         switch (result) {
14413                         case ISC_R_SUCCESS:
14414                         case ISC_R_NOSPACE:
14415                         case ISC_R_NOTFOUND:
14416                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
14417                                              "dns_journal_compact: %s",
14418                                              dns_result_totext(result));
14419                                 break;
14420                         default:
14421                                 dns_zone_log(zone, ISC_LOG_ERROR,
14422                                              "dns_journal_compact failed: %s",
14423                                              dns_result_totext(result));
14424                                 break;
14425                         }
14426                 }
14427                 if (zone->type == dns_zone_master && inline_raw(zone))
14428                         zone_send_secureserial(zone, serial);
14429         } else {
14430                 if (dump && zone->masterfile != NULL) {
14431                         /*
14432                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
14433                          * to keep the old masterfile.
14434                          */
14435                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
14436                             remove(zone->masterfile) < 0 && errno != ENOENT) {
14437                                 char strbuf[ISC_STRERRORSIZE];
14438                                 isc__strerror(errno, strbuf, sizeof(strbuf));
14439                                 isc_log_write(dns_lctx,
14440                                               DNS_LOGCATEGORY_GENERAL,
14441                                               DNS_LOGMODULE_ZONE,
14442                                               ISC_LOG_WARNING,
14443                                               "unable to remove masterfile "
14444                                               "'%s': '%s'",
14445                                               zone->masterfile, strbuf);
14446                         }
14447                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
14448                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
14449                         else
14450                                 zone_needdump(zone, 0);
14451                 }
14452                 if (dump && zone->journal != NULL) {
14453                         /*
14454                          * The in-memory database just changed, and
14455                          * because 'dump' is set, it didn't change by
14456                          * being loaded from disk.  Also, we have not
14457                          * journaled diffs for this change.
14458                          * Therefore, the on-disk journal is missing
14459                          * the deltas for this change.  Since it can
14460                          * no longer be used to bring the zone
14461                          * up-to-date, it is useless and should be
14462                          * removed.
14463                          */
14464                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14465                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14466                                       "removing journal file");
14467                         if (remove(zone->journal) < 0 && errno != ENOENT) {
14468                                 char strbuf[ISC_STRERRORSIZE];
14469                                 isc__strerror(errno, strbuf, sizeof(strbuf));
14470                                 isc_log_write(dns_lctx,
14471                                               DNS_LOGCATEGORY_GENERAL,
14472                                               DNS_LOGMODULE_ZONE,
14473                                               ISC_LOG_WARNING,
14474                                               "unable to remove journal "
14475                                               "'%s': '%s'",
14476                                               zone->journal, strbuf);
14477                         }
14478                 }
14479 
14480                 if (inline_raw(zone))
14481                         zone_send_securedb(zone, db);
14482         }
14483 
14484         dns_db_closeversion(db, &ver, ISC_FALSE);
14485 
14486         dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
14487 
14488         if (zone->db != NULL)
14489                 zone_detachdb(zone);
14490         zone_attachdb(zone, db);
14491         dns_db_settask(zone->db, zone->task);
14492         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
14493         return (ISC_R_SUCCESS);
14494 
14495  fail:
14496         dns_db_closeversion(db, &ver, ISC_FALSE);
14497         return (result);
14498 }
14499 
14500 /* The caller must hold the dblock as a writer. */
14501 static inline void
14502 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
14503         REQUIRE(zone->db == NULL && db != NULL);
14504 
14505         dns_db_attach(db, &zone->db);
14506         if (zone->acache != NULL) {
14507                 isc_result_t result;
14508                 result = dns_acache_setdb(zone->acache, db);
14509                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
14510                         UNEXPECTED_ERROR(__FILE__, __LINE__,
14511                                          "dns_acache_setdb() failed: %s",
14512                                          isc_result_totext(result));
14513                 }
14514         }
14515 }
14516 
14517 /* The caller must hold the dblock as a writer. */
14518 static inline void
14519 zone_detachdb(dns_zone_t *zone) {
14520         REQUIRE(zone->db != NULL);
14521 
14522         if (zone->acache != NULL)
14523                 (void)dns_acache_putdb(zone->acache, zone->db);
14524         dns_db_detach(&zone->db);
14525 }
14526 
14527 static void
14528 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
14529         isc_time_t now;
14530         isc_boolean_t again = ISC_FALSE;
14531         unsigned int soacount;
14532         unsigned int nscount;
14533         isc_uint32_t serial, refresh, retry, expire, minimum;
14534         isc_result_t xfrresult = result;
14535         isc_boolean_t free_needed;
14536         dns_zone_t *secure = NULL;
14537 
14538         REQUIRE(DNS_ZONE_VALID(zone));
14539 
14540         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14541                      "zone transfer finished: %s", dns_result_totext(result));
14542 
14543         /*
14544          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
14545          * could result in a deadlock due to a LOR so we will spin if we
14546          * can't obtain the both locks.
14547          */
14548  again:
14549         LOCK_ZONE(zone);
14550         if (inline_raw(zone)) {
14551                 secure = zone->secure;
14552                 INSIST(secure != zone);
14553                 TRYLOCK_ZONE(result, secure);
14554                 if (result != ISC_R_SUCCESS) {
14555                         UNLOCK_ZONE(zone);
14556                         secure = NULL;
14557 #if ISC_PLATFORM_USETHREADS
14558                         isc_thread_yield();
14559 #endif
14560                         goto again;
14561                 }
14562         }
14563 
14564         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
14565         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14566         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14567 
14568         TIME_NOW(&now);
14569         switch (result) {
14570         case ISC_R_SUCCESS:
14571                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14572                 /*FALLTHROUGH*/
14573         case DNS_R_UPTODATE:
14574                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
14575                 /*
14576                  * Has the zone expired underneath us?
14577                  */
14578                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14579                 if (zone->db == NULL) {
14580                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14581                         goto same_master;
14582                 }
14583 
14584                 /*
14585                  * Update the zone structure's data from the actual
14586                  * SOA received.
14587                  */
14588                 nscount = 0;
14589                 soacount = 0;
14590                 INSIST(zone->db != NULL);
14591                 result = zone_get_from_db(zone, zone->db, &nscount,
14592                                           &soacount, &serial, &refresh,
14593                                           &retry, &expire, &minimum, NULL);
14594                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14595                 if (result == ISC_R_SUCCESS) {
14596                         if (soacount != 1)
14597                                 dns_zone_log(zone, ISC_LOG_ERROR,
14598                                              "transferred zone "
14599                                              "has %d SOA record%s", soacount,
14600                                              (soacount != 0) ? "s" : "");
14601                         if (nscount == 0) {
14602                                 dns_zone_log(zone, ISC_LOG_ERROR,
14603                                              "transferred zone "
14604                                              "has no NS records");
14605                                 if (DNS_ZONE_FLAG(zone,
14606                                                   DNS_ZONEFLG_HAVETIMERS)) {
14607                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
14608                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
14609                                 }
14610                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14611                                 zone_unload(zone);
14612                                 goto next_master;
14613                         }
14614                         zone->refresh = RANGE(refresh, zone->minrefresh,
14615                                               zone->maxrefresh);
14616                         zone->retry = RANGE(retry, zone->minretry,
14617                                             zone->maxretry);
14618                         zone->expire = RANGE(expire,
14619                                              zone->refresh + zone->retry,
14620                                              DNS_MAX_EXPIRE);
14621                         zone->minimum = minimum;
14622                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14623                 }
14624 
14625                 /*
14626                  * Set our next update/expire times.
14627                  */
14628                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14629                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14630                         zone->refreshtime = now;
14631                         DNS_ZONE_TIME_ADD(&now, zone->expire,
14632                                           &zone->expiretime);
14633                 } else {
14634                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
14635                                             &zone->refreshtime);
14636                         DNS_ZONE_TIME_ADD(&now, zone->expire,
14637                                           &zone->expiretime);
14638                 }
14639                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
14640                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
14641                         if (zone->tsigkey != NULL) {
14642                                 char namebuf[DNS_NAME_FORMATSIZE];
14643                                 dns_name_format(&zone->tsigkey->name, namebuf,
14644                                                 sizeof(namebuf));
14645                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
14646                                          namebuf);
14647                         } else
14648                                 buf[0] = '\0';
14649                         dns_zone_log(zone, ISC_LOG_INFO,
14650                                      "transferred serial %u%s",
14651                                      serial, buf);
14652                         if (inline_raw(zone))
14653                                 zone_send_secureserial(zone, serial);
14654                 }
14655 
14656                 /*
14657                  * This is not necessary if we just performed a AXFR
14658                  * however it is necessary for an IXFR / UPTODATE and
14659                  * won't hurt with an AXFR.
14660                  */
14661                 if (zone->masterfile != NULL || zone->journal != NULL) {
14662                         unsigned int delay = DNS_DUMP_DELAY;
14663 
14664                         result = ISC_R_FAILURE;
14665                         if (zone->journal != NULL)
14666                                 result = isc_file_settime(zone->journal, &now);
14667                         if (result != ISC_R_SUCCESS &&
14668                             zone->masterfile != NULL)
14669                                 result = isc_file_settime(zone->masterfile,
14670                                                           &now);
14671 
14672                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
14673                             result == ISC_R_FILENOTFOUND)
14674                                 delay = 0;
14675 
14676                         if ((result == ISC_R_SUCCESS ||
14677                             result == ISC_R_FILENOTFOUND) &&
14678                             zone->masterfile != NULL)
14679                                 zone_needdump(zone, delay);
14680                         else if (result != ISC_R_SUCCESS)
14681                                 dns_zone_log(zone, ISC_LOG_ERROR,
14682                                              "transfer: could not set file "
14683                                              "modification time of '%s': %s",
14684                                              zone->masterfile,
14685                                              dns_result_totext(result));
14686                 }
14687                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
14688                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
14689                 break;
14690 
14691         case DNS_R_BADIXFR:
14692                 /* Force retry with AXFR. */
14693                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14694                 goto same_master;
14695 
14696         default:
14697         next_master:
14698                 /*
14699                  * Skip to next failed / untried master.
14700                  */
14701                 do {
14702                         zone->curmaster++;
14703                 } while (zone->curmaster < zone->masterscnt &&
14704                          zone->mastersok[zone->curmaster]);
14705                 /* FALLTHROUGH */
14706         same_master:
14707                 if (zone->curmaster >= zone->masterscnt) {
14708                         zone->curmaster = 0;
14709                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14710                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14711                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14712                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14713                                 while (zone->curmaster < zone->masterscnt &&
14714                                        zone->mastersok[zone->curmaster])
14715                                         zone->curmaster++;
14716                                 again = ISC_TRUE;
14717                         } else
14718                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14719                 } else {
14720                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14721                         again = ISC_TRUE;
14722                 }
14723                 inc_stats(zone, dns_zonestatscounter_xfrfail);
14724                 break;
14725         }
14726         zone_settimer(zone, &now);
14727 
14728         /*
14729          * If creating the transfer object failed, zone->xfr is NULL.
14730          * Otherwise, we are called as the done callback of a zone
14731          * transfer object that just entered its shutting-down
14732          * state.  Since we are no longer responsible for shutting
14733          * it down, we can detach our reference.
14734          */
14735         if (zone->xfr != NULL)
14736                 dns_xfrin_detach(&zone->xfr);
14737 
14738         if (zone->tsigkey != NULL)
14739                 dns_tsigkey_detach(&zone->tsigkey);
14740 
14741         /*
14742          * Handle any deferred journal compaction.
14743          */
14744         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
14745                 result = dns_journal_compact(zone->mctx, zone->journal,
14746                                              zone->compact_serial,
14747                                              zone->journalsize);
14748                 switch (result) {
14749                 case ISC_R_SUCCESS:
14750                 case ISC_R_NOSPACE:
14751                 case ISC_R_NOTFOUND:
14752                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
14753                                      "dns_journal_compact: %s",
14754                                      dns_result_totext(result));
14755                         break;
14756                 default:
14757                         dns_zone_log(zone, ISC_LOG_ERROR,
14758                                      "dns_journal_compact failed: %s",
14759                                      dns_result_totext(result));
14760                         break;
14761                 }
14762                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
14763         }
14764 
14765         if (secure != NULL)
14766                 UNLOCK_ZONE(secure);
14767         /*
14768          * This transfer finishing freed up a transfer quota slot.
14769          * Let any other zones waiting for quota have it.
14770          */
14771         if (zone->zmgr != NULL &&
14772             zone->statelist == &zone->zmgr->xfrin_in_progress) {
14773                 UNLOCK_ZONE(zone);
14774                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14775                 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
14776                 zone->statelist = NULL;
14777                 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
14778                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14779                 LOCK_ZONE(zone);
14780         }
14781 
14782         /*
14783          * Retry with a different server if necessary.
14784          */
14785         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
14786                 queue_soa_query(zone);
14787 
14788         INSIST(zone->irefs > 0);
14789         zone->irefs--;
14790         free_needed = exit_check(zone);
14791         UNLOCK_ZONE(zone);
14792         if (free_needed)
14793                 zone_free(zone);
14794 }
14795 
14796 static void
14797 zone_loaddone(void *arg, isc_result_t result) {
14798         static char me[] = "zone_loaddone";
14799         dns_load_t *load = arg;
14800         dns_zone_t *zone;
14801         isc_result_t tresult;
14802         dns_zone_t *secure = NULL;
14803 
14804         REQUIRE(DNS_LOAD_VALID(load));
14805         zone = load->zone;
14806 
14807         ENTER;
14808 
14809         tresult = dns_db_endload(load->db, &load->callbacks);
14810         if (tresult != ISC_R_SUCCESS &&
14811             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
14812                 result = tresult;
14813 
14814         /*
14815          * Lock hierarchy: zmgr, zone, raw.
14816          */
14817  again:
14818         LOCK_ZONE(zone);
14819         INSIST(zone != zone->raw);
14820         if (inline_secure(zone))
14821                 LOCK_ZONE(zone->raw);
14822         else if (inline_raw(zone)) {
14823                 secure = zone->secure;
14824                 TRYLOCK_ZONE(result, secure);
14825                 if (result != ISC_R_SUCCESS) {
14826                         UNLOCK_ZONE(zone);
14827                         secure = NULL;
14828 #if ISC_PLATFORM_USETHREADS
14829                         isc_thread_yield();
14830 #endif
14831                         goto again;
14832                 }
14833         }
14834         (void)zone_postload(zone, load->db, load->loadtime, result);
14835         zonemgr_putio(&zone->readio);
14836         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
14837         zone_idetach(&load->callbacks.zone);
14838         /*
14839          * Leave the zone frozen if the reload fails.
14840          */
14841         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
14842              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
14843                 zone->update_disabled = ISC_FALSE;
14844         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
14845         if (inline_secure(zone))
14846                 UNLOCK_ZONE(zone->raw);
14847         else if (secure != NULL)
14848                 UNLOCK_ZONE(secure);
14849         UNLOCK_ZONE(zone);
14850 
14851         load->magic = 0;
14852         dns_db_detach(&load->db);
14853         if (load->zone->lctx != NULL)
14854                 dns_loadctx_detach(&load->zone->lctx);
14855         dns_zone_idetach(&load->zone);
14856         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
14857 }
14858 
14859 void
14860 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
14861         REQUIRE(DNS_ZONE_VALID(zone));
14862         REQUIRE(table != NULL);
14863         REQUIRE(*table == NULL);
14864 
14865         LOCK_ZONE(zone);
14866         if (zone->ssutable != NULL)
14867                 dns_ssutable_attach(zone->ssutable, table);
14868         UNLOCK_ZONE(zone);
14869 }
14870 
14871 void
14872 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14873         REQUIRE(DNS_ZONE_VALID(zone));
14874 
14875         LOCK_ZONE(zone);
14876         if (zone->ssutable != NULL)
14877                 dns_ssutable_detach(&zone->ssutable);
14878         if (table != NULL)
14879                 dns_ssutable_attach(table, &zone->ssutable);
14880         UNLOCK_ZONE(zone);
14881 }
14882 
14883 void
14884 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14885         REQUIRE(DNS_ZONE_VALID(zone));
14886 
14887         zone->sigvalidityinterval = interval;
14888 }
14889 
14890 isc_uint32_t
14891 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14892         REQUIRE(DNS_ZONE_VALID(zone));
14893 
14894         return (zone->sigvalidityinterval);
14895 }
14896 
14897 void
14898 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14899         isc_time_t now;
14900 
14901         REQUIRE(DNS_ZONE_VALID(zone));
14902 
14903         LOCK_ZONE(zone);
14904         zone->sigresigninginterval = interval;
14905         set_resigntime(zone);
14906         if (zone->task != NULL) {
14907                 TIME_NOW(&now);
14908                 zone_settimer(zone, &now);
14909         }
14910         UNLOCK_ZONE(zone);
14911 }
14912 
14913 isc_uint32_t
14914 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14915         REQUIRE(DNS_ZONE_VALID(zone));
14916 
14917         return (zone->sigresigninginterval);
14918 }
14919 
14920 static void
14921 queue_xfrin(dns_zone_t *zone) {
14922         const char me[] = "queue_xfrin";
14923         isc_result_t result;
14924         dns_zonemgr_t *zmgr = zone->zmgr;
14925 
14926         ENTER;
14927 
14928         INSIST(zone->statelist == NULL);
14929 
14930         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14931         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14932         LOCK_ZONE(zone);
14933         zone->irefs++;
14934         UNLOCK_ZONE(zone);
14935         zone->statelist = &zmgr->waiting_for_xfrin;
14936         result = zmgr_start_xfrin_ifquota(zmgr, zone);
14937         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14938 
14939         if (result == ISC_R_QUOTA) {
14940                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14941                               "zone transfer deferred due to quota");
14942         } else if (result != ISC_R_SUCCESS) {
14943                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14944                               "starting zone transfer: %s",
14945                               isc_result_totext(result));
14946         }
14947 }
14948 
14949 /*
14950  * This event callback is called when a zone has received
14951  * any necessary zone transfer quota.  This is the time
14952  * to go ahead and start the transfer.
14953  */
14954 static void
14955 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14956         isc_result_t result = ISC_R_SUCCESS;
14957         dns_peer_t *peer = NULL;
14958         char master[ISC_SOCKADDR_FORMATSIZE];
14959         char source[ISC_SOCKADDR_FORMATSIZE];
14960         dns_rdatatype_t xfrtype;
14961         dns_zone_t *zone = event->ev_arg;
14962         isc_netaddr_t masterip;
14963         isc_sockaddr_t sourceaddr;
14964         isc_sockaddr_t masteraddr;
14965         isc_time_t now;
14966         const char *soa_before = "";
14967         isc_dscp_t dscp = -1;
14968         isc_boolean_t loaded;
14969 
14970         UNUSED(task);
14971 
14972         INSIST(task == zone->task);
14973 
14974         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14975                 result = ISC_R_CANCELED;
14976                 goto cleanup;
14977         }
14978 
14979         TIME_NOW(&now);
14980 
14981         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14982         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14983                                     &zone->sourceaddr, &now))
14984         {
14985                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14986                 dns_zone_log(zone, ISC_LOG_INFO,
14987                              "got_transfer_quota: skipping zone transfer as "
14988                              "master %s (source %s) is unreachable (cached)",
14989                              master, source);
14990                 result = ISC_R_CANCELED;
14991                 goto cleanup;
14992         }
14993 
14994         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14995         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14996 
14997         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14998                 soa_before = "SOA before ";
14999         /*
15000          * Decide whether we should request IXFR or AXFR.
15001          */
15002         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15003         loaded = ISC_TF(zone->db != NULL);
15004         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15005 
15006         if (!loaded) {
15007                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15008                              "no database exists yet, requesting AXFR of "
15009                              "initial version from %s", master);
15010                 xfrtype = dns_rdatatype_axfr;
15011         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
15012                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15013                              "forced reload, requesting AXFR of "
15014                              "initial version from %s", master);
15015                 xfrtype = dns_rdatatype_axfr;
15016         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
15017                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15018                              "retrying with AXFR from %s due to "
15019                              "previous IXFR failure", master);
15020                 xfrtype = dns_rdatatype_axfr;
15021                 LOCK_ZONE(zone);
15022                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
15023                 UNLOCK_ZONE(zone);
15024         } else {
15025                 isc_boolean_t use_ixfr = ISC_TRUE;
15026                 if (peer != NULL)
15027                         result = dns_peer_getrequestixfr(peer, &use_ixfr);
15028                 if (peer == NULL || result != ISC_R_SUCCESS)
15029                         use_ixfr = zone->requestixfr;
15030                 if (use_ixfr == ISC_FALSE) {
15031                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
15032                                      "IXFR disabled, requesting %sAXFR from %s",
15033                                      soa_before, master);
15034                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
15035                                 xfrtype = dns_rdatatype_soa;
15036                         else
15037                                 xfrtype = dns_rdatatype_axfr;
15038                 } else {
15039                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
15040                                      "requesting IXFR from %s", master);
15041                         xfrtype = dns_rdatatype_ixfr;
15042                 }
15043         }
15044 
15045         /*
15046          * Determine if we should attempt to sign the request with TSIG.
15047          */
15048         result = ISC_R_NOTFOUND;
15049 
15050         /*
15051          * First, look for a tsig key in the master statement, then
15052          * try for a server key.
15053          */
15054         if ((zone->masterkeynames != NULL) &&
15055             (zone->masterkeynames[zone->curmaster] != NULL)) {
15056                 dns_view_t *view = dns_zone_getview(zone);
15057                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
15058                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
15059         }
15060         if (zone->tsigkey == NULL)
15061                 result = dns_view_getpeertsig(zone->view, &masterip,
15062                                               &zone->tsigkey);
15063 
15064         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
15065                 dns_zone_log(zone, ISC_LOG_ERROR,
15066                              "could not get TSIG key for zone transfer: %s",
15067                              isc_result_totext(result));
15068         }
15069 
15070         if (zone->masterdscps != NULL)
15071             dscp = zone->masterdscps[zone->curmaster];
15072 
15073         LOCK_ZONE(zone);
15074         masteraddr = zone->masteraddr;
15075         sourceaddr = zone->sourceaddr;
15076         switch (isc_sockaddr_pf(&masteraddr)) {
15077         case PF_INET:
15078                 if (dscp == -1)
15079                         dscp = zone->xfrsource4dscp;
15080                 break;
15081         case PF_INET6:
15082                 if (dscp == -1)
15083                         dscp = zone->xfrsource6dscp;
15084                 break;
15085         default:
15086                 INSIST(0);
15087         };
15088         UNLOCK_ZONE(zone);
15089         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
15090         result = dns_xfrin_create3(zone, xfrtype, &masteraddr, &sourceaddr,
15091                                    dscp, zone->tsigkey, zone->mctx,
15092                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
15093                                    zone->task, zone_xfrdone, &zone->xfr);
15094         if (result == ISC_R_SUCCESS) {
15095                 LOCK_ZONE(zone);
15096                 if (xfrtype == dns_rdatatype_axfr) {
15097                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
15098                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
15099                         else
15100                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
15101                 } else if (xfrtype == dns_rdatatype_ixfr) {
15102                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
15103                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
15104                         else
15105                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
15106                 }
15107                 UNLOCK_ZONE(zone);
15108         }
15109  cleanup:
15110         /*
15111          * Any failure in this function is handled like a failed
15112          * zone transfer.  This ensures that we get removed from
15113          * zmgr->xfrin_in_progress.
15114          */
15115         if (result != ISC_R_SUCCESS)
15116                 zone_xfrdone(zone, result);
15117 
15118         isc_event_free(&event);
15119 }
15120 
15121 /*
15122  * Update forwarding support.
15123  */
15124 
15125 static void
15126 forward_destroy(dns_forward_t *forward) {
15127 
15128         forward->magic = 0;
15129         if (forward->request != NULL)
15130                 dns_request_destroy(&forward->request);
15131         if (forward->msgbuf != NULL)
15132                 isc_buffer_free(&forward->msgbuf);
15133         if (forward->zone != NULL) {
15134                 LOCK(&forward->zone->lock);
15135                 if (ISC_LINK_LINKED(forward, link))
15136                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
15137                 UNLOCK(&forward->zone->lock);
15138                 dns_zone_idetach(&forward->zone);
15139         }
15140         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
15141 }
15142 
15143 static isc_result_t
15144 sendtomaster(dns_forward_t *forward) {
15145         isc_result_t result;
15146         isc_sockaddr_t src;
15147         isc_dscp_t dscp = -1;
15148 
15149         LOCK_ZONE(forward->zone);
15150 
15151         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
15152                 UNLOCK_ZONE(forward->zone);
15153                 return (ISC_R_CANCELED);
15154         }
15155 
15156         if (forward->which >= forward->zone->masterscnt) {
15157                 UNLOCK_ZONE(forward->zone);
15158                 return (ISC_R_NOMORE);
15159         }
15160 
15161         forward->addr = forward->zone->masters[forward->which];
15162         /*
15163          * Always use TCP regardless of whether the original update
15164          * used TCP.
15165          * XXX The timeout may but a bit small if we are far down a
15166          * transfer graph and the master has to try several masters.
15167          */
15168         switch (isc_sockaddr_pf(&forward->addr)) {
15169         case PF_INET:
15170                 src = forward->zone->xfrsource4;
15171                 dscp = forward->zone->xfrsource4dscp;
15172                 break;
15173         case PF_INET6:
15174                 src = forward->zone->xfrsource6;
15175                 dscp = forward->zone->xfrsource6dscp;
15176                 break;
15177         default:
15178                 result = ISC_R_NOTIMPLEMENTED;
15179                 goto unlock;
15180         }
15181         result = dns_request_createraw4(forward->zone->view->requestmgr,
15182                                         forward->msgbuf,
15183                                         &src, &forward->addr, dscp,
15184                                         forward->options, 15 /* XXX */,
15185                                         0, 0, forward->zone->task,
15186                                         forward_callback, forward,
15187                                         &forward->request);
15188         if (result == ISC_R_SUCCESS) {
15189                 if (!ISC_LINK_LINKED(forward, link))
15190                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
15191         }
15192 
15193  unlock:
15194         UNLOCK_ZONE(forward->zone);
15195         return (result);
15196 }
15197 
15198 static void
15199 forward_callback(isc_task_t *task, isc_event_t *event) {
15200         const char me[] = "forward_callback";
15201         dns_requestevent_t *revent = (dns_requestevent_t *)event;
15202         dns_message_t *msg = NULL;
15203         char master[ISC_SOCKADDR_FORMATSIZE];
15204         isc_result_t result;
15205         dns_forward_t *forward;
15206         dns_zone_t *zone;
15207 
15208         UNUSED(task);
15209 
15210         forward = revent->ev_arg;
15211         INSIST(DNS_FORWARD_VALID(forward));
15212         zone = forward->zone;
15213         INSIST(DNS_ZONE_VALID(zone));
15214 
15215         ENTER;
15216 
15217         isc_sockaddr_format(&forward->addr, master, sizeof(master));
15218 
15219         if (revent->result != ISC_R_SUCCESS) {
15220                 dns_zone_log(zone, ISC_LOG_INFO,
15221                              "could not forward dynamic update to %s: %s",
15222                              master, dns_result_totext(revent->result));
15223                 goto next_master;
15224         }
15225 
15226         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
15227         if (result != ISC_R_SUCCESS)
15228                 goto next_master;
15229 
15230         result = dns_request_getresponse(revent->request, msg,
15231                                          DNS_MESSAGEPARSE_PRESERVEORDER |
15232                                          DNS_MESSAGEPARSE_CLONEBUFFER);
15233         if (result != ISC_R_SUCCESS)
15234                 goto next_master;
15235 
15236         switch (msg->rcode) {
15237         /*
15238          * Pass these rcodes back to client.
15239          */
15240         case dns_rcode_noerror:
15241         case dns_rcode_yxdomain:
15242         case dns_rcode_yxrrset:
15243         case dns_rcode_nxrrset:
15244         case dns_rcode_refused:
15245         case dns_rcode_nxdomain: {
15246                 char rcode[128];
15247                 isc_buffer_t rb;
15248 
15249                 isc_buffer_init(&rb, rcode, sizeof(rcode));
15250                 (void)dns_rcode_totext(msg->rcode, &rb);
15251                 dns_zone_log(zone, ISC_LOG_INFO,
15252                              "forwarded dynamic update: "
15253                              "master %s returned: %.*s",
15254                              master, (int)rb.used, rcode);
15255                 break;
15256         }
15257 
15258         /* These should not occur if the masters/zone are valid. */
15259         case dns_rcode_notzone:
15260         case dns_rcode_notauth: {
15261                 char rcode[128];
15262                 isc_buffer_t rb;
15263 
15264                 isc_buffer_init(&rb, rcode, sizeof(rcode));
15265                 (void)dns_rcode_totext(msg->rcode, &rb);
15266                 dns_zone_log(zone, ISC_LOG_WARNING,
15267                              "forwarding dynamic update: "
15268                              "unexpected response: master %s returned: %.*s",
15269                              master, (int)rb.used, rcode);
15270                 goto next_master;
15271         }
15272 
15273         /* Try another server for these rcodes. */
15274         case dns_rcode_formerr:
15275         case dns_rcode_servfail:
15276         case dns_rcode_notimp:
15277         case dns_rcode_badvers:
15278         default:
15279                 goto next_master;
15280         }
15281 
15282         /* call callback */
15283         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
15284         msg = NULL;
15285         dns_request_destroy(&forward->request);
15286         forward_destroy(forward);
15287         isc_event_free(&event);
15288         return;
15289 
15290  next_master:
15291         if (msg != NULL)
15292                 dns_message_destroy(&msg);
15293         isc_event_free(&event);
15294         forward->which++;
15295         dns_request_destroy(&forward->request);
15296         result = sendtomaster(forward);
15297         if (result != ISC_R_SUCCESS) {
15298                 /* call callback */
15299                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
15300                              "exhausted dynamic update forwarder list");
15301                 (forward->callback)(forward->callback_arg, result, NULL);
15302                 forward_destroy(forward);
15303         }
15304 }
15305 
15306 isc_result_t
15307 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
15308                        dns_updatecallback_t callback, void *callback_arg)
15309 {
15310         dns_forward_t *forward;
15311         isc_result_t result;
15312         isc_region_t *mr;
15313 
15314         REQUIRE(DNS_ZONE_VALID(zone));
15315         REQUIRE(msg != NULL);
15316         REQUIRE(callback != NULL);
15317 
15318         forward = isc_mem_get(zone->mctx, sizeof(*forward));
15319         if (forward == NULL)
15320                 return (ISC_R_NOMEMORY);
15321 
15322         forward->request = NULL;
15323         forward->zone = NULL;
15324         forward->msgbuf = NULL;
15325         forward->which = 0;
15326         forward->mctx = 0;
15327         forward->callback = callback;
15328         forward->callback_arg = callback_arg;
15329         ISC_LINK_INIT(forward, link);
15330         forward->magic = FORWARD_MAGIC;
15331         forward->options = DNS_REQUESTOPT_TCP;
15332         /*
15333          * If we have a SIG(0) signed message we need to preserve the
15334          * query id as that is included in the SIG(0) computation.
15335          */
15336         if (msg->sig0 != NULL)
15337                 forward->options |= DNS_REQUESTOPT_FIXEDID;
15338 
15339         mr = dns_message_getrawmessage(msg);
15340         if (mr == NULL) {
15341                 result = ISC_R_UNEXPECTEDEND;
15342                 goto cleanup;
15343         }
15344 
15345         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
15346         if (result != ISC_R_SUCCESS)
15347                 goto cleanup;
15348         result = isc_buffer_copyregion(forward->msgbuf, mr);
15349         if (result != ISC_R_SUCCESS)
15350                 goto cleanup;
15351 
15352         isc_mem_attach(zone->mctx, &forward->mctx);
15353         dns_zone_iattach(zone, &forward->zone);
15354         result = sendtomaster(forward);
15355 
15356  cleanup:
15357         if (result != ISC_R_SUCCESS) {
15358                 forward_destroy(forward);
15359         }
15360         return (result);
15361 }
15362 
15363 isc_result_t
15364 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
15365         REQUIRE(DNS_ZONE_VALID(zone));
15366         REQUIRE(next != NULL && *next == NULL);
15367 
15368         *next = ISC_LIST_NEXT(zone, link);
15369         if (*next == NULL)
15370                 return (ISC_R_NOMORE);
15371         else
15372                 return (ISC_R_SUCCESS);
15373 }
15374 
15375 isc_result_t
15376 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
15377         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15378         REQUIRE(first != NULL && *first == NULL);
15379 
15380         *first = ISC_LIST_HEAD(zmgr->zones);
15381         if (*first == NULL)
15382                 return (ISC_R_NOMORE);
15383         else
15384                 return (ISC_R_SUCCESS);
15385 }
15386 
15387 /***
15388  ***    Zone manager.
15389  ***/
15390 
15391 isc_result_t
15392 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
15393                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
15394                    dns_zonemgr_t **zmgrp)
15395 {
15396         dns_zonemgr_t *zmgr;
15397         isc_result_t result;
15398 
15399         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
15400         if (zmgr == NULL)
15401                 return (ISC_R_NOMEMORY);
15402         zmgr->mctx = NULL;
15403         zmgr->refs = 1;
15404         isc_mem_attach(mctx, &zmgr->mctx);
15405         zmgr->taskmgr = taskmgr;
15406         zmgr->timermgr = timermgr;
15407         zmgr->socketmgr = socketmgr;
15408         zmgr->zonetasks = NULL;
15409         zmgr->loadtasks = NULL;
15410         zmgr->mctxpool = NULL;
15411         zmgr->task = NULL;
15412         zmgr->notifyrl = NULL;
15413         zmgr->refreshrl = NULL;
15414         zmgr->startupnotifyrl = NULL;
15415         zmgr->startuprefreshrl = NULL;
15416         ISC_LIST_INIT(zmgr->zones);
15417         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
15418         ISC_LIST_INIT(zmgr->xfrin_in_progress);
15419         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
15420         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
15421         if (result != ISC_R_SUCCESS)
15422                 goto free_mem;
15423 
15424         zmgr->transfersin = 10;
15425         zmgr->transfersperns = 2;
15426 
15427         /* Unreachable lock. */
15428         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
15429         if (result != ISC_R_SUCCESS)
15430                 goto free_rwlock;
15431 
15432         /* Create a single task for queueing of SOA queries. */
15433         result = isc_task_create(taskmgr, 1, &zmgr->task);
15434         if (result != ISC_R_SUCCESS)
15435                 goto free_urlock;
15436 
15437         isc_task_setname(zmgr->task, "zmgr", zmgr);
15438         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15439                                         &zmgr->notifyrl);
15440         if (result != ISC_R_SUCCESS)
15441                 goto free_task;
15442 
15443         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15444                                         &zmgr->refreshrl);
15445         if (result != ISC_R_SUCCESS)
15446                 goto free_notifyrl;
15447 
15448         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15449                                         &zmgr->startupnotifyrl);
15450         if (result != ISC_R_SUCCESS)
15451                 goto free_refreshrl;
15452 
15453         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15454                                         &zmgr->startuprefreshrl);
15455         if (result != ISC_R_SUCCESS)
15456                 goto free_startupnotifyrl;
15457 
15458         /* default to 20 refresh queries / notifies per second. */
15459         setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
15460         setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
15461         setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
15462         setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
15463 
15464         zmgr->iolimit = 1;
15465         zmgr->ioactive = 0;
15466         ISC_LIST_INIT(zmgr->high);
15467         ISC_LIST_INIT(zmgr->low);
15468 
15469         result = isc_mutex_init(&zmgr->iolock);
15470         if (result != ISC_R_SUCCESS)
15471                 goto free_startuprefreshrl;
15472 
15473         zmgr->magic = ZONEMGR_MAGIC;
15474 
15475         *zmgrp = zmgr;
15476         return (ISC_R_SUCCESS);
15477 
15478 #if 0
15479  free_iolock:
15480         DESTROYLOCK(&zmgr->iolock);
15481 #endif
15482  free_startuprefreshrl:
15483         isc_ratelimiter_detach(&zmgr->startuprefreshrl);
15484  free_startupnotifyrl:
15485         isc_ratelimiter_detach(&zmgr->startupnotifyrl);
15486  free_refreshrl:
15487         isc_ratelimiter_detach(&zmgr->refreshrl);
15488  free_notifyrl:
15489         isc_ratelimiter_detach(&zmgr->notifyrl);
15490  free_task:
15491         isc_task_detach(&zmgr->task);
15492  free_urlock:
15493         isc_rwlock_destroy(&zmgr->urlock);
15494  free_rwlock:
15495         isc_rwlock_destroy(&zmgr->rwlock);
15496  free_mem:
15497         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
15498         isc_mem_detach(&mctx);
15499         return (result);
15500 }
15501 
15502 isc_result_t
15503 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
15504         isc_result_t result;
15505         isc_mem_t *mctx = NULL;
15506         dns_zone_t *zone = NULL;
15507         void *item;
15508 
15509         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15510         REQUIRE(zonep != NULL && *zonep == NULL);
15511 
15512         if (zmgr->mctxpool == NULL)
15513                 return (ISC_R_FAILURE);
15514 
15515         item = isc_pool_get(zmgr->mctxpool);
15516         if (item == NULL)
15517                 return (ISC_R_FAILURE);
15518 
15519         isc_mem_attach((isc_mem_t *) item, &mctx);
15520         result = dns_zone_create(&zone, mctx);
15521         isc_mem_detach(&mctx);
15522 
15523         if (result == ISC_R_SUCCESS)
15524                 *zonep = zone;
15525 
15526         return (result);
15527 }
15528 
15529 isc_result_t
15530 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15531         isc_result_t result;
15532 
15533         REQUIRE(DNS_ZONE_VALID(zone));
15534         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15535 
15536         if (zmgr->zonetasks == NULL)
15537                 return (ISC_R_FAILURE);
15538 
15539         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15540         LOCK_ZONE(zone);
15541         REQUIRE(zone->task == NULL);
15542         REQUIRE(zone->timer == NULL);
15543         REQUIRE(zone->zmgr == NULL);
15544 
15545         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
15546         isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
15547 
15548         /*
15549          * Set the task name.  The tag will arbitrarily point to one
15550          * of the zones sharing the task (in practice, the one
15551          * to be managed last).
15552          */
15553         isc_task_setname(zone->task, "zone", zone);
15554         isc_task_setname(zone->loadtask, "loadzone", zone);
15555 
15556         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
15557                                   NULL, NULL,
15558                                   zone->task, zone_timer, zone,
15559                                   &zone->timer);
15560 
15561         if (result != ISC_R_SUCCESS)
15562                 goto cleanup_tasks;
15563 
15564         /*
15565          * The timer "holds" a iref.
15566          */
15567         zone->irefs++;
15568         INSIST(zone->irefs != 0);
15569 
15570         ISC_LIST_APPEND(zmgr->zones, zone, link);
15571         zone->zmgr = zmgr;
15572         zmgr->refs++;
15573 
15574         goto unlock;
15575 
15576  cleanup_tasks:
15577         isc_task_detach(&zone->loadtask);
15578         isc_task_detach(&zone->task);
15579 
15580  unlock:
15581         UNLOCK_ZONE(zone);
15582         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15583         return (result);
15584 }
15585 
15586 void
15587 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15588         isc_boolean_t free_now = ISC_FALSE;
15589 
15590         REQUIRE(DNS_ZONE_VALID(zone));
15591         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15592         REQUIRE(zone->zmgr == zmgr);
15593 
15594         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15595         LOCK_ZONE(zone);
15596 
15597         ISC_LIST_UNLINK(zmgr->zones, zone, link);
15598         zone->zmgr = NULL;
15599         zmgr->refs--;
15600         if (zmgr->refs == 0)
15601                 free_now = ISC_TRUE;
15602 
15603         UNLOCK_ZONE(zone);
15604         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15605 
15606         if (free_now)
15607                 zonemgr_free(zmgr);
15608         ENSURE(zone->zmgr == NULL);
15609 }
15610 
15611 void
15612 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
15613         REQUIRE(DNS_ZONEMGR_VALID(source));
15614         REQUIRE(target != NULL && *target == NULL);
15615 
15616         RWLOCK(&source->rwlock, isc_rwlocktype_write);
15617         REQUIRE(source->refs > 0);
15618         source->refs++;
15619         INSIST(source->refs > 0);
15620         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
15621         *target = source;
15622 }
15623 
15624 void
15625 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
15626         dns_zonemgr_t *zmgr;
15627         isc_boolean_t free_now = ISC_FALSE;
15628 
15629         REQUIRE(zmgrp != NULL);
15630         zmgr = *zmgrp;
15631         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15632 
15633         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15634         zmgr->refs--;
15635         if (zmgr->refs == 0)
15636                 free_now = ISC_TRUE;
15637         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15638 
15639         if (free_now)
15640                 zonemgr_free(zmgr);
15641         *zmgrp = NULL;
15642 }
15643 
15644 isc_result_t
15645 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
15646         dns_zone_t *p;
15647 
15648         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15649 
15650         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15651         for (p = ISC_LIST_HEAD(zmgr->zones);
15652              p != NULL;
15653              p = ISC_LIST_NEXT(p, link))
15654         {
15655                 dns_zone_maintenance(p);
15656         }
15657         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15658 
15659         /*
15660          * Recent configuration changes may have increased the
15661          * amount of available transfers quota.  Make sure any
15662          * transfers currently blocked on quota get started if
15663          * possible.
15664          */
15665         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15666         zmgr_resume_xfrs(zmgr, ISC_TRUE);
15667         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15668         return (ISC_R_SUCCESS);
15669 }
15670 
15671 void
15672 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
15673 
15674         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15675 
15676         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15677         zmgr_resume_xfrs(zmgr, ISC_TRUE);
15678         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15679 }
15680 
15681 void
15682 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
15683         dns_zone_t *zone;
15684 
15685         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15686 
15687         isc_ratelimiter_shutdown(zmgr->notifyrl);
15688         isc_ratelimiter_shutdown(zmgr->refreshrl);
15689         isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
15690         isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
15691 
15692         if (zmgr->task != NULL)
15693                 isc_task_destroy(&zmgr->task);
15694         if (zmgr->zonetasks != NULL)
15695                 isc_taskpool_destroy(&zmgr->zonetasks);
15696         if (zmgr->loadtasks != NULL)
15697                 isc_taskpool_destroy(&zmgr->loadtasks);
15698         if (zmgr->mctxpool != NULL)
15699                 isc_pool_destroy(&zmgr->mctxpool);
15700 
15701         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15702         for (zone = ISC_LIST_HEAD(zmgr->zones);
15703              zone != NULL;
15704              zone = ISC_LIST_NEXT(zone, link))
15705         {
15706                 LOCK_ZONE(zone);
15707                 forward_cancel(zone);
15708                 UNLOCK_ZONE(zone);
15709         }
15710         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15711 }
15712 
15713 static isc_result_t
15714 mctxinit(void **target, void *arg) {
15715         isc_result_t result;
15716         isc_mem_t *mctx = NULL;
15717 
15718         UNUSED(arg);
15719 
15720         REQUIRE(target != NULL && *target == NULL);
15721 
15722         result = isc_mem_create(0, 0, &mctx);
15723         if (result != ISC_R_SUCCESS)
15724                 return (result);
15725         isc_mem_setname(mctx, "zonemgr-pool", NULL);
15726 
15727         *target = mctx;
15728         return (ISC_R_SUCCESS);
15729 }
15730 
15731 static void
15732 mctxfree(void **target) {
15733         isc_mem_t *mctx = *(isc_mem_t **) target;
15734         isc_mem_detach(&mctx);
15735         *target = NULL;
15736 }
15737 
15738 #define ZONES_PER_TASK 100
15739 #define ZONES_PER_MCTX 1000
15740 
15741 isc_result_t
15742 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
15743         isc_result_t result;
15744         int ntasks = num_zones / ZONES_PER_TASK;
15745         int nmctx = num_zones / ZONES_PER_MCTX;
15746         isc_taskpool_t *pool = NULL;
15747         isc_pool_t *mctxpool = NULL;
15748 
15749         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15750 
15751         /*
15752          * For anything fewer than 1000 zones we use 10 tasks in
15753          * the task pools.  More than that, and we'll scale at one
15754          * task per 100 zones.  Similarly, for anything smaller than
15755          * 2000 zones we use 2 memory contexts, then scale at 1:1000.
15756          */
15757         if (ntasks < 10)
15758                 ntasks = 10;
15759         if (nmctx < 2)
15760                 nmctx = 2;
15761 
15762         /* Create or resize the zone task pools. */
15763         if (zmgr->zonetasks == NULL)
15764                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15765                                              ntasks, 2, &pool);
15766         else
15767                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
15768 
15769         if (result == ISC_R_SUCCESS)
15770                 zmgr->zonetasks = pool;
15771 
15772         pool = NULL;
15773         if (zmgr->loadtasks == NULL)
15774                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15775                                              ntasks, 2, &pool);
15776         else
15777                 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
15778 
15779         if (result == ISC_R_SUCCESS)
15780                 zmgr->loadtasks = pool;
15781 
15782         /*
15783          * We always set all tasks in the zone-load task pool to
15784          * privileged.  This prevents other tasks in the system from
15785          * running while the server task manager is in privileged
15786          * mode.
15787          *
15788          * NOTE: If we start using task privileges for any other
15789          * part of the system than zone tasks, then this will need to be
15790          * revisted.  In that case we'd want to turn on privileges for
15791          * zone tasks only when we were loading, and turn them off the
15792          * rest of the time.  For now, however, it's okay to just
15793          * set it and forget it.
15794          */
15795         isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
15796 
15797         /* Create or resize the zone memory context pool. */
15798         if (zmgr->mctxpool == NULL)
15799                 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
15800                                          mctxinit, NULL, &mctxpool);
15801         else
15802                 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
15803 
15804         if (result == ISC_R_SUCCESS)
15805                 zmgr->mctxpool = mctxpool;
15806 
15807         return (result);
15808 }
15809 
15810 static void
15811 zonemgr_free(dns_zonemgr_t *zmgr) {
15812         isc_mem_t *mctx;
15813 
15814         INSIST(zmgr->refs == 0);
15815         INSIST(ISC_LIST_EMPTY(zmgr->zones));
15816 
15817         zmgr->magic = 0;
15818 
15819         DESTROYLOCK(&zmgr->iolock);
15820         isc_ratelimiter_detach(&zmgr->notifyrl);
15821         isc_ratelimiter_detach(&zmgr->refreshrl);
15822         isc_ratelimiter_detach(&zmgr->startupnotifyrl);
15823         isc_ratelimiter_detach(&zmgr->startuprefreshrl);
15824 
15825         isc_rwlock_destroy(&zmgr->urlock);
15826         isc_rwlock_destroy(&zmgr->rwlock);
15827         mctx = zmgr->mctx;
15828         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
15829         isc_mem_detach(&mctx);
15830 }
15831 
15832 void
15833 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15834         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15835 
15836         zmgr->transfersin = value;
15837 }
15838 
15839 isc_uint32_t
15840 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
15841         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15842 
15843         return (zmgr->transfersin);
15844 }
15845 
15846 void
15847 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15848         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15849 
15850         zmgr->transfersperns = value;
15851 }
15852 
15853 isc_uint32_t
15854 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
15855         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15856 
15857         return (zmgr->transfersperns);
15858 }
15859 
15860 /*
15861  * Try to start a new incoming zone transfer to fill a quota
15862  * slot that was just vacated.
15863  *
15864  * Requires:
15865  *      The zone manager is locked by the caller.
15866  */
15867 static void
15868 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
15869         dns_zone_t *zone;
15870         dns_zone_t *next;
15871 
15872         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15873              zone != NULL;
15874              zone = next)
15875         {
15876                 isc_result_t result;
15877                 next = ISC_LIST_NEXT(zone, statelink);
15878                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
15879                 if (result == ISC_R_SUCCESS) {
15880                         if (multi)
15881                                 continue;
15882                         /*
15883                          * We successfully filled the slot.  We're done.
15884                          */
15885                         break;
15886                 } else if (result == ISC_R_QUOTA) {
15887                         /*
15888                          * Not enough quota.  This is probably the per-server
15889                          * quota, because we usually get called when a unit of
15890                          * global quota has just been freed.  Try the next
15891                          * zone, it may succeed if it uses another master.
15892                          */
15893                         continue;
15894                 } else {
15895                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
15896                                      "starting zone transfer: %s",
15897                                      isc_result_totext(result));
15898                         break;
15899                 }
15900         }
15901 }
15902 
15903 /*
15904  * Try to start an incoming zone transfer for 'zone', quota permitting.
15905  *
15906  * Requires:
15907  *      The zone manager is locked by the caller.
15908  *
15909  * Returns:
15910  *      ISC_R_SUCCESS   There was enough quota and we attempted to
15911  *                      start a transfer.  zone_xfrdone() has been or will
15912  *                      be called.
15913  *      ISC_R_QUOTA     Not enough quota.
15914  *      Others          Failure.
15915  */
15916 static isc_result_t
15917 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15918         dns_peer_t *peer = NULL;
15919         isc_netaddr_t masterip;
15920         isc_uint32_t nxfrsin, nxfrsperns;
15921         dns_zone_t *x;
15922         isc_uint32_t maxtransfersin, maxtransfersperns;
15923         isc_event_t *e;
15924 
15925         /*
15926          * If we are exiting just pretend we got quota so the zone will
15927          * be cleaned up in the zone's task context.
15928          */
15929         LOCK_ZONE(zone);
15930         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15931                 UNLOCK_ZONE(zone);
15932                 goto gotquota;
15933         }
15934 
15935         /*
15936          * Find any configured information about the server we'd
15937          * like to transfer this zone from.
15938          */
15939         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15940         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15941         UNLOCK_ZONE(zone);
15942 
15943         /*
15944          * Determine the total maximum number of simultaneous
15945          * transfers allowed, and the maximum for this specific
15946          * master.
15947          */
15948         maxtransfersin = zmgr->transfersin;
15949         maxtransfersperns = zmgr->transfersperns;
15950         if (peer != NULL)
15951                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
15952 
15953         /*
15954          * Count the total number of transfers that are in progress,
15955          * and the number of transfers in progress from this master.
15956          * We linearly scan a list of all transfers; if this turns
15957          * out to be too slow, we could hash on the master address.
15958          */
15959         nxfrsin = nxfrsperns = 0;
15960         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15961              x != NULL;
15962              x = ISC_LIST_NEXT(x, statelink))
15963         {
15964                 isc_netaddr_t xip;
15965 
15966                 LOCK_ZONE(x);
15967                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15968                 UNLOCK_ZONE(x);
15969 
15970                 nxfrsin++;
15971                 if (isc_netaddr_equal(&xip, &masterip))
15972                         nxfrsperns++;
15973         }
15974 
15975         /* Enforce quota. */
15976         if (nxfrsin >= maxtransfersin)
15977                 return (ISC_R_QUOTA);
15978 
15979         if (nxfrsperns >= maxtransfersperns)
15980                 return (ISC_R_QUOTA);
15981 
15982  gotquota:
15983         /*
15984          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
15985          * list and send it an event to let it start the actual transfer in the
15986          * context of its own task.
15987          */
15988         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15989                                got_transfer_quota, zone, sizeof(isc_event_t));
15990         if (e == NULL)
15991                 return (ISC_R_NOMEMORY);
15992 
15993         LOCK_ZONE(zone);
15994         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15995         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15996         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15997         zone->statelist = &zmgr->xfrin_in_progress;
15998         isc_task_send(zone->task, &e);
15999         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
16000         UNLOCK_ZONE(zone);
16001 
16002         return (ISC_R_SUCCESS);
16003 }
16004 
16005 void
16006 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
16007 
16008         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16009         REQUIRE(iolimit > 0);
16010 
16011         zmgr->iolimit = iolimit;
16012 }
16013 
16014 isc_uint32_t
16015 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
16016 
16017         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16018 
16019         return (zmgr->iolimit);
16020 }
16021 
16022 /*
16023  * Get permission to request a file handle from the OS.
16024  * An event will be sent to action when one is available.
16025  * There are two queues available (high and low), the high
16026  * queue will be serviced before the low one.
16027  *
16028  * zonemgr_putio() must be called after the event is delivered to
16029  * 'action'.
16030  */
16031 
16032 static isc_result_t
16033 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
16034               isc_task_t *task, isc_taskaction_t action, void *arg,
16035               dns_io_t **iop)
16036 {
16037         dns_io_t *io;
16038         isc_boolean_t queue;
16039 
16040         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16041         REQUIRE(iop != NULL && *iop == NULL);
16042 
16043         io = isc_mem_get(zmgr->mctx, sizeof(*io));
16044         if (io == NULL)
16045                 return (ISC_R_NOMEMORY);
16046 
16047         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
16048                                        action, arg, sizeof(*io->event));
16049         if (io->event == NULL) {
16050                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
16051                 return (ISC_R_NOMEMORY);
16052         }
16053 
16054         io->zmgr = zmgr;
16055         io->high = high;
16056         io->task = NULL;
16057         isc_task_attach(task, &io->task);
16058         ISC_LINK_INIT(io, link);
16059         io->magic = IO_MAGIC;
16060 
16061         LOCK(&zmgr->iolock);
16062         zmgr->ioactive++;
16063         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
16064         if (queue) {
16065                 if (io->high)
16066                         ISC_LIST_APPEND(zmgr->high, io, link);
16067                 else
16068                         ISC_LIST_APPEND(zmgr->low, io, link);
16069         }
16070         UNLOCK(&zmgr->iolock);
16071         *iop = io;
16072 
16073         if (!queue)
16074                 isc_task_send(io->task, &io->event);
16075         return (ISC_R_SUCCESS);
16076 }
16077 
16078 static void
16079 zonemgr_putio(dns_io_t **iop) {
16080         dns_io_t *io;
16081         dns_io_t *next;
16082         dns_zonemgr_t *zmgr;
16083 
16084         REQUIRE(iop != NULL);
16085         io = *iop;
16086         REQUIRE(DNS_IO_VALID(io));
16087 
16088         *iop = NULL;
16089 
16090         INSIST(!ISC_LINK_LINKED(io, link));
16091         INSIST(io->event == NULL);
16092 
16093         zmgr = io->zmgr;
16094         isc_task_detach(&io->task);
16095         io->magic = 0;
16096         isc_mem_put(zmgr->mctx, io, sizeof(*io));
16097 
16098         LOCK(&zmgr->iolock);
16099         INSIST(zmgr->ioactive > 0);
16100         zmgr->ioactive--;
16101         next = HEAD(zmgr->high);
16102         if (next == NULL)
16103                 next = HEAD(zmgr->low);
16104         if (next != NULL) {
16105                 if (next->high)
16106                         ISC_LIST_UNLINK(zmgr->high, next, link);
16107                 else
16108                         ISC_LIST_UNLINK(zmgr->low, next, link);
16109                 INSIST(next->event != NULL);
16110         }
16111         UNLOCK(&zmgr->iolock);
16112         if (next != NULL)
16113                 isc_task_send(next->task, &next->event);
16114 }
16115 
16116 static void
16117 zonemgr_cancelio(dns_io_t *io) {
16118         isc_boolean_t send_event = ISC_FALSE;
16119 
16120         REQUIRE(DNS_IO_VALID(io));
16121 
16122         /*
16123          * If we are queued to be run then dequeue.
16124          */
16125         LOCK(&io->zmgr->iolock);
16126         if (ISC_LINK_LINKED(io, link)) {
16127                 if (io->high)
16128                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
16129                 else
16130                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
16131 
16132                 send_event = ISC_TRUE;
16133                 INSIST(io->event != NULL);
16134         }
16135         UNLOCK(&io->zmgr->iolock);
16136         if (send_event) {
16137                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
16138                 isc_task_send(io->task, &io->event);
16139         }
16140 }
16141 
16142 static void
16143 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
16144         char *buf;
16145         int buflen;
16146         isc_result_t result;
16147 
16148         buflen = strlen(path) + strlen(templat) + 2;
16149 
16150         buf = isc_mem_get(zone->mctx, buflen);
16151         if (buf == NULL)
16152                 return;
16153 
16154         result = isc_file_template(path, templat, buf, buflen);
16155         if (result != ISC_R_SUCCESS)
16156                 goto cleanup;
16157 
16158         result = isc_file_renameunique(path, buf);
16159         if (result != ISC_R_SUCCESS)
16160                 goto cleanup;
16161 
16162         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
16163                      "renaming file to '%s' for failure analysis and "
16164                      "retransferring.", path, buf);
16165 
16166  cleanup:
16167         isc_mem_put(zone->mctx, buf, buflen);
16168 }
16169 
16170 #if 0
16171 /* Hook for ondestroy notification from a database. */
16172 
16173 static void
16174 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
16175         dns_db_t *db = event->sender;
16176         UNUSED(task);
16177 
16178         isc_event_free(&event);
16179 
16180         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16181                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16182                       "database (%p) destroyed", (void*) db);
16183 }
16184 #endif
16185 
16186 static void
16187 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
16188         isc_interval_t interval;
16189         isc_uint32_t s, ns;
16190         isc_uint32_t pertic;
16191         isc_result_t result;
16192 
16193         if (value == 0)
16194                 value = 1;
16195 
16196         if (value == 1) {
16197                 s = 1;
16198                 ns = 0;
16199                 pertic = 1;
16200         } else if (value <= 10) {
16201                 s = 0;
16202                 ns = 1000000000 / value;
16203                 pertic = 1;
16204         } else {
16205                 s = 0;
16206                 ns = (1000000000 / value) * 10;
16207                 pertic = 10;
16208         }
16209 
16210         isc_interval_set(&interval, s, ns);
16211 
16212         result = isc_ratelimiter_setinterval(rl, &interval);
16213         RUNTIME_CHECK(result == ISC_R_SUCCESS);
16214         isc_ratelimiter_setpertic(rl, pertic);
16215 
16216         *rate = value;
16217 }
16218 
16219 void
16220 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
16221 
16222         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16223 
16224         setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
16225 }
16226 
16227 void
16228 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
16229 
16230         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16231 
16232         setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
16233 }
16234 
16235 void
16236 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
16237 
16238         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16239 
16240         setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
16241         /* XXXMPA seperate out once we have the code to support this. */
16242         setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
16243 }
16244 
16245 unsigned int
16246 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
16247         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16248 
16249         return (zmgr->notifyrate);
16250 }
16251 
16252 unsigned int
16253 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
16254         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16255 
16256         return (zmgr->startupnotifyrate);
16257 }
16258 
16259 unsigned int
16260 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
16261         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16262 
16263         return (zmgr->serialqueryrate);
16264 }
16265 
16266 isc_boolean_t
16267 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16268                         isc_sockaddr_t *local, isc_time_t *now)
16269 {
16270         unsigned int i;
16271         isc_rwlocktype_t locktype;
16272         isc_result_t result;
16273         isc_uint32_t seconds = isc_time_seconds(now);
16274         isc_uint32_t count = 0;
16275 
16276         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16277 
16278         locktype = isc_rwlocktype_read;
16279         RWLOCK(&zmgr->urlock, locktype);
16280         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16281                 if (zmgr->unreachable[i].expire >= seconds &&
16282                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16283                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
16284                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
16285                         if (result == ISC_R_SUCCESS) {
16286                                 locktype = isc_rwlocktype_write;
16287                                 zmgr->unreachable[i].last = seconds;
16288                                 count = zmgr->unreachable[i].count;
16289                         }
16290                         break;
16291                 }
16292         }
16293         RWUNLOCK(&zmgr->urlock, locktype);
16294         return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
16295 }
16296 
16297 void
16298 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16299                            isc_sockaddr_t *local)
16300 {
16301         unsigned int i;
16302         isc_rwlocktype_t locktype;
16303         isc_result_t result;
16304 
16305         char master[ISC_SOCKADDR_FORMATSIZE];
16306         char source[ISC_SOCKADDR_FORMATSIZE];
16307 
16308         isc_sockaddr_format(remote, master, sizeof(master));
16309         isc_sockaddr_format(local, source, sizeof(source));
16310 
16311         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16312 
16313         locktype = isc_rwlocktype_read;
16314         RWLOCK(&zmgr->urlock, locktype);
16315         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16316                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16317                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
16318                         if (zmgr->unreachable[i].expire == 0)
16319                                 break;
16320                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
16321                         if (result == ISC_R_SUCCESS) {
16322                                 locktype = isc_rwlocktype_write;
16323                                 zmgr->unreachable[i].expire = 0;
16324                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16325                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
16326                                               "master %s (source %s) deleted "
16327                                               "from unreachable cache",
16328                                               master, source);
16329                         }
16330                         break;
16331                 }
16332         }
16333         RWUNLOCK(&zmgr->urlock, locktype);
16334 }
16335 
16336 void
16337 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16338                            isc_sockaddr_t *local, isc_time_t *now)
16339 {
16340         isc_uint32_t seconds = isc_time_seconds(now);
16341         isc_uint32_t last = seconds;
16342         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
16343 
16344         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16345 
16346         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
16347         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16348                 /* Existing entry? */
16349                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16350                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
16351                         break;
16352                 /* Empty slot? */
16353                 if (zmgr->unreachable[i].expire < seconds)
16354                         slot = i;
16355                 /* Least recently used slot? */
16356                 if (zmgr->unreachable[i].last < last) {
16357                         last = zmgr->unreachable[i].last;
16358                         oldest = i;
16359                 }
16360         }
16361         if (i < UNREACH_CHACHE_SIZE) {
16362                 /*
16363                  * Found a existing entry.  Update the expire timer and
16364                  * last usage timestamps.
16365                  */
16366                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
16367                 zmgr->unreachable[i].last = seconds;
16368                 if (zmgr->unreachable[i].expire < seconds)
16369                         zmgr->unreachable[i].count = 1;
16370                 else
16371                         zmgr->unreachable[i].count++;
16372         } else if (slot != UNREACH_CHACHE_SIZE) {
16373                 /*
16374                  * Found a empty slot. Add a new entry to the cache.
16375                  */
16376                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
16377                 zmgr->unreachable[slot].last = seconds;
16378                 zmgr->unreachable[slot].remote = *remote;
16379                 zmgr->unreachable[slot].local = *local;
16380                 zmgr->unreachable[slot].count = 1;
16381         } else {
16382                 /*
16383                  * Replace the least recently used entry in the cache.
16384                  */
16385                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
16386                 zmgr->unreachable[oldest].last = seconds;
16387                 zmgr->unreachable[oldest].remote = *remote;
16388                 zmgr->unreachable[oldest].local = *local;
16389                 zmgr->unreachable[oldest].count = 1;
16390         }
16391         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
16392 }
16393 
16394 void
16395 dns_zone_forcereload(dns_zone_t *zone) {
16396         REQUIRE(DNS_ZONE_VALID(zone));
16397 
16398         if (zone->type == dns_zone_master ||
16399             (zone->type == dns_zone_redirect && zone->masters == NULL))
16400                 return;
16401 
16402         LOCK_ZONE(zone);
16403         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
16404         UNLOCK_ZONE(zone);
16405         dns_zone_refresh(zone);
16406 }
16407 
16408 isc_boolean_t
16409 dns_zone_isforced(dns_zone_t *zone) {
16410         REQUIRE(DNS_ZONE_VALID(zone));
16411 
16412         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
16413 }
16414 
16415 isc_result_t
16416 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
16417         /*
16418          * This function is obsoleted.
16419          */
16420         UNUSED(zone);
16421         UNUSED(on);
16422         return (ISC_R_NOTIMPLEMENTED);
16423 }
16424 
16425 isc_uint64_t *
16426 dns_zone_getstatscounters(dns_zone_t *zone) {
16427         /*
16428          * This function is obsoleted.
16429          */
16430         UNUSED(zone);
16431         return (NULL);
16432 }
16433 
16434 void
16435 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
16436         REQUIRE(DNS_ZONE_VALID(zone));
16437         REQUIRE(zone->stats == NULL);
16438 
16439         LOCK_ZONE(zone);
16440         zone->stats = NULL;
16441         isc_stats_attach(stats, &zone->stats);
16442         UNLOCK_ZONE(zone);
16443 }
16444 
16445 void
16446 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
16447 
16448         REQUIRE(DNS_ZONE_VALID(zone));
16449 
16450         LOCK_ZONE(zone);
16451         if (zone->requeststats_on && stats == NULL)
16452                 zone->requeststats_on = ISC_FALSE;
16453         else if (!zone->requeststats_on && stats != NULL) {
16454                 if (zone->requeststats == NULL) {
16455                         isc_stats_attach(stats, &zone->requeststats);
16456                         zone->requeststats_on = ISC_TRUE;
16457                 }
16458         }
16459         UNLOCK_ZONE(zone);
16460 }
16461 
16462 void
16463 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
16464 
16465         REQUIRE(DNS_ZONE_VALID(zone));
16466 
16467         LOCK_ZONE(zone);
16468         if (zone->requeststats_on && stats != NULL) {
16469                 if (zone->rcvquerystats == NULL) {
16470                         dns_stats_attach(stats, &zone->rcvquerystats);
16471                         zone->requeststats_on = ISC_TRUE;
16472                 }
16473         }
16474         UNLOCK_ZONE(zone);
16475 }
16476 
16477 isc_stats_t *
16478 dns_zone_getrequeststats(dns_zone_t *zone) {
16479         /*
16480          * We don't lock zone for efficiency reason.  This is not catastrophic
16481          * because requeststats must always be valid when requeststats_on is
16482          * true.
16483          * Some counters may be incremented while requeststats_on is becoming
16484          * false, or some cannot be incremented just after the statistics are
16485          * installed, but it shouldn't matter much in practice.
16486          */
16487         if (zone->requeststats_on)
16488                 return (zone->requeststats);
16489         else
16490                 return (NULL);
16491 }
16492 
16493 /*
16494  * Return the received query stats bucket
16495  * see note from dns_zone_getrequeststats()
16496  */
16497 dns_stats_t *
16498 dns_zone_getrcvquerystats(dns_zone_t *zone) {
16499         if (zone->requeststats_on)
16500                 return (zone->rcvquerystats);
16501         else
16502                 return (NULL);
16503 }
16504 
16505 void
16506 dns_zone_dialup(dns_zone_t *zone) {
16507 
16508         REQUIRE(DNS_ZONE_VALID(zone));
16509 
16510         zone_debuglog(zone, "dns_zone_dialup", 3,
16511                       "notify = %d, refresh = %d",
16512                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
16513                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
16514 
16515         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
16516                 dns_zone_notify(zone);
16517         if (zone->type != dns_zone_master && zone->masters != NULL &&
16518             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
16519                 dns_zone_refresh(zone);
16520 }
16521 
16522 void
16523 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
16524         REQUIRE(DNS_ZONE_VALID(zone));
16525 
16526         LOCK_ZONE(zone);
16527         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
16528                          DNS_ZONEFLG_DIALREFRESH |
16529                          DNS_ZONEFLG_NOREFRESH);
16530         switch (dialup) {
16531         case dns_dialuptype_no:
16532                 break;
16533         case dns_dialuptype_yes:
16534                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
16535                                  DNS_ZONEFLG_DIALREFRESH |
16536                                  DNS_ZONEFLG_NOREFRESH));
16537                 break;
16538         case dns_dialuptype_notify:
16539                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
16540                 break;
16541         case dns_dialuptype_notifypassive:
16542                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
16543                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
16544                 break;
16545         case dns_dialuptype_refresh:
16546                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
16547                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
16548                 break;
16549         case dns_dialuptype_passive:
16550                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
16551                 break;
16552         default:
16553                 INSIST(0);
16554         }
16555         UNLOCK_ZONE(zone);
16556 }
16557 
16558 isc_result_t
16559 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
16560         isc_result_t result = ISC_R_SUCCESS;
16561 
16562         REQUIRE(DNS_ZONE_VALID(zone));
16563 
16564         LOCK_ZONE(zone);
16565         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
16566         UNLOCK_ZONE(zone);
16567 
16568         return (result);
16569 }
16570 
16571 const char *
16572 dns_zone_getkeydirectory(dns_zone_t *zone) {
16573         REQUIRE(DNS_ZONE_VALID(zone));
16574 
16575         return (zone->keydirectory);
16576 }
16577 
16578 unsigned int
16579 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
16580         dns_zone_t *zone;
16581         unsigned int count = 0;
16582 
16583         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16584 
16585         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16586         switch (state) {
16587         case DNS_ZONESTATE_XFERRUNNING:
16588                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
16589                      zone != NULL;
16590                      zone = ISC_LIST_NEXT(zone, statelink))
16591                         count++;
16592                 break;
16593         case DNS_ZONESTATE_XFERDEFERRED:
16594                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
16595                      zone != NULL;
16596                      zone = ISC_LIST_NEXT(zone, statelink))
16597                         count++;
16598                 break;
16599         case DNS_ZONESTATE_SOAQUERY:
16600                 for (zone = ISC_LIST_HEAD(zmgr->zones);
16601                      zone != NULL;
16602                      zone = ISC_LIST_NEXT(zone, link))
16603                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
16604                                 count++;
16605                 break;
16606         case DNS_ZONESTATE_ANY:
16607                 for (zone = ISC_LIST_HEAD(zmgr->zones);
16608                      zone != NULL;
16609                      zone = ISC_LIST_NEXT(zone, link)) {
16610                         dns_view_t *view = zone->view;
16611                         if (view != NULL && strcmp(view->name, "_bind") == 0)
16612                                 continue;
16613                         count++;
16614                 }
16615                 break;
16616         case DNS_ZONESTATE_AUTOMATIC:
16617                 for (zone = ISC_LIST_HEAD(zmgr->zones);
16618                      zone != NULL;
16619                      zone = ISC_LIST_NEXT(zone, link)) {
16620                         dns_view_t *view = zone->view;
16621                         if (view != NULL && strcmp(view->name, "_bind") == 0)
16622                                 continue;
16623                         if (zone->automatic)
16624                                 count++;
16625                 }
16626                 break;
16627         default:
16628                 INSIST(0);
16629         }
16630 
16631         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16632 
16633         return (count);
16634 }
16635 
16636 isc_result_t
16637 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
16638         isc_boolean_t ok = ISC_TRUE;
16639         isc_boolean_t fail = ISC_FALSE;
16640         char namebuf[DNS_NAME_FORMATSIZE];
16641         char namebuf2[DNS_NAME_FORMATSIZE];
16642         char typebuf[DNS_RDATATYPE_FORMATSIZE];
16643         int level = ISC_LOG_WARNING;
16644         dns_name_t bad;
16645 
16646         REQUIRE(DNS_ZONE_VALID(zone));
16647 
16648         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
16649             rdata->type != dns_rdatatype_nsec3)
16650                 return (ISC_R_SUCCESS);
16651 
16652         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
16653             rdata->type == dns_rdatatype_nsec3) {
16654                 level = ISC_LOG_ERROR;
16655                 fail = ISC_TRUE;
16656         }
16657 
16658         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
16659         if (!ok) {
16660                 dns_name_format(name, namebuf, sizeof(namebuf));
16661                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16662                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
16663                              dns_result_totext(DNS_R_BADOWNERNAME));
16664                 if (fail)
16665                         return (DNS_R_BADOWNERNAME);
16666         }
16667 
16668         dns_name_init(&bad, NULL);
16669         ok = dns_rdata_checknames(rdata, name, &bad);
16670         if (!ok) {
16671                 dns_name_format(name, namebuf, sizeof(namebuf));
16672                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
16673                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16674                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
16675                              namebuf2, dns_result_totext(DNS_R_BADNAME));
16676                 if (fail)
16677                         return (DNS_R_BADNAME);
16678         }
16679 
16680         return (ISC_R_SUCCESS);
16681 }
16682 
16683 void
16684 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
16685         REQUIRE(DNS_ZONE_VALID(zone));
16686         zone->checkmx = checkmx;
16687 }
16688 
16689 void
16690 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
16691         REQUIRE(DNS_ZONE_VALID(zone));
16692         zone->checksrv = checksrv;
16693 }
16694 
16695 void
16696 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
16697         REQUIRE(DNS_ZONE_VALID(zone));
16698         zone->checkns = checkns;
16699 }
16700 
16701 void
16702 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
16703         REQUIRE(DNS_ZONE_VALID(zone));
16704 
16705         LOCK_ZONE(zone);
16706         zone->isself = isself;
16707         zone->isselfarg = arg;
16708         UNLOCK_ZONE(zone);
16709 }
16710 
16711 void
16712 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
16713         REQUIRE(DNS_ZONE_VALID(zone));
16714 
16715         LOCK_ZONE(zone);
16716         zone->notifydelay = delay;
16717         UNLOCK_ZONE(zone);
16718 }
16719 
16720 isc_uint32_t
16721 dns_zone_getnotifydelay(dns_zone_t *zone) {
16722         REQUIRE(DNS_ZONE_VALID(zone));
16723 
16724         return (zone->notifydelay);
16725 }
16726 
16727 isc_result_t
16728 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
16729                      isc_uint16_t keyid, isc_boolean_t delete)
16730 {
16731         isc_result_t result;
16732         REQUIRE(DNS_ZONE_VALID(zone));
16733 
16734         dns_zone_log(zone, ISC_LOG_NOTICE,
16735                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
16736                      algorithm, keyid);
16737         LOCK_ZONE(zone);
16738         result = zone_signwithkey(zone, algorithm, keyid, delete);
16739         UNLOCK_ZONE(zone);
16740 
16741         return (result);
16742 }
16743 
16744 static const char *hex = "0123456789ABCDEF";
16745 
16746 isc_result_t
16747 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
16748         isc_result_t result;
16749         char salt[255*2+1];
16750         unsigned int i, j;
16751 
16752         REQUIRE(DNS_ZONE_VALID(zone));
16753 
16754         if (nsec3param->salt_length != 0) {
16755                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
16756                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
16757                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
16758                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
16759                 }
16760                 salt[j] = '\0';
16761         } else
16762                 strcpy(salt, "-");
16763         dns_zone_log(zone, ISC_LOG_NOTICE,
16764                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
16765                      nsec3param->hash, nsec3param->iterations,
16766                      salt);
16767         LOCK_ZONE(zone);
16768         result = zone_addnsec3chain(zone, nsec3param);
16769         UNLOCK_ZONE(zone);
16770 
16771         return (result);
16772 }
16773 
16774 void
16775 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
16776         REQUIRE(DNS_ZONE_VALID(zone));
16777 
16778         if (nodes == 0)
16779                 nodes = 1;
16780         zone->nodes = nodes;
16781 }
16782 
16783 void
16784 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
16785         REQUIRE(DNS_ZONE_VALID(zone));
16786 
16787         /*
16788          * We treat signatures as a signed value so explicitly
16789          * limit its range here.
16790          */
16791         if (signatures > ISC_INT32_MAX)
16792                 signatures = ISC_INT32_MAX;
16793         else if (signatures == 0)
16794                 signatures = 1;
16795         zone->signatures = signatures;
16796 }
16797 
16798 isc_uint32_t
16799 dns_zone_getsignatures(dns_zone_t *zone) {
16800         REQUIRE(DNS_ZONE_VALID(zone));
16801         return (zone->signatures);
16802 }
16803 
16804 void
16805 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
16806         REQUIRE(DNS_ZONE_VALID(zone));
16807         zone->privatetype = type;
16808 }
16809 
16810 dns_rdatatype_t
16811 dns_zone_getprivatetype(dns_zone_t *zone) {
16812         REQUIRE(DNS_ZONE_VALID(zone));
16813         return (zone->privatetype);
16814 }
16815 
16816 static isc_result_t
16817 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
16818                  isc_boolean_t delete)
16819 {
16820         dns_signing_t *signing;
16821         dns_signing_t *current;
16822         isc_result_t result = ISC_R_SUCCESS;
16823         isc_time_t now;
16824         dns_db_t *db = NULL;
16825 
16826         signing = isc_mem_get(zone->mctx, sizeof *signing);
16827         if (signing == NULL)
16828                 return (ISC_R_NOMEMORY);
16829 
16830         signing->magic = 0;
16831         signing->db  = NULL;
16832         signing->dbiterator = NULL;
16833         signing->algorithm = algorithm;
16834         signing->keyid = keyid;
16835         signing->delete = delete;
16836         signing->done = ISC_FALSE;
16837 
16838         TIME_NOW(&now);
16839 
16840         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16841         if (zone->db != NULL)
16842                 dns_db_attach(zone->db, &db);
16843         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16844 
16845         if (db == NULL) {
16846                 result = ISC_R_NOTFOUND;
16847                 goto cleanup;
16848         }
16849 
16850         dns_db_attach(db, &signing->db);
16851 
16852         for (current = ISC_LIST_HEAD(zone->signing);
16853              current != NULL;
16854              current = ISC_LIST_NEXT(current, link)) {
16855                 if (current->db == signing->db &&
16856                     current->algorithm == signing->algorithm &&
16857                     current->keyid == signing->keyid) {
16858                         if (current->delete != signing->delete)
16859                                 current->done = ISC_TRUE;
16860                         else
16861                                 goto cleanup;
16862                 }
16863         }
16864 
16865         result = dns_db_createiterator(signing->db, 0,
16866                                        &signing->dbiterator);
16867 
16868         if (result == ISC_R_SUCCESS)
16869                 result = dns_dbiterator_first(signing->dbiterator);
16870         if (result == ISC_R_SUCCESS) {
16871                 dns_dbiterator_pause(signing->dbiterator);
16872                 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
16873                 signing = NULL;
16874                 if (isc_time_isepoch(&zone->signingtime)) {
16875                         zone->signingtime = now;
16876                         if (zone->task != NULL)
16877                                 zone_settimer(zone, &now);
16878                 }
16879         }
16880 
16881  cleanup:
16882         if (signing != NULL) {
16883                 if (signing->db != NULL)
16884                         dns_db_detach(&signing->db);
16885                 if (signing->dbiterator != NULL)
16886                         dns_dbiterator_destroy(&signing->dbiterator);
16887                 isc_mem_put(zone->mctx, signing, sizeof *signing);
16888         }
16889         if (db != NULL)
16890                 dns_db_detach(&db);
16891         return (result);
16892 }
16893 
16894 static void
16895 logmsg(const char *format, ...) {
16896         va_list args;
16897         va_start(args, format);
16898         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
16899                        ISC_LOG_DEBUG(1), format, args);
16900         va_end(args);
16901 }
16902 
16903 static void
16904 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
16905         dns_dnsseckey_t *key;
16906         while (!ISC_LIST_EMPTY(*list)) {
16907                 key = ISC_LIST_HEAD(*list);
16908                 ISC_LIST_UNLINK(*list, key, link);
16909                 dns_dnsseckey_destroy(mctx, &key);
16910         }
16911 }
16912 
16913 /* Called once; *timep should be set to the current time. */
16914 static isc_result_t
16915 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
16916         isc_result_t result;
16917         isc_stdtime_t now, then = 0, event;
16918         int i;
16919 
16920         now = *timep;
16921 
16922         for (i = 0; i <= DST_MAX_TIMES; i++) {
16923                 result = dst_key_gettime(key, i, &event);
16924                 if (result == ISC_R_SUCCESS && event > now &&
16925                     (then == 0 || event < then))
16926                         then = event;
16927         }
16928 
16929         if (then != 0) {
16930                 *timep = then;
16931                 return (ISC_R_SUCCESS);
16932         }
16933 
16934         return (ISC_R_NOTFOUND);
16935 }
16936 
16937 static isc_result_t
16938 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
16939           const dns_rdata_t *rdata, isc_boolean_t *flag)
16940 {
16941         dns_rdataset_t rdataset;
16942         dns_dbnode_t *node = NULL;
16943         isc_result_t result;
16944 
16945         dns_rdataset_init(&rdataset);
16946         if (rdata->type == dns_rdatatype_nsec3)
16947                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
16948         else
16949                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
16950         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
16951                                      (isc_stdtime_t) 0, &rdataset, NULL);
16952         if (result == ISC_R_NOTFOUND) {
16953                 *flag = ISC_FALSE;
16954                 result = ISC_R_SUCCESS;
16955                 goto failure;
16956         }
16957 
16958         for (result = dns_rdataset_first(&rdataset);
16959              result == ISC_R_SUCCESS;
16960              result = dns_rdataset_next(&rdataset)) {
16961                 dns_rdata_t myrdata = DNS_RDATA_INIT;
16962                 dns_rdataset_current(&rdataset, &myrdata);
16963                 if (!dns_rdata_compare(&myrdata, rdata))
16964                         break;
16965         }
16966         dns_rdataset_disassociate(&rdataset);
16967         if (result == ISC_R_SUCCESS) {
16968                 *flag = ISC_TRUE;
16969         } else if (result == ISC_R_NOMORE) {
16970                 *flag = ISC_FALSE;
16971                 result = ISC_R_SUCCESS;
16972         }
16973 
16974  failure:
16975         if (node != NULL)
16976                 dns_db_detachnode(db, &node);
16977         return (result);
16978 }
16979 
16980 /*
16981  * Add records to signal the state of signing or of key removal.
16982  */
16983 static isc_result_t
16984 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16985                     dns_dbversion_t *ver, dns_diff_t *diff,
16986                     isc_boolean_t sign_all)
16987 {
16988         dns_difftuple_t *tuple, *newtuple = NULL;
16989         dns_rdata_dnskey_t dnskey;
16990         dns_rdata_t rdata = DNS_RDATA_INIT;
16991         isc_boolean_t flag;
16992         isc_region_t r;
16993         isc_result_t result = ISC_R_SUCCESS;
16994         isc_uint16_t keyid;
16995         unsigned char buf[5];
16996         dns_name_t *name = dns_db_origin(db);
16997 
16998         for (tuple = ISC_LIST_HEAD(diff->tuples);
16999              tuple != NULL;
17000              tuple = ISC_LIST_NEXT(tuple, link)) {
17001                 if (tuple->rdata.type != dns_rdatatype_dnskey)
17002                         continue;
17003 
17004                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
17005                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17006                 if ((dnskey.flags &
17007                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
17008                          != DNS_KEYOWNER_ZONE)
17009                         continue;
17010 
17011                 dns_rdata_toregion(&tuple->rdata, &r);
17012 
17013                 keyid = dst_region_computeid(&r, dnskey.algorithm);
17014 
17015                 buf[0] = dnskey.algorithm;
17016                 buf[1] = (keyid & 0xff00) >> 8;
17017                 buf[2] = (keyid & 0xff);
17018                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
17019                 buf[4] = 0;
17020                 rdata.data = buf;
17021                 rdata.length = sizeof(buf);
17022                 rdata.type = privatetype;
17023                 rdata.rdclass = tuple->rdata.rdclass;
17024 
17025                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
17026                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
17027                         if (flag)
17028                                 continue;
17029                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
17030                                                    name, 0, &rdata, &newtuple));
17031                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
17032                         INSIST(newtuple == NULL);
17033                 }
17034 
17035                 /*
17036                  * Remove any record which says this operation has already
17037                  * completed.
17038                  */
17039                 buf[4] = 1;
17040                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
17041                 if (flag) {
17042                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
17043                                                    name, 0, &rdata, &newtuple));
17044                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
17045                         INSIST(newtuple == NULL);
17046                 }
17047         }
17048  failure:
17049         return (result);
17050 }
17051 
17052 static isc_result_t
17053 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17054           dns_diff_t *diff, zonediff_t *zonediff)
17055 {
17056         isc_result_t result;
17057         isc_stdtime_t now, inception, soaexpire;
17058         isc_boolean_t check_ksk, keyset_kskonly;
17059         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
17060         unsigned int nkeys = 0, i;
17061         dns_difftuple_t *tuple;
17062 
17063         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
17064                                 zone_keys, &nkeys);
17065         if (result != ISC_R_SUCCESS) {
17066                 dns_zone_log(zone, ISC_LOG_ERROR,
17067                              "sign_apex:find_zone_keys -> %s",
17068                              dns_result_totext(result));
17069                 return (result);
17070         }
17071 
17072         isc_stdtime_get(&now);
17073         inception = now - 3600; /* Allow for clock skew. */
17074         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
17075 
17076         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
17077         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
17078 
17079         /*
17080          * See if update_sigs will update DNSKEY signature and if not
17081          * cause them to sign so that so that newly activated keys
17082          * are used.
17083          */
17084         for (tuple = ISC_LIST_HEAD(diff->tuples);
17085              tuple != NULL;
17086              tuple = ISC_LIST_NEXT(tuple, link)) {
17087                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
17088                     dns_name_equal(&tuple->name, &zone->origin))
17089                         break;
17090         }
17091 
17092         if (tuple == NULL) {
17093                 result = del_sigs(zone, db, ver, &zone->origin,
17094                                   dns_rdatatype_dnskey, zonediff,
17095                                   zone_keys, nkeys, now, ISC_FALSE);
17096                 if (result != ISC_R_SUCCESS) {
17097                         dns_zone_log(zone, ISC_LOG_ERROR,
17098                                      "sign_apex:del_sigs -> %s",
17099                                      dns_result_totext(result));
17100                         goto failure;
17101                 }
17102                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
17103                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
17104                                   inception, soaexpire, check_ksk,
17105                                   keyset_kskonly);
17106                 if (result != ISC_R_SUCCESS) {
17107                         dns_zone_log(zone, ISC_LOG_ERROR,
17108                                      "sign_apex:add_sigs -> %s",
17109                                      dns_result_totext(result));
17110                         goto failure;
17111                 }
17112         }
17113 
17114         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
17115                              inception, soaexpire, now, check_ksk,
17116                              keyset_kskonly, zonediff);
17117 
17118         if (result != ISC_R_SUCCESS) {
17119                 dns_zone_log(zone, ISC_LOG_ERROR,
17120                              "sign_apex:update_sigs -> %s",
17121                              dns_result_totext(result));
17122                 goto failure;
17123         }
17124 
17125  failure:
17126         for (i = 0; i < nkeys; i++)
17127                 dst_key_free(&zone_keys[i]);
17128         return (result);
17129 }
17130 
17131 /*
17132  * Prevent the zone entering a inconsistent state where
17133  * NSEC only DNSKEYs are present with NSEC3 chains.
17134  * See update.c:check_dnssec()
17135  */
17136 static isc_boolean_t
17137 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17138             dns_diff_t *diff)
17139 {
17140         isc_result_t result;
17141         dns_difftuple_t *tuple;
17142         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
17143         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
17144 
17145         /* Scan the tuples for an NSEC-only DNSKEY */
17146         for (tuple = ISC_LIST_HEAD(diff->tuples);
17147              tuple != NULL;
17148              tuple = ISC_LIST_NEXT(tuple, link)) {
17149                 isc_uint8_t alg;
17150                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
17151                     tuple->op != DNS_DIFFOP_ADD)
17152                         continue;
17153 
17154                 alg = tuple->rdata.data[3];
17155                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
17156                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
17157                         nseconly = ISC_TRUE;
17158                         break;
17159                 }
17160         }
17161 
17162         /* Check existing DB for NSEC-only DNSKEY */
17163         if (!nseconly) {
17164                 result = dns_nsec_nseconly(db, ver, &nseconly);
17165                 if (result == ISC_R_NOTFOUND)
17166                         result = ISC_R_SUCCESS;
17167                 CHECK(result);
17168         }
17169 
17170         /* Check existing DB for NSEC3 */
17171         if (!nsec3)
17172                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
17173                                         privatetype, &nsec3));
17174 
17175         /* Refuse to allow NSEC3 with NSEC-only keys */
17176         if (nseconly && nsec3) {
17177                 dns_zone_log(zone, ISC_LOG_ERROR,
17178                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
17179                 goto failure;
17180         }
17181 
17182         return (ISC_TRUE);
17183 
17184  failure:
17185         return (ISC_FALSE);
17186 }
17187 
17188 static isc_result_t
17189 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17190                  dns_diff_t *diff)
17191 {
17192         isc_result_t result;
17193         dns_dbnode_t *node = NULL;
17194         dns_rdataset_t rdataset;
17195 
17196         dns_rdataset_init(&rdataset);
17197         CHECK(dns_db_getoriginnode(db, &node));
17198 
17199         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
17200                                      dns_rdatatype_none, 0, &rdataset, NULL);
17201         if (dns_rdataset_isassociated(&rdataset))
17202                 dns_rdataset_disassociate(&rdataset);
17203         if (result != ISC_R_NOTFOUND)
17204                 goto failure;
17205 
17206         result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
17207 
17208  failure:
17209         if (node != NULL)
17210                 dns_db_detachnode(db, &node);
17211         return (result);
17212 }
17213 
17214 /*
17215  * Given an RRSIG rdataset and an algorithm, determine whether there
17216  * are any signatures using that algorithm.
17217  */
17218 static isc_boolean_t
17219 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
17220         dns_rdata_t rdata = DNS_RDATA_INIT;
17221         dns_rdata_rrsig_t rrsig;
17222         isc_result_t result;
17223 
17224         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
17225         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
17226                 return (ISC_FALSE);
17227         }
17228 
17229         for (result = dns_rdataset_first(rdataset);
17230              result == ISC_R_SUCCESS;
17231              result = dns_rdataset_next(rdataset))
17232         {
17233                 dns_rdataset_current(rdataset, &rdata);
17234                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
17235                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17236                 dns_rdata_reset(&rdata);
17237                 if (rrsig.algorithm == alg)
17238                         return (ISC_TRUE);
17239         }
17240 
17241         return (ISC_FALSE);
17242 }
17243 
17244 static isc_result_t
17245 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17246            dns_diff_t *diff)
17247 {
17248         dns_name_t *origin;
17249         isc_boolean_t build_nsec3;
17250         isc_result_t result;
17251 
17252         origin = dns_db_origin(db);
17253         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
17254                                  &build_nsec3));
17255         if (build_nsec3)
17256                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
17257                                            ISC_FALSE, zone->privatetype, diff));
17258         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
17259 
17260  failure:
17261         return (result);
17262 }
17263 
17264 static void
17265 zone_rekey(dns_zone_t *zone) {
17266         isc_result_t result;
17267         dns_db_t *db = NULL;
17268         dns_dbnode_t *node = NULL;
17269         dns_dbversion_t *ver = NULL;
17270         dns_rdataset_t soaset, soasigs, keyset, keysigs;
17271         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
17272         dns_dnsseckey_t *key;
17273         dns_diff_t diff, _sig_diff;
17274         zonediff_t zonediff;
17275         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
17276         isc_boolean_t newalg = ISC_FALSE;
17277         isc_boolean_t fullsign;
17278         dns_ttl_t ttl = 3600;
17279         const char *dir;
17280         isc_mem_t *mctx;
17281         isc_stdtime_t now;
17282         isc_time_t timenow;
17283         isc_interval_t ival;
17284         char timebuf[80];
17285 
17286         REQUIRE(DNS_ZONE_VALID(zone));
17287 
17288         ISC_LIST_INIT(dnskeys);
17289         ISC_LIST_INIT(keys);
17290         ISC_LIST_INIT(rmkeys);
17291         dns_rdataset_init(&soaset);
17292         dns_rdataset_init(&soasigs);
17293         dns_rdataset_init(&keyset);
17294         dns_rdataset_init(&keysigs);
17295         dir = dns_zone_getkeydirectory(zone);
17296         mctx = zone->mctx;
17297         dns_diff_init(mctx, &diff);
17298         dns_diff_init(mctx, &_sig_diff);
17299         zonediff_init(&zonediff, &_sig_diff);
17300 
17301         CHECK(dns_zone_getdb(zone, &db));
17302         CHECK(dns_db_newversion(db, &ver));
17303         CHECK(dns_db_getoriginnode(db, &node));
17304 
17305         TIME_NOW(&timenow);
17306         now = isc_time_seconds(&timenow);
17307 
17308         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
17309 
17310         /* Get the SOA record's TTL */
17311         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
17312                                   dns_rdatatype_none, 0, &soaset, &soasigs));
17313         ttl = soaset.ttl;
17314         dns_rdataset_disassociate(&soaset);
17315 
17316         /* Get the DNSKEY rdataset */
17317         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
17318                                      dns_rdatatype_none, 0, &keyset, &keysigs);
17319         if (result == ISC_R_SUCCESS) {
17320                 ttl = keyset.ttl;
17321                 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
17322                                                      mctx, &keyset,
17323                                                      &keysigs, &soasigs,
17324                                                      ISC_FALSE, ISC_FALSE,
17325                                                      &dnskeys));
17326         } else if (result != ISC_R_NOTFOUND)
17327                 goto failure;
17328 
17329         /*
17330          * True when called from "rndc sign".  Indicates the zone should be
17331          * fully signed now.
17332          */
17333         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
17334 
17335         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
17336         if (result == ISC_R_SUCCESS) {
17337                 isc_boolean_t check_ksk;
17338                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
17339 
17340                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
17341                                                &zone->origin, ttl, &diff,
17342                                                ISC_TF(!check_ksk),
17343                                                mctx, logmsg);
17344 
17345                 /* Keys couldn't be updated for some reason;
17346                  * try again later. */
17347                 if (result != ISC_R_SUCCESS) {
17348                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
17349                                      "couldn't update zone keys: %s",
17350                                      isc_result_totext(result));
17351                         goto failure;
17352                 }
17353 
17354                 /*
17355                  * See if any pre-existing keys have newly become active;
17356                  * also, see if any new key is for a new algorithm, as in that
17357                  * event, we need to sign the zone fully.  (If there's a new
17358                  * key, but it's for an already-existing algorithm, then
17359                  * the zone signing can be handled incrementally.)
17360                  */
17361                 for (key = ISC_LIST_HEAD(dnskeys);
17362                      key != NULL;
17363                      key = ISC_LIST_NEXT(key, link)) {
17364                         if (!key->first_sign)
17365                                 continue;
17366 
17367                         newactive = ISC_TRUE;
17368 
17369                         if (!dns_rdataset_isassociated(&keysigs)) {
17370                                 newalg = ISC_TRUE;
17371                                 break;
17372                         }
17373 
17374                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
17375                                 /*
17376                                  * This isn't a new algorithm; clear
17377                                  * first_sign so we won't sign the
17378                                  * whole zone with this key later
17379                                  */
17380                                 key->first_sign = ISC_FALSE;
17381                         } else {
17382                                 newalg = ISC_TRUE;
17383                                 break;
17384                         }
17385                 }
17386 
17387                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
17388                     dnskey_sane(zone, db, ver, &diff)) {
17389                         CHECK(dns_diff_apply(&diff, db, ver));
17390                         CHECK(clean_nsec3param(zone, db, ver, &diff));
17391                         CHECK(add_signing_records(db, zone->privatetype,
17392                                                   ver, &diff,
17393                                                   ISC_TF(newalg || fullsign)));
17394                         CHECK(update_soa_serial(db, ver, &diff, mctx,
17395                                                 zone->updatemethod));
17396                         CHECK(add_chains(zone, db, ver, &diff));
17397                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
17398                         CHECK(zone_journal(zone, zonediff.diff, NULL,
17399                                            "zone_rekey"));
17400                         commit = ISC_TRUE;
17401                 }
17402         }
17403 
17404         dns_db_closeversion(db, &ver, ISC_TRUE);
17405 
17406         if (commit) {
17407                 dns_difftuple_t *tuple;
17408 
17409                 LOCK_ZONE(zone);
17410                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17411 
17412                 zone_needdump(zone, DNS_DUMP_DELAY);
17413 
17414                 zone_settimer(zone, &timenow);
17415 
17416                 /* Remove any signatures from removed keys.  */
17417                 if (!ISC_LIST_EMPTY(rmkeys)) {
17418                         for (key = ISC_LIST_HEAD(rmkeys);
17419                              key != NULL;
17420                              key = ISC_LIST_NEXT(key, link)) {
17421                                 result = zone_signwithkey(zone,
17422                                                           dst_key_alg(key->key),
17423                                                           dst_key_id(key->key),
17424                                                           ISC_TRUE);
17425                                 if (result != ISC_R_SUCCESS) {
17426                                         dns_zone_log(zone, ISC_LOG_ERROR,
17427                                              "zone_signwithkey failed: %s",
17428                                              dns_result_totext(result));
17429                                 }
17430                         }
17431                 }
17432 
17433                 if (fullsign) {
17434                         /*
17435                          * "rndc sign" was called, so we now sign the zone
17436                          * with all active keys, whether they're new or not.
17437                          */
17438                         for (key = ISC_LIST_HEAD(dnskeys);
17439                              key != NULL;
17440                              key = ISC_LIST_NEXT(key, link)) {
17441                                 if (!key->force_sign && !key->hint_sign)
17442                                         continue;
17443 
17444                                 result = zone_signwithkey(zone,
17445                                                           dst_key_alg(key->key),
17446                                                           dst_key_id(key->key),
17447                                                           ISC_FALSE);
17448                                 if (result != ISC_R_SUCCESS) {
17449                                         dns_zone_log(zone, ISC_LOG_ERROR,
17450                                              "zone_signwithkey failed: %s",
17451                                              dns_result_totext(result));
17452                                 }
17453                         }
17454                 } else if (newalg) {
17455                         /*
17456                          * We haven't been told to sign fully, but a new
17457                          * algorithm was added to the DNSKEY.  We sign
17458                          * the full zone, but only with newly active
17459                          * keys.
17460                          */
17461                         for (key = ISC_LIST_HEAD(dnskeys);
17462                              key != NULL;
17463                              key = ISC_LIST_NEXT(key, link)) {
17464                                 if (!key->first_sign)
17465                                         continue;
17466 
17467                                 result = zone_signwithkey(zone,
17468                                                           dst_key_alg(key->key),
17469                                                           dst_key_id(key->key),
17470                                                           ISC_FALSE);
17471                                 if (result != ISC_R_SUCCESS) {
17472                                         dns_zone_log(zone, ISC_LOG_ERROR,
17473                                              "zone_signwithkey failed: %s",
17474                                              dns_result_totext(result));
17475                                 }
17476                         }
17477                 }
17478 
17479                 /*
17480                  * Clear fullsign flag, if it was set, so we don't do
17481                  * another full signing next time
17482                  */
17483                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
17484 
17485                 /*
17486                  * Cause the zone to add/delete NSEC3 chains for the
17487                  * deferred NSEC3PARAM changes.
17488                  */
17489                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
17490                      tuple != NULL;
17491                      tuple = ISC_LIST_NEXT(tuple, link)) {
17492                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
17493                         dns_rdata_t rdata = DNS_RDATA_INIT;
17494                         dns_rdata_nsec3param_t nsec3param;
17495 
17496                         if (tuple->rdata.type != zone->privatetype ||
17497                             tuple->op != DNS_DIFFOP_ADD)
17498                                 continue;
17499 
17500                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
17501                                                         buf, sizeof(buf)))
17502                                 continue;
17503                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
17504                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
17505                         if (nsec3param.flags == 0)
17506                                 continue;
17507 
17508                         result = zone_addnsec3chain(zone, &nsec3param);
17509                         if (result != ISC_R_SUCCESS) {
17510                                 dns_zone_log(zone, ISC_LOG_ERROR,
17511                                              "zone_addnsec3chain failed: %s",
17512                                              dns_result_totext(result));
17513                         }
17514                 }
17515 
17516                 /*
17517                  * Activate any NSEC3 chain updates that may have
17518                  * been scheduled before this rekey.
17519                  */
17520                 if (fullsign || newalg)
17521                         resume_addnsec3chain(zone);
17522 
17523                 /*
17524                  * Schedule the next resigning event
17525                  */
17526                 set_resigntime(zone);
17527                 UNLOCK_ZONE(zone);
17528         }
17529 
17530         isc_time_settoepoch(&zone->refreshkeytime);
17531 
17532         /*
17533          * If we're doing key maintenance, set the key refresh timer to
17534          * the next scheduled key event or to 'dnssec-loadkeys-interval'
17535          * seconds in the future, whichever is sooner.
17536          */
17537         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
17538                 isc_time_t timethen;
17539                 isc_stdtime_t then;
17540 
17541                 LOCK_ZONE(zone);
17542                 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
17543                                   &timethen);
17544                 zone->refreshkeytime = timethen;
17545                 UNLOCK_ZONE(zone);
17546 
17547                 for (key = ISC_LIST_HEAD(dnskeys);
17548                      key != NULL;
17549                      key = ISC_LIST_NEXT(key, link)) {
17550                         then = now;
17551                         result = next_keyevent(key->key, &then);
17552                         if (result != ISC_R_SUCCESS)
17553                                 continue;
17554 
17555                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
17556                         LOCK_ZONE(zone);
17557                         if (isc_time_compare(&timethen,
17558                                              &zone->refreshkeytime) < 0) {
17559                                 zone->refreshkeytime = timethen;
17560                         }
17561                         UNLOCK_ZONE(zone);
17562                 }
17563 
17564                 zone_settimer(zone, &timenow);
17565 
17566                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
17567                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
17568         }
17569 
17570  done:
17571         dns_diff_clear(&diff);
17572         dns_diff_clear(&_sig_diff);
17573 
17574         clear_keylist(&dnskeys, mctx);
17575         clear_keylist(&keys, mctx);
17576         clear_keylist(&rmkeys, mctx);
17577 
17578         if (ver != NULL)
17579                 dns_db_closeversion(db, &ver, ISC_FALSE);
17580         if (dns_rdataset_isassociated(&keyset))
17581                 dns_rdataset_disassociate(&keyset);
17582         if (dns_rdataset_isassociated(&keysigs))
17583                 dns_rdataset_disassociate(&keysigs);
17584         if (dns_rdataset_isassociated(&soasigs))
17585                 dns_rdataset_disassociate(&soasigs);
17586         if (node != NULL)
17587                 dns_db_detachnode(db, &node);
17588         if (db != NULL)
17589                 dns_db_detach(&db);
17590 
17591         INSIST(ver == NULL);
17592         return;
17593 
17594  failure:
17595         /*
17596          * Something went wrong; try again in ten minutes or
17597          * after a key refresh interval, whichever is shorter.
17598          */
17599         isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
17600         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
17601         goto done;
17602 }
17603 
17604 void
17605 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
17606         isc_time_t now;
17607 
17608         if (zone->type == dns_zone_master && zone->task != NULL) {
17609                 LOCK_ZONE(zone);
17610 
17611                 if (fullsign)
17612                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
17613 
17614                 TIME_NOW(&now);
17615                 zone->refreshkeytime = now;
17616                 zone_settimer(zone, &now);
17617 
17618                 UNLOCK_ZONE(zone);
17619         }
17620 }
17621 
17622 isc_result_t
17623 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17624                  unsigned int *errors)
17625 {
17626         isc_result_t result;
17627         dns_dbnode_t *node = NULL;
17628 
17629         REQUIRE(DNS_ZONE_VALID(zone));
17630         REQUIRE(errors != NULL);
17631 
17632         result = dns_db_getoriginnode(db, &node);
17633         if (result != ISC_R_SUCCESS)
17634                 return (result);
17635         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
17636                                   ISC_FALSE);
17637         dns_db_detachnode(db, &node);
17638         return (result);
17639 }
17640 
17641 void
17642 dns_zone_setautomatic(dns_zone_t *zone, isc_boolean_t automatic) {
17643         REQUIRE(DNS_ZONE_VALID(zone));
17644 
17645         LOCK_ZONE(zone);
17646         zone->automatic = automatic;
17647         UNLOCK_ZONE(zone);
17648 }
17649 
17650 isc_boolean_t
17651 dns_zone_getautomatic(dns_zone_t *zone) {
17652         REQUIRE(DNS_ZONE_VALID(zone));
17653         return (zone->automatic);
17654 }
17655 
17656 void
17657 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
17658         REQUIRE(DNS_ZONE_VALID(zone));
17659 
17660         LOCK_ZONE(zone);
17661         zone->added = added;
17662         UNLOCK_ZONE(zone);
17663 }
17664 
17665 isc_boolean_t
17666 dns_zone_getadded(dns_zone_t *zone) {
17667         REQUIRE(DNS_ZONE_VALID(zone));
17668         return (zone->added);
17669 }
17670 
17671 isc_result_t
17672 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
17673 {
17674         isc_time_t loadtime;
17675         isc_result_t result;
17676         dns_zone_t *secure = NULL;
17677 
17678         TIME_NOW(&loadtime);
17679 
17680         /*
17681          * Lock hierarchy: zmgr, zone, raw.
17682          */
17683  again:
17684         LOCK_ZONE(zone);
17685         INSIST(zone != zone->raw);
17686         if (inline_secure(zone))
17687                 LOCK_ZONE(zone->raw);
17688         else if (inline_raw(zone)) {
17689                 secure = zone->secure;
17690                 TRYLOCK_ZONE(result, secure);
17691                 if (result != ISC_R_SUCCESS) {
17692                         UNLOCK_ZONE(zone);
17693                         secure = NULL;
17694 #if ISC_PLATFORM_USETHREADS
17695                         isc_thread_yield();
17696 #endif
17697                         goto again;
17698                 }
17699         }
17700         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17701         if (inline_secure(zone))
17702                 UNLOCK_ZONE(zone->raw);
17703         else if (secure != NULL)
17704                 UNLOCK_ZONE(secure);
17705         UNLOCK_ZONE(zone);
17706         return result;
17707 }
17708 
17709 isc_result_t
17710 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
17711         REQUIRE(DNS_ZONE_VALID(zone));
17712         if (interval == 0)
17713                 return (ISC_R_RANGE);
17714         /* Maximum value: 24 hours (3600 minutes) */
17715         if (interval > (24 * 60))
17716                 interval = (24 * 60);
17717         /* Multiply by 60 for seconds */
17718         zone->refreshkeyinterval = interval * 60;
17719         return (ISC_R_SUCCESS);
17720 }
17721 
17722 void
17723 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
17724         REQUIRE(DNS_ZONE_VALID(zone));
17725         zone->requestixfr = flag;
17726 }
17727 
17728 isc_boolean_t
17729 dns_zone_getrequestixfr(dns_zone_t *zone) {
17730         REQUIRE(DNS_ZONE_VALID(zone));
17731         return (zone->requestixfr);
17732 }
17733 
17734 void
17735 dns_zone_setrequestexpire(dns_zone_t *zone, isc_boolean_t flag) {
17736         REQUIRE(DNS_ZONE_VALID(zone));
17737         zone->requestexpire = flag;
17738 }
17739 
17740 isc_boolean_t
17741 dns_zone_getrequestexpire(dns_zone_t *zone) {
17742         REQUIRE(DNS_ZONE_VALID(zone));
17743         return (zone->requestexpire);
17744 }
17745 
17746 void
17747 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
17748         REQUIRE(DNS_ZONE_VALID(zone));
17749         zone->updatemethod = method;
17750 }
17751 
17752 dns_updatemethod_t
17753 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
17754         REQUIRE(DNS_ZONE_VALID(zone));
17755         return(zone->updatemethod);
17756 }
17757 
17758 /*
17759  * Lock hierarchy: zmgr, zone, raw.
17760  */
17761 isc_result_t
17762 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
17763         isc_result_t result;
17764         dns_zonemgr_t *zmgr;
17765 
17766         REQUIRE(DNS_ZONE_VALID(zone));
17767         REQUIRE(zone->zmgr != NULL);
17768         REQUIRE(zone->task != NULL);
17769         REQUIRE(zone->loadtask != NULL);
17770         REQUIRE(zone->raw == NULL);
17771 
17772         REQUIRE(DNS_ZONE_VALID(raw));
17773         REQUIRE(raw->zmgr == NULL);
17774         REQUIRE(raw->task == NULL);
17775         REQUIRE(raw->loadtask == NULL);
17776         REQUIRE(raw->secure == NULL);
17777 
17778         REQUIRE(zone != raw);
17779 
17780         /*
17781          * Lock hierarchy: zmgr, zone, raw.
17782          */
17783         zmgr = zone->zmgr;
17784         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17785         LOCK_ZONE(zone);
17786         LOCK_ZONE(raw);
17787 
17788         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
17789                                   NULL, NULL, zone->task, zone_timer, raw,
17790                                   &raw->timer);
17791         if (result != ISC_R_SUCCESS)
17792                 goto unlock;
17793 
17794         /*
17795          * The timer "holds" a iref.
17796          */
17797         raw->irefs++;
17798         INSIST(raw->irefs != 0);
17799 
17800 
17801         /* dns_zone_attach(raw, &zone->raw); */
17802         isc_refcount_increment(&raw->erefs, NULL);
17803         zone->raw = raw;
17804 
17805         /* dns_zone_iattach(zone,  &raw->secure); */
17806         zone_iattach(zone, &raw->secure);
17807 
17808         isc_task_attach(zone->task, &raw->task);
17809         isc_task_attach(zone->loadtask, &raw->loadtask);
17810 
17811         ISC_LIST_APPEND(zmgr->zones, raw, link);
17812         raw->zmgr = zmgr;
17813         zmgr->refs++;
17814 
17815  unlock:
17816         UNLOCK_ZONE(raw);
17817         UNLOCK_ZONE(zone);
17818         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17819         return (result);
17820 }
17821 
17822 void
17823 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
17824         REQUIRE(DNS_ZONE_VALID(zone));
17825         REQUIRE(raw != NULL && *raw == NULL);
17826 
17827         LOCK(&zone->lock);
17828         INSIST(zone != zone->raw);
17829         if (zone->raw != NULL)
17830                 dns_zone_attach(zone->raw, raw);
17831         UNLOCK(&zone->lock);
17832 }
17833 
17834 struct keydone {
17835         isc_event_t event;
17836         isc_boolean_t all;
17837         unsigned char data[5];
17838 };
17839 
17840 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
17841 
17842 static void
17843 keydone(isc_task_t *task, isc_event_t *event) {
17844         const char *me = "keydone";
17845         isc_boolean_t commit = ISC_FALSE;
17846         isc_result_t result;
17847         dns_rdata_t rdata = DNS_RDATA_INIT;
17848         dns_dbversion_t *oldver = NULL, *newver = NULL;
17849         dns_zone_t *zone;
17850         dns_db_t *db = NULL;
17851         dns_dbnode_t *node = NULL;
17852         dns_rdataset_t rdataset;
17853         dns_diff_t diff;
17854         struct keydone *kd = (struct keydone *)event;
17855         dns_update_log_t log = { update_log_cb, NULL };
17856         isc_boolean_t clear_pending = ISC_FALSE;
17857 
17858         UNUSED(task);
17859 
17860         zone = event->ev_arg;
17861         INSIST(DNS_ZONE_VALID(zone));
17862 
17863         ENTER;
17864 
17865         dns_rdataset_init(&rdataset);
17866         dns_diff_init(zone->mctx, &diff);
17867 
17868         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17869         if (zone->db != NULL)
17870                 dns_db_attach(zone->db, &db);
17871         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17872         if (db == NULL)
17873                 goto failure;
17874 
17875         dns_db_currentversion(db, &oldver);
17876         result = dns_db_newversion(db, &newver);
17877         if (result != ISC_R_SUCCESS) {
17878                 dns_zone_log(zone, ISC_LOG_ERROR,
17879                              "keydone:dns_db_newversion -> %s",
17880                              dns_result_totext(result));
17881                 goto failure;
17882         }
17883 
17884         result = dns_db_getoriginnode(db, &node);
17885         if (result != ISC_R_SUCCESS)
17886                 goto failure;
17887 
17888         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17889                                      dns_rdatatype_none, 0, &rdataset, NULL);
17890         if (result == ISC_R_NOTFOUND) {
17891                 INSIST(!dns_rdataset_isassociated(&rdataset));
17892                 goto failure;
17893         }
17894         if (result != ISC_R_SUCCESS) {
17895                 INSIST(!dns_rdataset_isassociated(&rdataset));
17896                 goto failure;
17897         }
17898 
17899         for (result = dns_rdataset_first(&rdataset);
17900              result == ISC_R_SUCCESS;
17901              result = dns_rdataset_next(&rdataset)) {
17902                 isc_boolean_t found = ISC_FALSE;
17903 
17904                 dns_rdataset_current(&rdataset, &rdata);
17905 
17906                 if (kd->all) {
17907                         if (rdata.length == 5 && rdata.data[0] != 0 &&
17908                                rdata.data[3] == 0 && rdata.data[4] == 1)
17909                                 found = ISC_TRUE;
17910                         else if (rdata.data[0] == 0 &&
17911                                  (rdata.data[2] & PENDINGFLAGS) != 0) {
17912                                 found = ISC_TRUE;
17913                                 clear_pending = ISC_TRUE;
17914                         }
17915                 } else if (rdata.length == 5 &&
17916                            memcmp(rdata.data, kd->data, 5) == 0)
17917                         found = ISC_TRUE;
17918 
17919                 if (found)
17920                         CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
17921                                             &zone->origin, rdataset.ttl,
17922                                             &rdata));
17923                 dns_rdata_reset(&rdata);
17924         }
17925 
17926         if (!ISC_LIST_EMPTY(diff.tuples)) {
17927                 /* Write changes to journal file. */
17928                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17929                                         zone->updatemethod));
17930 
17931                 result = dns_update_signatures(&log, zone, db,
17932                                                oldver, newver, &diff,
17933                                                zone->sigvalidityinterval);
17934                 if (!clear_pending)
17935                         CHECK(result);
17936 
17937                 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
17938                 commit = ISC_TRUE;
17939 
17940                 LOCK_ZONE(zone);
17941                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17942                 zone_needdump(zone, 30);
17943                 UNLOCK_ZONE(zone);
17944         }
17945 
17946  failure:
17947         if (dns_rdataset_isassociated(&rdataset))
17948                 dns_rdataset_disassociate(&rdataset);
17949         if (db != NULL) {
17950                 if (node != NULL)
17951                         dns_db_detachnode(db, &node);
17952                 if (oldver != NULL)
17953                         dns_db_closeversion(db, &oldver, ISC_FALSE);
17954                 if (newver != NULL)
17955                         dns_db_closeversion(db, &newver, commit);
17956                 dns_db_detach(&db);
17957         }
17958         dns_diff_clear(&diff);
17959         isc_event_free(&event);
17960         dns_zone_idetach(&zone);
17961 
17962         INSIST(oldver == NULL);
17963         INSIST(newver == NULL);
17964 }
17965 
17966 isc_result_t
17967 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
17968         isc_result_t result = ISC_R_SUCCESS;
17969         isc_event_t *e;
17970         isc_buffer_t b;
17971         dns_zone_t *dummy = NULL;
17972         struct keydone *kd;
17973 
17974         REQUIRE(DNS_ZONE_VALID(zone));
17975 
17976         LOCK_ZONE(zone);
17977 
17978         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
17979                                zone, sizeof(struct keydone));
17980         if (e == NULL) {
17981                 result = ISC_R_NOMEMORY;
17982                 goto failure;
17983         }
17984 
17985         kd = (struct keydone *) e;
17986         if (strcasecmp(keystr, "all") == 0)
17987                 kd->all = ISC_TRUE;
17988         else {
17989                 isc_textregion_t r;
17990                 char *algstr;
17991                 dns_keytag_t keyid;
17992                 dns_secalg_t alg;
17993                 size_t n;
17994 
17995                 kd->all = ISC_FALSE;
17996 
17997                 n = sscanf(keystr, "%hd/", &keyid);
17998                 if (n == 0U)
17999                         CHECK(ISC_R_FAILURE);
18000 
18001                 algstr = strchr(keystr, '/');
18002                 if (algstr != NULL)
18003                         algstr++;
18004                 else
18005                         CHECK(ISC_R_FAILURE);
18006 
18007                 n = sscanf(algstr, "%hhd", &alg);
18008                 if (n == 0U) {
18009                         DE_CONST(algstr, r.base);
18010                         r.length = strlen(algstr);
18011                         CHECK(dns_secalg_fromtext(&alg, &r));
18012                 }
18013 
18014                 /* construct a private-type rdata */
18015                 isc_buffer_init(&b, kd->data, sizeof(kd->data));
18016                 isc_buffer_putuint8(&b, alg);
18017                 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
18018                 isc_buffer_putuint8(&b, (keyid & 0xff));
18019                 isc_buffer_putuint8(&b, 0);
18020                 isc_buffer_putuint8(&b, 1);
18021         }
18022 
18023         zone_iattach(zone, &dummy);
18024         isc_task_send(zone->task, &e);
18025 
18026  failure:
18027         if (e != NULL)
18028                 isc_event_free(&e);
18029         UNLOCK_ZONE(zone);
18030         return (result);
18031 }
18032 
18033 static void
18034 setnsec3param(isc_task_t *task, isc_event_t *event) {
18035         const char *me = "setnsec3param";
18036         isc_boolean_t commit = ISC_FALSE;
18037         isc_result_t result;
18038         dns_dbversion_t *oldver = NULL, *newver = NULL;
18039         dns_zone_t *zone;
18040         dns_db_t *db = NULL;
18041         dns_dbnode_t *node = NULL;
18042         dns_rdataset_t prdataset, nrdataset;
18043         dns_diff_t diff;
18044         struct np3event *npe = (struct np3event *)event;
18045         nsec3param_t *np;
18046         dns_update_log_t log = { update_log_cb, NULL };
18047         dns_rdata_t rdata;
18048         isc_boolean_t nseconly;
18049         isc_boolean_t exists = ISC_FALSE;
18050 
18051         UNUSED(task);
18052 
18053         zone = event->ev_arg;
18054         INSIST(DNS_ZONE_VALID(zone));
18055 
18056         ENTER;
18057 
18058         np = &npe->params;
18059 
18060         dns_rdataset_init(&prdataset);
18061         dns_rdataset_init(&nrdataset);
18062         dns_diff_init(zone->mctx, &diff);
18063 
18064         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18065         if (zone->db != NULL)
18066                 dns_db_attach(zone->db, &db);
18067         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18068         if (db == NULL)
18069                 goto failure;
18070 
18071         dns_db_currentversion(db, &oldver);
18072         result = dns_db_newversion(db, &newver);
18073         if (result != ISC_R_SUCCESS) {
18074                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18075                 dns_zone_log(zone, ISC_LOG_ERROR,
18076                              "setnsec3param:dns_db_newversion -> %s",
18077                              dns_result_totext(result));
18078                 goto failure;
18079         }
18080 
18081         CHECK(dns_db_getoriginnode(db, &node));
18082 
18083         /*
18084          * Does a private-type record already exist for this chain?
18085          */
18086         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
18087                                      dns_rdatatype_none, 0, &prdataset, NULL);
18088         if (result == ISC_R_SUCCESS) {
18089                 for (result = dns_rdataset_first(&prdataset);
18090                      result == ISC_R_SUCCESS;
18091                      result = dns_rdataset_next(&prdataset)) {
18092                         dns_rdata_init(&rdata);
18093                         dns_rdataset_current(&prdataset, &rdata);
18094 
18095                         if (np->length == rdata.length &&
18096                             memcmp(rdata.data, np->data, np->length) == 0) {
18097                                 exists = ISC_TRUE;
18098                                 break;
18099                         }
18100                 }
18101         } else if (result != ISC_R_NOTFOUND) {
18102                 INSIST(!dns_rdataset_isassociated(&prdataset));
18103                 goto failure;
18104         }
18105 
18106         /*
18107          * Does the chain already exist?
18108          */
18109         result = dns_db_findrdataset(db, node, newver,
18110                                      dns_rdatatype_nsec3param,
18111                                      dns_rdatatype_none, 0, &nrdataset, NULL);
18112         if (result == ISC_R_SUCCESS) {
18113                 for (result = dns_rdataset_first(&nrdataset);
18114                      result == ISC_R_SUCCESS;
18115                      result = dns_rdataset_next(&nrdataset)) {
18116                         dns_rdata_init(&rdata);
18117                         dns_rdataset_current(&nrdataset, &rdata);
18118 
18119                         if (np->length == (rdata.length + 1) &&
18120                             memcmp(rdata.data, np->data + 1,
18121                                    np->length - 1) == 0)
18122                         {
18123                                 exists = ISC_TRUE;
18124                                 break;
18125                         }
18126                 }
18127         } else if (result != ISC_R_NOTFOUND) {
18128                 INSIST(!dns_rdataset_isassociated(&nrdataset));
18129                 goto failure;
18130         }
18131 
18132 
18133         /*
18134          * We need to remove any existing NSEC3 chains.
18135          */
18136         if (!exists && np->replace && (np->length != 0 || np->nsec))
18137                 CHECK(dns_nsec3param_deletechains(db, newver, zone,
18138                                                   !np->nsec, &diff));
18139 
18140         if (!exists && np->length != 0) {
18141                 /*
18142                  * We're creating an NSEC3 chain.
18143                  *
18144                  * If the zone is not currently capable of supporting
18145                  * an NSEC3 chain, add the INITIAL flag, so these
18146                  * parameters can be used later when NSEC3 becomes
18147                  * available.
18148                  */
18149                 dns_rdata_init(&rdata);
18150 
18151                 np->data[2] |= DNS_NSEC3FLAG_CREATE;
18152                 result = dns_nsec_nseconly(db, newver, &nseconly);
18153                 if (result == ISC_R_NOTFOUND || nseconly)
18154                         np->data[2] |= DNS_NSEC3FLAG_INITIAL;
18155 
18156                 rdata.length = np->length;
18157                 rdata.data = np->data;
18158                 rdata.type = zone->privatetype;
18159                 rdata.rdclass = zone->rdclass;
18160                 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
18161                                     &zone->origin, 0, &rdata));
18162         }
18163 
18164         if (!ISC_LIST_EMPTY(diff.tuples)) {
18165                 /* Write changes to journal file. */
18166                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
18167                                         zone->updatemethod));
18168                 result = dns_update_signatures(&log, zone, db,
18169                                                oldver, newver, &diff,
18170                                                zone->sigvalidityinterval);
18171                 if (result != ISC_R_NOTFOUND)
18172                         CHECK(result);
18173                 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
18174                 commit = ISC_TRUE;
18175 
18176                 LOCK_ZONE(zone);
18177                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
18178                 zone_needdump(zone, 30);
18179                 UNLOCK_ZONE(zone);
18180         }
18181 
18182  failure:
18183         if (dns_rdataset_isassociated(&prdataset))
18184                 dns_rdataset_disassociate(&prdataset);
18185         if (dns_rdataset_isassociated(&nrdataset))
18186                 dns_rdataset_disassociate(&nrdataset);
18187         if (node != NULL)
18188                 dns_db_detachnode(db, &node);
18189         if (oldver != NULL)
18190                 dns_db_closeversion(db, &oldver, ISC_FALSE);
18191         if (newver != NULL)
18192                 dns_db_closeversion(db, &newver, commit);
18193         if (db != NULL)
18194                 dns_db_detach(&db);
18195         if (commit)
18196                 resume_addnsec3chain(zone);
18197         dns_diff_clear(&diff);
18198         isc_event_free(&event);
18199         dns_zone_idetach(&zone);
18200 
18201         INSIST(oldver == NULL);
18202         INSIST(newver == NULL);
18203 }
18204 
18205 isc_result_t
18206 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
18207                        isc_uint16_t iter, isc_uint8_t saltlen,
18208                        unsigned char *salt, isc_boolean_t replace)
18209 {
18210         isc_result_t result = ISC_R_SUCCESS;
18211         dns_rdata_nsec3param_t param;
18212         dns_rdata_t nrdata = DNS_RDATA_INIT;
18213         dns_rdata_t prdata = DNS_RDATA_INIT;
18214         unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
18215         struct np3event *npe;
18216         nsec3param_t *np;
18217         dns_zone_t *dummy = NULL;
18218         isc_buffer_t b;
18219         isc_event_t *e;
18220 
18221         REQUIRE(DNS_ZONE_VALID(zone));
18222         REQUIRE(salt != NULL);
18223 
18224         LOCK_ZONE(zone);
18225 
18226         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
18227                                setnsec3param, zone, sizeof(struct np3event));
18228         if (e == NULL) {
18229                 result = ISC_R_NOMEMORY;
18230                 goto failure;
18231         }
18232 
18233         npe = (struct np3event *) e;
18234         np = &npe->params;
18235 
18236         np->replace = replace;
18237         if (hash == 0) {
18238                 np->length = 0;
18239                 np->nsec = ISC_TRUE;
18240         } else {
18241                 param.common.rdclass = zone->rdclass;
18242                 param.common.rdtype = dns_rdatatype_nsec3param;
18243                 ISC_LINK_INIT(&param.common, link);
18244                 param.mctx = NULL;
18245                 param.hash = hash;
18246                 param.flags = flags;
18247                 param.iterations = iter;
18248                 param.salt_length = saltlen;
18249                 param.salt = salt;
18250                 isc_buffer_init(&b, nbuf, sizeof(nbuf));
18251                 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
18252                                            dns_rdatatype_nsec3param,
18253                                            &param, &b));
18254                 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
18255                                          np->data, sizeof(np->data));
18256                 np->length = prdata.length;
18257         }
18258 
18259         zone_iattach(zone, &dummy);
18260         isc_task_send(zone->task, &e);
18261 
18262  failure:
18263         if (e != NULL)
18264                 isc_event_free(&e);
18265         UNLOCK_ZONE(zone);
18266         return (result);
18267 }
18268 
18269 isc_result_t
18270 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
18271         REQUIRE(DNS_ZONE_VALID(zone));
18272         REQUIRE(loadtime != NULL);
18273 
18274         LOCK_ZONE(zone);
18275         *loadtime = zone->loadtime;
18276         UNLOCK_ZONE(zone);
18277         return (ISC_R_SUCCESS);
18278 }
18279 
18280 isc_result_t
18281 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
18282         REQUIRE(DNS_ZONE_VALID(zone));
18283         REQUIRE(expiretime != NULL);
18284 
18285         LOCK_ZONE(zone);
18286         *expiretime = zone->expiretime;
18287         UNLOCK_ZONE(zone);
18288         return (ISC_R_SUCCESS);
18289 }
18290 
18291 isc_result_t
18292 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
18293         REQUIRE(DNS_ZONE_VALID(zone));
18294         REQUIRE(refreshtime != NULL);
18295 
18296         LOCK_ZONE(zone);
18297         *refreshtime = zone->refreshtime;
18298         UNLOCK_ZONE(zone);
18299         return (ISC_R_SUCCESS);
18300 }
18301 
18302 isc_result_t
18303 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
18304         REQUIRE(DNS_ZONE_VALID(zone));
18305         REQUIRE(refreshkeytime != NULL);
18306 
18307         LOCK_ZONE(zone);
18308         *refreshkeytime = zone->refreshkeytime;
18309         UNLOCK_ZONE(zone);
18310         return (ISC_R_SUCCESS);
18311 }
18312 
18313 unsigned int
18314 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
18315         dns_include_t *include;
18316         char **array = NULL;
18317         unsigned int n = 0;
18318 
18319         REQUIRE(DNS_ZONE_VALID(zone));
18320         REQUIRE(includesp != NULL && *includesp == NULL);
18321 
18322         LOCK_ZONE(zone);
18323         if (zone->nincludes == 0)
18324                 goto done;
18325 
18326         array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
18327         if (array == NULL)
18328                 goto done;
18329         for (include = ISC_LIST_HEAD(zone->includes);
18330              include != NULL;
18331              include = ISC_LIST_NEXT(include, link)) {
18332                 INSIST(n < zone->nincludes);
18333                 array[n++] = isc_mem_strdup(zone->mctx, include->name);
18334         }
18335         INSIST(n == zone->nincludes);
18336         *includesp = array;
18337 
18338  done:
18339         UNLOCK_ZONE(zone);
18340         return (n);
18341 }
18342 
18343 void
18344 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
18345         REQUIRE(DNS_ZONE_VALID(zone));
18346 
18347         zone->statlevel = level;
18348 }
18349 
18350 dns_zonestat_level_t
18351 dns_zone_getstatlevel(dns_zone_t *zone) {
18352         REQUIRE(DNS_ZONE_VALID(zone));
18353 
18354         return (zone->statlevel);
18355 }
18356 
18357 static void
18358 setserial(isc_task_t *task, isc_event_t *event) {
18359         isc_uint32_t oldserial, desired;
18360         const char *me = "setserial";
18361         isc_boolean_t commit = ISC_FALSE;
18362         isc_result_t result;
18363         dns_dbversion_t *oldver = NULL, *newver = NULL;
18364         dns_zone_t *zone;
18365         dns_db_t *db = NULL;
18366         dns_diff_t diff;
18367         struct ssevent *sse = (struct ssevent *)event;
18368         dns_update_log_t log = { update_log_cb, NULL };
18369         dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
18370 
18371         UNUSED(task);
18372 
18373         zone = event->ev_arg;
18374         INSIST(DNS_ZONE_VALID(zone));
18375 
18376         ENTER;
18377 
18378         if (zone->update_disabled)
18379                 goto failure;
18380 
18381         desired = sse->serial;
18382 
18383         dns_diff_init(zone->mctx, &diff);
18384 
18385         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18386         if (zone->db != NULL)
18387                 dns_db_attach(zone->db, &db);
18388         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18389         if (db == NULL)
18390                 goto failure;
18391 
18392         dns_db_currentversion(db, &oldver);
18393         result = dns_db_newversion(db, &newver);
18394         if (result != ISC_R_SUCCESS) {
18395                 dns_zone_log(zone, ISC_LOG_ERROR,
18396                              "setserial:dns_db_newversion -> %s",
18397                              dns_result_totext(result));
18398                 goto failure;
18399         }
18400 
18401         CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
18402                                     DNS_DIFFOP_DEL, &oldtuple));
18403         CHECK(dns_difftuple_copy(oldtuple, &newtuple));
18404         newtuple->op = DNS_DIFFOP_ADD;
18405 
18406         oldserial = dns_soa_getserial(&oldtuple->rdata);
18407         if (desired == 0U)
18408                 desired = 1;
18409         if (!isc_serial_gt(desired, oldserial)) {
18410                 if (desired != oldserial)
18411                         dns_zone_log(zone, ISC_LOG_INFO,
18412                                      "setserial: desired serial (%u) "
18413                                      "out of range (%u-%u)", desired,
18414                                      oldserial + 1, (oldserial + 0x7fffffff));
18415                 goto failure;
18416         }
18417 
18418         dns_soa_setserial(desired, &newtuple->rdata);
18419         CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
18420         CHECK(do_one_tuple(&newtuple, db, newver, &diff));
18421         result = dns_update_signatures(&log, zone, db,
18422                                        oldver, newver, &diff,
18423                                        zone->sigvalidityinterval);
18424         if (result != ISC_R_NOTFOUND)
18425                 CHECK(result);
18426 
18427         /* Write changes to journal file. */
18428         CHECK(zone_journal(zone, &diff, NULL, "setserial"));
18429         commit = ISC_TRUE;
18430 
18431         LOCK_ZONE(zone);
18432         zone_needdump(zone, 30);
18433         UNLOCK_ZONE(zone);
18434 
18435  failure:
18436         if (oldtuple != NULL)
18437                 dns_difftuple_free(&oldtuple);
18438         if (newtuple != NULL)
18439                 dns_difftuple_free(&newtuple);
18440         if (oldver != NULL)
18441                 dns_db_closeversion(db, &oldver, ISC_FALSE);
18442         if (newver != NULL)
18443                 dns_db_closeversion(db, &newver, commit);
18444         if (db != NULL)
18445                 dns_db_detach(&db);
18446         dns_diff_clear(&diff);
18447         isc_event_free(&event);
18448         dns_zone_idetach(&zone);
18449 
18450         INSIST(oldver == NULL);
18451         INSIST(newver == NULL);
18452 }
18453 
18454 isc_result_t
18455 dns_zone_setserial(dns_zone_t *zone, isc_uint32_t serial) {
18456         isc_result_t result = ISC_R_SUCCESS;
18457         dns_zone_t *dummy = NULL;
18458         isc_event_t *e = NULL;
18459         struct ssevent *sse;
18460 
18461         REQUIRE(DNS_ZONE_VALID(zone));
18462 
18463         LOCK_ZONE(zone);
18464 
18465         if (!inline_secure(zone)) {
18466                 if (!dns_zone_isdynamic(zone, ISC_TRUE)) {
18467                         result = DNS_R_NOTDYNAMIC;
18468                         goto failure;
18469                 }
18470         }
18471 
18472         if (zone->update_disabled) {
18473                 result = DNS_R_FROZEN;
18474                 goto failure;
18475         }
18476 
18477         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
18478                                setserial, zone, sizeof(struct ssevent));
18479         if (e == NULL) {
18480                 result = ISC_R_NOMEMORY;
18481                 goto failure;
18482         }
18483 
18484         sse = (struct ssevent *)e;
18485         sse->serial = serial;
18486 
18487         zone_iattach(zone, &dummy);
18488         isc_task_send(zone->task, &e);
18489 
18490  failure:
18491         if (e != NULL)
18492                 isc_event_free(&e);
18493         UNLOCK_ZONE(zone);
18494         return (result);
18495 }

Generated on Tue Apr 28 17:41:03 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha