Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: catz.h,v 1.10 2026/01/29 18:37:50 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_prereconfig(dns_catz_zone_t *catz);
    416 /*%<
    417  * Must be called before reconfiguring a catalog zone. Locks the catalog zone.
    418  *
    419  * Requires:
    420  * \li	'catz' is a valid, unlocked dns_catz_zone_t.
    421  */
    422 
    423 void
    424 dns_catz_zone_postreconfig(dns_catz_zone_t *catz);
    425 /*%<
    426  * Must be called after reconfiguring a catalog zone. Unlocks the catalog zone.
    427  *
    428  * Requires:
    429  * \li	'catz' is a valid, locked dns_catz_zone_t.
    430  */
    431 
    432 void
    433 dns_catz_zone_for_each_entry2(dns_catz_zone_t *catz, dns_catz_entry_cb2 cb,
    434 			      void *arg1, void *arg2);
    435 /*%<
    436  * Iterate on the catalog zone members, call 'cb' on each 'entry'.
    437  *
    438  * Requires:
    439  * \li	'catz' is a valid dns_catz_zones_t.
    440  *
    441  */
    442 
    443 #ifdef DNS_CATZ_TRACE
    444 /* Compatibility macros */
    445 #define dns_catz_zone_attach(catz, catzp) \
    446 	dns_catz_zone__attach(catz, catzp, __func__, __FILE__, __LINE__)
    447 #define dns_catz_zone_detach(catzp) \
    448 	dns_catz_zone__detach(catzp, __func__, __FILE__, __LINE__)
    449 #define dns_catz_zone_ref(ptr) \
    450 	dns_catz_zone__ref(ptr, __func__, __FILE__, __LINE__)
    451 #define dns_catz_zone_unref(ptr) \
    452 	dns_catz_zone__unref(ptr, __func__, __FILE__, __LINE__)
    453 
    454 #define dns_catz_zones_attach(catzs, catzsp) \
    455 	dns_catz_zones__attach(catzs, catzsp, __func__, __FILE__, __LINE__)
    456 #define dns_catz_zones_detach(catzsp) \
    457 	dns_catz_zones__detach(catzsp, __func__, __FILE__, __LINE__)
    458 #define dns_catz_zones_ref(ptr) \
    459 	dns_catz_zones__ref(ptr, __func__, __FILE__, __LINE__)
    460 #define dns_catz_zones_unref(ptr) \
    461 	dns_catz_zones__unref(ptr, __func__, __FILE__, __LINE__)
    462 
    463 ISC_REFCOUNT_TRACE_DECL(dns_catz_zone);
    464 ISC_REFCOUNT_TRACE_DECL(dns_catz_zones);
    465 #else
    466 ISC_REFCOUNT_DECL(dns_catz_zone);
    467 ISC_REFCOUNT_DECL(dns_catz_zones);
    468 #endif /* DNS_CATZ_TRACE */
    469 
    470 ISC_LANG_ENDDECLS
    471