1 /* $NetBSD: catz.h,v 1.9 2025/01/26 16:25:26 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 dns_catz_entry_t * 135 dns_catz_entry_new(isc_mem_t *mctx, const dns_name_t *domain); 136 /*%< 137 * Allocate a new catz_entry on 'mctx', with the name 'domain' 138 * 139 * Requires: 140 * \li 'mctx' to be a valid memory context. 141 * \li 'domain' to be valid dns_name or NULL. 142 * 143 * Returns: 144 * \li ISC_R_SUCCESS on success 145 * \li ISC_R_NOMEMORY on allocation failure 146 */ 147 148 dns_catz_entry_t * 149 dns_catz_entry_copy(dns_catz_zone_t *catz, const dns_catz_entry_t *entry); 150 /*%< 151 * Allocate a new catz_entry and deep copy 'entry' into 'nentryp'. 152 * 153 * Requires: 154 * \li 'mctx' to be a valid memory context. 155 * \li 'entry' to be non NULL. 156 * 157 * Returns: 158 * \li ISC_R_SUCCESS on success 159 * \li ISC_R_NOMEMORY on allocation failure 160 */ 161 162 void 163 dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp); 164 /*%< 165 * Attach an entry 166 * 167 * Requires: 168 * \li 'entry' is a valid dns_catz_entry_t. 169 * \li 'entryp' is not NULL and '*entryp' is NULL. 170 */ 171 172 void 173 dns_catz_entry_detach(dns_catz_zone_t *catz, dns_catz_entry_t **entryp); 174 /*%< 175 * Detach an entry, free if no further references 176 * 177 * Requires: 178 * \li 'catz' is a valid dns_catz_zone_t. 179 * \li 'entryp' is not NULL and '*entryp' is not NULL. 180 */ 181 182 bool 183 dns_catz_entry_validate(const dns_catz_entry_t *entry); 184 /*%< 185 * Validate whether entry is correct. 186 * (NOT YET IMPLEMENTED: always returns true) 187 * 188 * Requires: 189 *\li 'entry' is a valid dns_catz_entry_t. 190 */ 191 192 bool 193 dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb); 194 /*%< 195 * Deep compare two entries 196 * 197 * Requires: 198 * \li 'ea' is a valid dns_catz_entry_t. 199 * \li 'eb' is a valid dns_catz_entry_t. 200 * 201 * Returns: 202 * \li 'true' if entries are the same. 203 * \li 'false' if the entries differ. 204 */ 205 206 dns_catz_zone_t * 207 dns_catz_zone_new(dns_catz_zones_t *catzs, const dns_name_t *name); 208 /*%< 209 * Allocate a new catz zone on catzs mctx 210 * 211 * Requires: 212 * \li 'catzs' is a valid dns_catz_zones_t. 213 * \li 'catzp' is not NULL and '*catzp' is NULL. 214 * \li 'name' is a valid dns_name_t. 215 * 216 */ 217 218 dns_name_t * 219 dns_catz_zone_getname(dns_catz_zone_t *catz); 220 /*%< 221 * Get catalog zone name 222 * 223 * Requires: 224 * \li 'catz' is a valid dns_catz_zone_t. 225 */ 226 227 dns_catz_options_t * 228 dns_catz_zone_getdefoptions(dns_catz_zone_t *catz); 229 /*%< 230 * Get default member zone options for catalog zone 'catz' 231 * 232 * Requires: 233 * \li 'catz' is a valid dns_catz_zone_t. 234 */ 235 236 void 237 dns_catz_zone_resetdefoptions(dns_catz_zone_t *catz); 238 /*%< 239 * Reset the default member zone options for catalog zone 'catz' to 240 * the default values. 241 * 242 * Requires: 243 * \li 'catz' is a valid dns_catz_zone_t. 244 */ 245 246 isc_result_t 247 dns_catz_generate_masterfilename(dns_catz_zone_t *catz, dns_catz_entry_t *entry, 248 isc_buffer_t **buffer); 249 /*%< 250 * Generate master file name and put it into *buffer (might be reallocated). 251 * The general format of the file name is: 252 * __catz__catalog.zone.name__member_zone_name.db 253 * But if it's too long it's shortened to: 254 * __catz__unique_hash_generated_from_the_above.db 255 * 256 * Requires: 257 * \li 'catz' is a valid dns_catz_zone_t. 258 * \li 'entry' is a valid dns_catz_entry_t. 259 * \li 'buffer' is not NULL and '*buffer' is not NULL. 260 */ 261 262 isc_result_t 263 dns_catz_generate_zonecfg(dns_catz_zone_t *catz, dns_catz_entry_t *entry, 264 isc_buffer_t **buf); 265 /*%< 266 * Generate a zone config entry (in text form) from dns_catz_entry and puts 267 * it into *buf. buf might be reallocated. 268 * 269 * Requires: 270 * \li 'catz' is a valid dns_catz_zone_t. 271 * \li 'entry' is a valid dns_catz_entry_t. 272 * \li 'buf' is not NULL and '*buf' is NULL. 273 * 274 */ 275 276 /* Methods provided by named to dynamically modify the member zones */ 277 /* xxxwpk TODO config! */ 278 typedef isc_result_t (*dns_catz_zoneop_fn_t)(dns_catz_entry_t *entry, 279 dns_catz_zone_t *origin, 280 dns_view_t *view, void *udata); 281 struct dns_catz_zonemodmethods { 282 dns_catz_zoneop_fn_t addzone; 283 dns_catz_zoneop_fn_t modzone; 284 dns_catz_zoneop_fn_t delzone; 285 void *udata; 286 }; 287 288 dns_catz_zones_t * 289 dns_catz_zones_new(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, 290 dns_catz_zonemodmethods_t *zmm); 291 /*%< 292 * Allocate a new catz_zones object, a collection storing all catalog zones 293 * for a view. 294 * 295 * Requires: 296 * \li 'mctx' is not NULL. 297 * \li 'loopmgr' is not NULL. 298 * \li 'catzsp' is not NULL and '*catzsp' is NULL. 299 * \li 'zmm' is not NULL. 300 * 301 */ 302 303 void * 304 dns_catz_zones_get_udata(dns_catz_zones_t *catzs); 305 /*%< 306 * Get the 'udata' member of the zone methods which was set when creating catzs. 307 * 308 * Requires: 309 * \li 'catzs' is a valid dns_catz_zones_t. 310 */ 311 312 isc_result_t 313 dns_catz_zone_add(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_zone_get(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 action immediately. 352 * If there was an update recently it schedules update 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_register(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_unregister(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_zones_shutdown(dns_catz_zones_t *catzs); 403 /*%< 404 * Shut down the catalog zones. 405 * 406 * Requires: 407 * \li 'catzs' is a valid dns_catz_zones_t. 408 * 409 */ 410 411 typedef void (*dns_catz_entry_cb2)(dns_catz_entry_t *entry, void *arg1, 412 void *arg2); 413 414 void 415 dns_catz_zone_for_each_entry2(dns_catz_zone_t *catz, dns_catz_entry_cb2 cb, 416 void *arg1, void *arg2); 417 /*%< 418 * Iterate on the catalog zone members, call 'cb' on each 'entry'. 419 * 420 * Requires: 421 * \li 'catz' is a valid dns_catz_zones_t. 422 * 423 */ 424 425 #ifdef DNS_CATZ_TRACE 426 /* Compatibility macros */ 427 #define dns_catz_zone_attach(catz, catzp) \ 428 dns_catz_zone__attach(catz, catzp, __func__, __FILE__, __LINE__) 429 #define dns_catz_zone_detach(catzp) \ 430 dns_catz_zone__detach(catzp, __func__, __FILE__, __LINE__) 431 #define dns_catz_zone_ref(ptr) \ 432 dns_catz_zone__ref(ptr, __func__, __FILE__, __LINE__) 433 #define dns_catz_zone_unref(ptr) \ 434 dns_catz_zone__unref(ptr, __func__, __FILE__, __LINE__) 435 436 #define dns_catz_zones_attach(catzs, catzsp) \ 437 dns_catz_zones__attach(catzs, catzsp, __func__, __FILE__, __LINE__) 438 #define dns_catz_zones_detach(catzsp) \ 439 dns_catz_zones__detach(catzsp, __func__, __FILE__, __LINE__) 440 #define dns_catz_zones_ref(ptr) \ 441 dns_catz_zones__ref(ptr, __func__, __FILE__, __LINE__) 442 #define dns_catz_zones_unref(ptr) \ 443 dns_catz_zones__unref(ptr, __func__, __FILE__, __LINE__) 444 445 ISC_REFCOUNT_TRACE_DECL(dns_catz_zone); 446 ISC_REFCOUNT_TRACE_DECL(dns_catz_zones); 447 #else 448 ISC_REFCOUNT_DECL(dns_catz_zone); 449 ISC_REFCOUNT_DECL(dns_catz_zones); 450 #endif /* DNS_CATZ_TRACE */ 451 452 ISC_LANG_ENDDECLS 453