Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: db_p.h,v 1.3 2025/05/21 14:48:02 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 #include <isc/heap.h>
     19 #include <isc/lang.h>
     20 #include <isc/urcu.h>
     21 
     22 #include <dns/nsec3.h>
     23 #include <dns/rbt.h>
     24 #include <dns/types.h>
     25 
     26 #define RDATATYPE_NCACHEANY DNS_TYPEPAIR_VALUE(0, dns_rdatatype_any)
     27 
     28 #ifdef STRONG_RWLOCK_CHECK
     29 #define STRONG_RWLOCK_CHECK(cond) REQUIRE(cond)
     30 #else
     31 #define STRONG_RWLOCK_CHECK(cond)
     32 #endif
     33 
     34 #define NODE_INITLOCK(l)    isc_rwlock_init((l))
     35 #define NODE_DESTROYLOCK(l) isc_rwlock_destroy(l)
     36 #define NODE_LOCK(l, t, tp)                                      \
     37 	{                                                        \
     38 		STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
     39 		RWLOCK((l), (t));                                \
     40 		*tp = t;                                         \
     41 	}
     42 #define NODE_UNLOCK(l, tp)                                       \
     43 	{                                                        \
     44 		STRONG_RWLOCK_CHECK(*tp != isc_rwlocktype_none); \
     45 		RWUNLOCK(l, *tp);                                \
     46 		*tp = isc_rwlocktype_none;                       \
     47 	}
     48 #define NODE_RDLOCK(l, tp) NODE_LOCK(l, isc_rwlocktype_read, tp);
     49 #define NODE_WRLOCK(l, tp) NODE_LOCK(l, isc_rwlocktype_write, tp);
     50 #define NODE_TRYLOCK(l, t, tp)                                   \
     51 	({                                                       \
     52 		STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
     53 		isc_result_t _result = isc_rwlock_trylock(l, t); \
     54 		if (_result == ISC_R_SUCCESS) {                  \
     55 			*tp = t;                                 \
     56 		};                                               \
     57 		_result;                                         \
     58 	})
     59 #define NODE_TRYRDLOCK(l, tp) NODE_TRYLOCK(l, isc_rwlocktype_read, tp)
     60 #define NODE_TRYWRLOCK(l, tp) NODE_TRYLOCK(l, isc_rwlocktype_write, tp)
     61 #define NODE_TRYUPGRADE(l, tp)                                   \
     62 	({                                                       \
     63 		STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_read); \
     64 		isc_result_t _result = isc_rwlock_tryupgrade(l); \
     65 		if (_result == ISC_R_SUCCESS) {                  \
     66 			*tp = isc_rwlocktype_write;              \
     67 		};                                               \
     68 		_result;                                         \
     69 	})
     70 #define NODE_FORCEUPGRADE(l, tp)                       \
     71 	if (NODE_TRYUPGRADE(l, tp) != ISC_R_SUCCESS) { \
     72 		NODE_UNLOCK(l, tp);                    \
     73 		NODE_WRLOCK(l, tp);                    \
     74 	}
     75 
     76 #define TREE_INITLOCK(l)    isc_rwlock_init(l)
     77 #define TREE_DESTROYLOCK(l) isc_rwlock_destroy(l)
     78 #define TREE_LOCK(l, t, tp)                                      \
     79 	{                                                        \
     80 		STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
     81 		RWLOCK(l, t);                                    \
     82 		*tp = t;                                         \
     83 	}
     84 #define TREE_UNLOCK(l, tp)                                       \
     85 	{                                                        \
     86 		STRONG_RWLOCK_CHECK(*tp != isc_rwlocktype_none); \
     87 		RWUNLOCK(l, *tp);                                \
     88 		*tp = isc_rwlocktype_none;                       \
     89 	}
     90 #define TREE_RDLOCK(l, tp) TREE_LOCK(l, isc_rwlocktype_read, tp);
     91 #define TREE_WRLOCK(l, tp) TREE_LOCK(l, isc_rwlocktype_write, tp);
     92 #define TREE_TRYLOCK(l, t, tp)                                   \
     93 	({                                                       \
     94 		STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
     95 		isc_result_t _result = isc_rwlock_trylock(l, t); \
     96 		if (_result == ISC_R_SUCCESS) {                  \
     97 			*tp = t;                                 \
     98 		};                                               \
     99 		_result;                                         \
    100 	})
    101 #define TREE_TRYRDLOCK(l, tp) TREE_TRYLOCK(l, isc_rwlocktype_read, tp)
    102 #define TREE_TRYWRLOCK(l, tp) TREE_TRYLOCK(l, isc_rwlocktype_write, tp)
    103 #define TREE_TRYUPGRADE(l, tp)                                   \
    104 	({                                                       \
    105 		STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_read); \
    106 		isc_result_t _result = isc_rwlock_tryupgrade(l); \
    107 		if (_result == ISC_R_SUCCESS) {                  \
    108 			*tp = isc_rwlocktype_write;              \
    109 		};                                               \
    110 		_result;                                         \
    111 	})
    112 #define TREE_FORCEUPGRADE(l, tp)                       \
    113 	if (TREE_TRYUPGRADE(l, tp) != ISC_R_SUCCESS) { \
    114 		TREE_UNLOCK(l, tp);                    \
    115 		TREE_WRLOCK(l, tp);                    \
    116 	}
    117 
    118 #define IS_STUB(db)  (((db)->common.attributes & DNS_DBATTR_STUB) != 0)
    119 #define IS_CACHE(db) (((db)->common.attributes & DNS_DBATTR_CACHE) != 0)
    120 
    121 ISC_LANG_BEGINDECLS
    122 
    123 struct dns_glue {
    124 	struct dns_glue *next;
    125 	dns_name_t name;
    126 	dns_rdataset_t rdataset_a;
    127 	dns_rdataset_t sigrdataset_a;
    128 	dns_rdataset_t rdataset_aaaa;
    129 	dns_rdataset_t sigrdataset_aaaa;
    130 };
    131 
    132 struct dns_gluelist {
    133 	isc_mem_t *mctx;
    134 
    135 	const dns_dbversion_t *version;
    136 	dns_slabheader_t *header;
    137 
    138 	struct dns_glue *glue;
    139 
    140 	struct rcu_head rcu_head;
    141 	struct cds_wfs_node wfs_node;
    142 };
    143 
    144 typedef struct dns_glue_additionaldata_ctx {
    145 	dns_db_t *db;
    146 	dns_dbversion_t *version;
    147 	dns_dbnode_t *node;
    148 
    149 	dns_glue_t *glue;
    150 } dns_glue_additionaldata_ctx_t;
    151 
    152 typedef struct {
    153 	isc_rwlock_t lock;
    154 	/* Protected in the refcount routines. */
    155 	isc_refcount_t references;
    156 	/* Locked by lock. */
    157 	bool exiting;
    158 } db_nodelock_t;
    159 
    160 static inline bool
    161 prio_type(dns_typepair_t type) {
    162 	switch (type) {
    163 	case dns_rdatatype_soa:
    164 	case DNS_SIGTYPE(dns_rdatatype_soa):
    165 	case dns_rdatatype_a:
    166 	case DNS_SIGTYPE(dns_rdatatype_a):
    167 	case dns_rdatatype_mx:
    168 	case DNS_SIGTYPE(dns_rdatatype_mx):
    169 	case dns_rdatatype_aaaa:
    170 	case DNS_SIGTYPE(dns_rdatatype_aaaa):
    171 	case dns_rdatatype_nsec:
    172 	case DNS_SIGTYPE(dns_rdatatype_nsec):
    173 	case dns_rdatatype_nsec3:
    174 	case DNS_SIGTYPE(dns_rdatatype_nsec3):
    175 	case dns_rdatatype_ns:
    176 	case DNS_SIGTYPE(dns_rdatatype_ns):
    177 	case dns_rdatatype_ds:
    178 	case DNS_SIGTYPE(dns_rdatatype_ds):
    179 	case dns_rdatatype_cname:
    180 	case DNS_SIGTYPE(dns_rdatatype_cname):
    181 	case dns_rdatatype_dname:
    182 	case DNS_SIGTYPE(dns_rdatatype_dname):
    183 	case dns_rdatatype_svcb:
    184 	case DNS_SIGTYPE(dns_rdatatype_svcb):
    185 	case dns_rdatatype_https:
    186 	case DNS_SIGTYPE(dns_rdatatype_https):
    187 	case dns_rdatatype_dnskey:
    188 	case DNS_SIGTYPE(dns_rdatatype_dnskey):
    189 	case dns_rdatatype_srv:
    190 	case DNS_SIGTYPE(dns_rdatatype_srv):
    191 	case dns_rdatatype_txt:
    192 	case DNS_SIGTYPE(dns_rdatatype_txt):
    193 	case dns_rdatatype_ptr:
    194 	case DNS_SIGTYPE(dns_rdatatype_ptr):
    195 	case dns_rdatatype_naptr:
    196 	case DNS_SIGTYPE(dns_rdatatype_naptr):
    197 		return true;
    198 	}
    199 	return false;
    200 }
    201 
    202 void
    203 dns__db_logtoomanyrecords(dns_db_t *db, const dns_name_t *name,
    204 			  dns_rdatatype_t type, const char *op, uint32_t limit);
    205 /*
    206  * Emit a log message when adding an rdataset of name/type would exceed the
    207  * 'maxrrperset' limit. 'op' is 'adding' or 'updating' depending on whether
    208  * the addition is to create a new rdataset or to merge to an existing one.
    209  */
    210 
    211 void
    212 dns__db_free_glue(isc_mem_t *mctx, dns_glue_t *glue);
    213 void
    214 dns__db_destroy_gluelist(dns_gluelist_t **gluelistp);
    215 void
    216 dns__db_free_gluelist_rcu(struct rcu_head *rcu_head);
    217 void
    218 dns__db_cleanup_gluelists(struct cds_wfs_stack *glue_stack);
    219 isc_result_t
    220 dns__db_addglue(dns_db_t *db, dns_dbversion_t *dbversion,
    221 		dns_rdataset_t *rdataset, dns_message_t *msg,
    222 		dns_additionaldatafunc_t add, struct cds_wfs_stack *glue_stack);
    223 
    224 dns_glue_t *
    225 dns__db_new_glue(isc_mem_t *mctx, const dns_name_t *name);
    226 
    227 ISC_LANG_ENDDECLS
    228