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