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