1 /* $NetBSD: catz.h,v 1.7 2024/02/21 22:52:09 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 /* Add -DDNS_CATZ_TRACE=1 to CFLAGS for detailed reference tracing */ 19 20 #include <inttypes.h> 21 #include <stdbool.h> 22 23 #include <isc/ht.h> 24 #include <isc/lang.h> 25 #include <isc/refcount.h> 26 #include <isc/rwlock.h> 27 #include <isc/time.h> 28 #include <isc/timer.h> 29 30 #include <dns/db.h> 31 #include <dns/fixedname.h> 32 #include <dns/ipkeylist.h> 33 #include <dns/rdata.h> 34 #include <dns/types.h> 35 36 ISC_LANG_BEGINDECLS 37 38 #define DNS_CATZ_ERROR_LEVEL ISC_LOG_WARNING 39 #define DNS_CATZ_INFO_LEVEL ISC_LOG_INFO 40 #define DNS_CATZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1) 41 #define DNS_CATZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2) 42 #define DNS_CATZ_DEBUG_LEVEL3 ISC_LOG_DEBUG(3) 43 #define DNS_CATZ_DEBUG_QUIET (DNS_CATZ_DEBUG_LEVEL3 + 1) 44 45 /* 46 * Catalog Zones functions and structures. 47 */ 48 49 /* 50 * Options for a member zone in a catalog 51 */ 52 struct dns_catz_entry_options { 53 /* 54 * Options that can be overridden in catalog zone 55 */ 56 /* default-masters/default-primaries definition */ 57 dns_ipkeylist_t masters; 58 59 /* both as text in config format, NULL if none */ 60 isc_buffer_t *allow_query; 61 isc_buffer_t *allow_transfer; 62 63 /* 64 * Options that are only set in named.conf 65 */ 66 /* zone-directory definition */ 67 char *zonedir; 68 69 /* zone should not be stored on disk (no 'file' statement in def */ 70 bool in_memory; 71 /* 72 * Minimal interval between catalog zone updates, if a new version 73 * of catalog zone is received before this time the update will be 74 * postponed. This is a global option for the whole catalog zone. 75 */ 76 uint32_t min_update_interval; 77 }; 78 79 void 80 dns_catz_options_init(dns_catz_options_t *options); 81 /*%< 82 * Initialize 'options' to NULL values. 83 * 84 * Requires: 85 * \li 'options' to be non NULL. 86 */ 87 88 void 89 dns_catz_options_free(dns_catz_options_t *options, isc_mem_t *mctx); 90 /*%< 91 * Free 'options' contents into 'mctx'. ('options' itself is not freed.) 92 * 93 * Requires: 94 * \li 'options' to be non NULL. 95 * \li 'mctx' to be a valid memory context. 96 */ 97 98 void 99 dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *opts, 100 dns_catz_options_t *nopts); 101 /*%< 102 * Duplicate 'opts' into 'nopts', allocating space from 'mctx'. 103 * 104 * Requires: 105 * \li 'mctx' to be a valid memory context. 106 * \li 'options' to be non NULL and valid options. 107 * \li 'nopts' to be non NULL. 108 */ 109 110 void 111 dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults, 112 dns_catz_options_t *opts); 113 /*%< 114 * Replace empty values in 'opts' with values from 'defaults' 115 * 116 * Requires: 117 * \li 'mctx' to be a valid memory context. 118 * \li 'defaults' to be non NULL and valid options. 119 * \li 'opts' to be non NULL. 120 */ 121 122 dns_name_t * 123 dns_catz_entry_getname(dns_catz_entry_t *entry); 124 /*%< 125 * Get domain name for 'entry' 126 * 127 * Requires: 128 * \li 'entry' to be non NULL. 129 * 130 * Returns: 131 * \li domain name for entry. 132 */ 133 134 void 135 dns_catz_entry_new(isc_mem_t *mctx, const dns_name_t *domain, 136 dns_catz_entry_t **nentryp); 137 /*%< 138 * Allocate a new catz_entry on 'mctx', with the name 'domain' 139 * 140 * Requires: 141 * \li 'mctx' to be a valid memory context. 142 * \li 'domain' to be valid dns_name or NULL. 143 * \li 'nentryp' to be non NULL, *nentryp to be NULL. 144 * 145 * Returns: 146 * \li ISC_R_SUCCESS on success 147 * \li ISC_R_NOMEMORY on allocation failure 148 */ 149 150 void 151 dns_catz_entry_copy(dns_catz_zone_t *catz, const dns_catz_entry_t *entry, 152 dns_catz_entry_t **nentryp); 153 /*%< 154 * Allocate a new catz_entry and deep copy 'entry' into 'nentryp'. 155 * 156 * Requires: 157 * \li 'mctx' to be a valid memory context. 158 * \li 'entry' to be non NULL. 159 * \li 'nentryp' to be non NULL, *nentryp to be NULL. 160 * 161 * Returns: 162 * \li ISC_R_SUCCESS on success 163 * \li ISC_R_NOMEMORY on allocation failure 164 */ 165 166 void 167 dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp); 168 /*%< 169 * Attach an entry 170 * 171 * Requires: 172 * \li 'entry' is a valid dns_catz_entry_t. 173 * \li 'entryp' is not NULL and '*entryp' is NULL. 174 */ 175 176 void 177 dns_catz_entry_detach(dns_catz_zone_t *catz, dns_catz_entry_t **entryp); 178 /*%< 179 * Detach an entry, free if no further references 180 * 181 * Requires: 182 * \li 'catz' is a valid dns_catz_zone_t. 183 * \li 'entryp' is not NULL and '*entryp' is not NULL. 184 */ 185 186 bool 187 dns_catz_entry_validate(const dns_catz_entry_t *entry); 188 /*%< 189 * Validate whether entry is correct. 190 * (NOT YET IMPLEMENTED: always returns true) 191 * 192 * Requires: 193 *\li 'entry' is a valid dns_catz_entry_t. 194 */ 195 196 bool 197 dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb); 198 /*%< 199 * Deep compare two entries 200 * 201 * Requires: 202 * \li 'ea' is a valid dns_catz_entry_t. 203 * \li 'eb' is a valid dns_catz_entry_t. 204 * 205 * Returns: 206 * \li 'true' if entries are the same. 207 * \li 'false' if the entries differ. 208 */ 209 210 isc_result_t 211 dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **catzp, 212 const dns_name_t *name); 213 /*%< 214 * Allocate a new catz zone on catzs mctx 215 * 216 * Requires: 217 * \li 'catzs' is a valid dns_catz_zones_t. 218 * \li 'catzp' is not NULL and '*zonep' is NULL. 219 * \li 'name' is a valid dns_name_t. 220 * 221 */ 222 223 dns_name_t * 224 dns_catz_zone_getname(dns_catz_zone_t *catz); 225 /*%< 226 * Get catalog zone name 227 * 228 * Requires: 229 * \li 'catz' is a valid dns_catz_zone_t. 230 */ 231 232 dns_catz_options_t * 233 dns_catz_zone_getdefoptions(dns_catz_zone_t *catz); 234 /*%< 235 * Get default member zone options for catalog zone 'catz' 236 * 237 * Requires: 238 * \li 'catz' is a valid dns_catz_zone_t. 239 */ 240 241 void 242 dns_catz_zone_resetdefoptions(dns_catz_zone_t *catz); 243 /*%< 244 * Reset the default member zone options for catalog zone 'catz' to 245 * the default values. 246 * 247 * Requires: 248 * \li 'catz' is a valid dns_catz_zone_t. 249 */ 250 251 isc_result_t 252 dns_catz_generate_masterfilename(dns_catz_zone_t *catz, dns_catz_entry_t *entry, 253 isc_buffer_t **buffer); 254 /*%< 255 * Generate master file name and put it into *buffer (might be reallocated). 256 * The general format of the file name is: 257 * __catz__catalog.zone.name__member_zone_name.db 258 * But if it's too long it's shortened to: 259 * __catz__unique_hash_generated_from_the_above.db 260 * 261 * Requires: 262 * \li 'catz' is a valid dns_catz_zone_t. 263 * \li 'entry' is a valid dns_catz_entry_t. 264 * \li 'buffer' is not NULL and '*buffer' is not NULL. 265 */ 266 267 isc_result_t 268 dns_catz_generate_zonecfg(dns_catz_zone_t *catz, dns_catz_entry_t *entry, 269 isc_buffer_t **buf); 270 /*%< 271 * Generate a zone config entry (in text form) from dns_catz_entry and puts 272 * it into *buf. buf might be reallocated. 273 * 274 * Requires: 275 * \li 'catz' is a valid dns_catz_zone_t. 276 * \li 'entry' is a valid dns_catz_entry_t. 277 * \li 'buf' is not NULL and '*buf' is NULL. 278 * 279 */ 280 281 /* Methods provided by named to dynamically modify the member zones */ 282 /* xxxwpk TODO config! */ 283 typedef isc_result_t (*dns_catz_zoneop_fn_t)(dns_catz_entry_t *entry, 284 dns_catz_zone_t *origin, 285 dns_view_t *view, 286 isc_taskmgr_t *taskmgr, 287 void *udata); 288 struct dns_catz_zonemodmethods { 289 dns_catz_zoneop_fn_t addzone; 290 dns_catz_zoneop_fn_t modzone; 291 dns_catz_zoneop_fn_t delzone; 292 void *udata; 293 }; 294 295 isc_result_t 296 dns_catz_new_zones(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, 297 isc_timermgr_t *timermgr, dns_catz_zones_t **catzsp, 298 dns_catz_zonemodmethods_t *zmm); 299 /*%< 300 * Allocate a new catz_zones object, a collection storing all catalog zones 301 * for a view. 302 * 303 * Requires: 304 * \li 'mctx' is not NULL. 305 * \li 'taskmgr' is not NULL. 306 * \li 'timermgr' is not NULL. 307 * \li 'catzsp' is not NULL and '*catzsp' is NULL. 308 * \li 'zmm' is not NULL. 309 * 310 */ 311 312 isc_result_t 313 dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name, 314 dns_catz_zone_t **catzp); 315 /*%< 316 * Allocate a new catz named 'name' and put it in 'catzs' collection. This 317 * function is safe to call only during a (re)configuration. 318 * 319 * Requires: 320 * \li 'catzs' is a valid dns_catz_zones_t. 321 * \li 'name' is a valid dns_name_t. 322 * \li 'catzp' is not NULL and *catzp is NULL. 323 * 324 */ 325 326 dns_catz_zone_t * 327 dns_catz_get_zone(dns_catz_zones_t *catzs, const dns_name_t *name); 328 /*%< 329 * Returns a zone named 'name' from collection 'catzs' 330 * 331 * Requires: 332 * \li 'catzs' is a valid dns_catz_zones_t. 333 * \li 'name' is a valid dns_name_t. 334 */ 335 336 void 337 dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view); 338 /*%< 339 * Set a view for 'catzs'. 340 * 341 * Requires: 342 * \li 'catzs' is a valid dns_catz_zones_t. 343 * \li 'catzs->view' is NULL or 'catzs->view' == 'view'. 344 */ 345 346 isc_result_t 347 dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg); 348 /*%< 349 * Callback for update of catalog zone database. 350 * If there was no catalog zone update recently it launches an 351 * update_taskaction immediately. 352 * If there was an update recently it schedules update_taskaction for some time 353 * in the future. 354 * If there is an update scheduled it replaces old db version with a new one. 355 * 356 * Requires: 357 * \li 'db' is a valid database. 358 * \li 'fn_arg' is not NULL (casted to dns_catz_zones_t*). 359 */ 360 361 void 362 dns_catz_dbupdate_unregister(dns_db_t *db, dns_catz_zones_t *catzs); 363 /*%< 364 * Register the catalog zone database update notify callback. 365 * 366 * Requires: 367 * \li 'db' is a valid database. 368 * \li 'catzs' is valid. 369 */ 370 371 void 372 dns_catz_dbupdate_register(dns_db_t *db, dns_catz_zones_t *catzs); 373 /*%< 374 * Unregister the catalog zone database update notify callback. 375 * 376 * Requires: 377 * \li 'db' is a valid database. 378 * \li 'catzs' is valid. 379 */ 380 381 void 382 dns_catz_prereconfig(dns_catz_zones_t *catzs); 383 /*%< 384 * Called before reconfig, clears 'active' flag on all the zones in set 385 * 386 * Requires: 387 * \li 'catzs' is a valid dns_catz_zones_t. 388 * 389 */ 390 391 void 392 dns_catz_postreconfig(dns_catz_zones_t *catzs); 393 /*%< 394 * Called after reconfig, walks through all zones in set, removes those 395 * inactive and force reload of those with changed configuration. 396 * 397 * Requires: 398 * \li 'catzs' is a valid dns_catz_zones_t. 399 */ 400 401 void 402 dns_catz_get_iterator(dns_catz_zone_t *catz, isc_ht_iter_t **itp); 403 /*%< 404 * Get the hashtable iterator on catalog zone members, point '*itp' to it. 405 * 406 * Requires: 407 * \li 'catzs' is a valid dns_catz_zones_t. 408 * \li 'itp' is not NULL and '*itp' is NULL. 409 * 410 */ 411 412 void 413 dns_catz_shutdown_catzs(dns_catz_zones_t *catzs); 414 /*%< 415 * Shut down the catalog zones. 416 * 417 * Requires: 418 * \li 'catzs' is a valid dns_catz_zones_t. 419 * 420 */ 421 422 #ifdef DNS_CATZ_TRACE 423 /* Compatibility macros */ 424 #define dns_catz_attach_catz(catz, catzp) \ 425 dns_catz_zone__attach(catz, catzp, __func__, __FILE__, __LINE__) 426 #define dns_catz_detach_catz(catzp) \ 427 dns_catz_zone__detach(catzp, __func__, __FILE__, __LINE__) 428 #define dns_catz_ref_catz(ptr) \ 429 dns_catz_zone__ref(ptr, __func__, __FILE__, __LINE__) 430 #define dns_catz_unref_catz(ptr) \ 431 dns_catz_zone__unref(ptr, __func__, __FILE__, __LINE__) 432 433 #define dns_catz_attach_catzs(catzs, catzsp) \ 434 dns_catz_zones__attach(catzs, catzsp, __func__, __FILE__, __LINE__) 435 #define dns_catz_detach_catzs(catzsp) \ 436 dns_catz_zones__detach(catzsp, __func__, __FILE__, __LINE__) 437 #define dns_catz_ref_catzs(ptr) \ 438 dns_catz_zones__ref(ptr, __func__, __FILE__, __LINE__) 439 #define dns_catz_unref_catzs(ptr) \ 440 dns_catz_zones__unref(ptr, __func__, __FILE__, __LINE__) 441 442 ISC_REFCOUNT_TRACE_DECL(dns_catz_zone); 443 ISC_REFCOUNT_TRACE_DECL(dns_catz_zones); 444 #else 445 /* Compatibility macros */ 446 #define dns_catz_attach_catz(catz, catzp) dns_catz_zone_attach(catz, catzp) 447 #define dns_catz_detach_catz(catzp) dns_catz_zone_detach(catzp) 448 #define dns_catz_ref_catz(ptr) dns_catz_zone_ref(ptr) 449 #define dns_catz_unref_catz(ptr) dns_catz_zone_unref(ptr) 450 451 #define dns_catz_attach_catzs(catzs, catzsp) \ 452 dns_catz_zones_attach(catzs, catzsp) 453 #define dns_catz_detach_catzs(catzsp) dns_catz_zones_detach(catzsp) 454 #define dns_catz_ref_catzs(ptr) dns_catz_zones_ref(ptr) 455 #define dns_catz_unref_catzs(ptr) dns_catz_zones_unref(ptr) 456 457 ISC_REFCOUNT_DECL(dns_catz_zone); 458 ISC_REFCOUNT_DECL(dns_catz_zones); 459 #endif /* DNS_CATZ_TRACE */ 460 461 ISC_LANG_ENDDECLS 462