1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* $Id: rdatalist.c,v 1.2 2020/02/18 18:11:27 florian Exp $ */ 18 19 /*! \file */ 20 21 #include <stddef.h> 22 23 #include <isc/util.h> 24 25 #include <dns/name.h> 26 #include <dns/rdata.h> 27 #include <dns/rdatalist.h> 28 #include <dns/rdataset.h> 29 30 #include "rdatalist_p.h" 31 32 static dns_rdatasetmethods_t methods = { 33 isc__rdatalist_disassociate, 34 isc__rdatalist_first, 35 isc__rdatalist_next, 36 isc__rdatalist_current, 37 isc__rdatalist_clone, 38 isc__rdatalist_count, 39 isc__rdatalist_addnoqname, 40 isc__rdatalist_getnoqname, 41 isc__rdatalist_addclosest, 42 isc__rdatalist_getclosest, 43 NULL, 44 NULL, 45 NULL, 46 NULL, 47 NULL, 48 NULL 49 }; 50 51 void 52 dns_rdatalist_init(dns_rdatalist_t *rdatalist) { 53 54 REQUIRE(rdatalist != NULL); 55 56 /* 57 * Initialize rdatalist. 58 */ 59 60 rdatalist->rdclass = 0; 61 rdatalist->type = 0; 62 rdatalist->covers = 0; 63 rdatalist->ttl = 0; 64 ISC_LIST_INIT(rdatalist->rdata); 65 ISC_LINK_INIT(rdatalist, link); 66 } 67 68 isc_result_t 69 dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist, 70 dns_rdataset_t *rdataset) 71 { 72 /* 73 * Make 'rdataset' refer to the rdata in 'rdatalist'. 74 */ 75 76 REQUIRE(rdatalist != NULL); 77 REQUIRE(! dns_rdataset_isassociated(rdataset)); 78 79 rdataset->methods = &methods; 80 rdataset->rdclass = rdatalist->rdclass; 81 rdataset->type = rdatalist->type; 82 rdataset->covers = rdatalist->covers; 83 rdataset->ttl = rdatalist->ttl; 84 rdataset->trust = 0; 85 rdataset->private1 = rdatalist; 86 rdataset->private2 = NULL; 87 rdataset->private3 = NULL; 88 rdataset->privateuint4 = 0; 89 rdataset->private5 = NULL; 90 91 return (ISC_R_SUCCESS); 92 } 93 94 isc_result_t 95 dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset, 96 dns_rdatalist_t **rdatalist) 97 { 98 REQUIRE(rdatalist != NULL && rdataset != NULL); 99 *rdatalist = rdataset->private1; 100 101 return (ISC_R_SUCCESS); 102 } 103 104 void 105 isc__rdatalist_disassociate(dns_rdataset_t *rdataset) { 106 UNUSED(rdataset); 107 } 108 109 isc_result_t 110 isc__rdatalist_first(dns_rdataset_t *rdataset) { 111 dns_rdatalist_t *rdatalist; 112 113 rdatalist = rdataset->private1; 114 rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata); 115 116 if (rdataset->private2 == NULL) 117 return (ISC_R_NOMORE); 118 119 return (ISC_R_SUCCESS); 120 } 121 122 isc_result_t 123 isc__rdatalist_next(dns_rdataset_t *rdataset) { 124 dns_rdata_t *rdata; 125 126 REQUIRE(rdataset != NULL); 127 128 rdata = rdataset->private2; 129 if (rdata == NULL) 130 return (ISC_R_NOMORE); 131 132 rdataset->private2 = ISC_LIST_NEXT(rdata, link); 133 134 if (rdataset->private2 == NULL) 135 return (ISC_R_NOMORE); 136 137 return (ISC_R_SUCCESS); 138 } 139 140 void 141 isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 142 dns_rdata_t *list_rdata; 143 144 REQUIRE(rdataset != NULL); 145 146 list_rdata = rdataset->private2; 147 INSIST(list_rdata != NULL); 148 149 dns_rdata_clone(list_rdata, rdata); 150 } 151 152 void 153 isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 154 155 REQUIRE(source != NULL); 156 REQUIRE(target != NULL); 157 158 *target = *source; 159 160 /* 161 * Reset iterator state. 162 */ 163 target->private2 = NULL; 164 } 165 166 unsigned int 167 isc__rdatalist_count(dns_rdataset_t *rdataset) { 168 dns_rdatalist_t *rdatalist; 169 dns_rdata_t *rdata; 170 unsigned int count; 171 172 REQUIRE(rdataset != NULL); 173 174 rdatalist = rdataset->private1; 175 176 count = 0; 177 for (rdata = ISC_LIST_HEAD(rdatalist->rdata); 178 rdata != NULL; 179 rdata = ISC_LIST_NEXT(rdata, link)) 180 count++; 181 182 return (count); 183 } 184 185 isc_result_t 186 isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) { 187 dns_rdataset_t *neg = NULL; 188 dns_rdataset_t *negsig = NULL; 189 dns_rdataset_t *rdset; 190 dns_ttl_t ttl; 191 192 REQUIRE(rdataset != NULL); 193 194 for (rdset = ISC_LIST_HEAD(name->list); 195 rdset != NULL; 196 rdset = ISC_LIST_NEXT(rdset, link)) 197 { 198 if (rdset->rdclass != rdataset->rdclass) 199 continue; 200 if (rdset->type == dns_rdatatype_nsec || 201 rdset->type == dns_rdatatype_nsec3) 202 neg = rdset; 203 } 204 if (neg == NULL) 205 return (ISC_R_NOTFOUND); 206 207 for (rdset = ISC_LIST_HEAD(name->list); 208 rdset != NULL; 209 rdset = ISC_LIST_NEXT(rdset, link)) 210 { 211 if (rdset->type == dns_rdatatype_rrsig && 212 rdset->covers == neg->type) 213 negsig = rdset; 214 } 215 216 if (negsig == NULL) 217 return (ISC_R_NOTFOUND); 218 /* 219 * Minimise ttl. 220 */ 221 ttl = rdataset->ttl; 222 if (neg->ttl < ttl) 223 ttl = neg->ttl; 224 if (negsig->ttl < ttl) 225 ttl = negsig->ttl; 226 rdataset->ttl = neg->ttl = negsig->ttl = ttl; 227 rdataset->attributes |= DNS_RDATASETATTR_NOQNAME; 228 rdataset->private6 = name; 229 return (ISC_R_SUCCESS); 230 } 231 232 isc_result_t 233 isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, 234 dns_rdataset_t *neg, dns_rdataset_t *negsig) 235 { 236 dns_rdataclass_t rdclass = rdataset->rdclass; 237 dns_rdataset_t *tneg = NULL; 238 dns_rdataset_t *tnegsig = NULL; 239 dns_name_t *noqname = rdataset->private6; 240 241 REQUIRE(rdataset != NULL); 242 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0); 243 244 (void)dns_name_dynamic(noqname); /* Sanity Check. */ 245 246 for (rdataset = ISC_LIST_HEAD(noqname->list); 247 rdataset != NULL; 248 rdataset = ISC_LIST_NEXT(rdataset, link)) 249 { 250 if (rdataset->rdclass != rdclass) 251 continue; 252 if (rdataset->type == dns_rdatatype_nsec || 253 rdataset->type == dns_rdatatype_nsec3) 254 tneg = rdataset; 255 } 256 if (tneg == NULL) 257 return (ISC_R_NOTFOUND); 258 259 for (rdataset = ISC_LIST_HEAD(noqname->list); 260 rdataset != NULL; 261 rdataset = ISC_LIST_NEXT(rdataset, link)) 262 { 263 if (rdataset->type == dns_rdatatype_rrsig && 264 rdataset->covers == tneg->type) 265 tnegsig = rdataset; 266 } 267 if (tnegsig == NULL) 268 return (ISC_R_NOTFOUND); 269 270 dns_name_clone(noqname, name); 271 dns_rdataset_clone(tneg, neg); 272 dns_rdataset_clone(tnegsig, negsig); 273 return (ISC_R_SUCCESS); 274 } 275 276 isc_result_t 277 isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) { 278 dns_rdataset_t *neg = NULL; 279 dns_rdataset_t *negsig = NULL; 280 dns_rdataset_t *rdset; 281 dns_ttl_t ttl; 282 283 REQUIRE(rdataset != NULL); 284 285 for (rdset = ISC_LIST_HEAD(name->list); 286 rdset != NULL; 287 rdset = ISC_LIST_NEXT(rdset, link)) 288 { 289 if (rdset->rdclass != rdataset->rdclass) 290 continue; 291 if (rdset->type == dns_rdatatype_nsec || 292 rdset->type == dns_rdatatype_nsec3) 293 neg = rdset; 294 } 295 if (neg == NULL) 296 return (ISC_R_NOTFOUND); 297 298 for (rdset = ISC_LIST_HEAD(name->list); 299 rdset != NULL; 300 rdset = ISC_LIST_NEXT(rdset, link)) 301 { 302 if (rdset->type == dns_rdatatype_rrsig && 303 rdset->covers == neg->type) 304 negsig = rdset; 305 } 306 307 if (negsig == NULL) 308 return (ISC_R_NOTFOUND); 309 /* 310 * Minimise ttl. 311 */ 312 ttl = rdataset->ttl; 313 if (neg->ttl < ttl) 314 ttl = neg->ttl; 315 if (negsig->ttl < ttl) 316 ttl = negsig->ttl; 317 rdataset->ttl = neg->ttl = negsig->ttl = ttl; 318 rdataset->attributes |= DNS_RDATASETATTR_CLOSEST; 319 rdataset->private7 = name; 320 return (ISC_R_SUCCESS); 321 } 322 323 isc_result_t 324 isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, 325 dns_rdataset_t *neg, dns_rdataset_t *negsig) 326 { 327 dns_rdataclass_t rdclass = rdataset->rdclass; 328 dns_rdataset_t *tneg = NULL; 329 dns_rdataset_t *tnegsig = NULL; 330 dns_name_t *closest = rdataset->private7; 331 332 REQUIRE(rdataset != NULL); 333 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0); 334 335 (void)dns_name_dynamic(closest); /* Sanity Check. */ 336 337 for (rdataset = ISC_LIST_HEAD(closest->list); 338 rdataset != NULL; 339 rdataset = ISC_LIST_NEXT(rdataset, link)) 340 { 341 if (rdataset->rdclass != rdclass) 342 continue; 343 if (rdataset->type == dns_rdatatype_nsec || 344 rdataset->type == dns_rdatatype_nsec3) 345 tneg = rdataset; 346 } 347 if (tneg == NULL) 348 return (ISC_R_NOTFOUND); 349 350 for (rdataset = ISC_LIST_HEAD(closest->list); 351 rdataset != NULL; 352 rdataset = ISC_LIST_NEXT(rdataset, link)) 353 { 354 if (rdataset->type == dns_rdatatype_rrsig && 355 rdataset->covers == tneg->type) 356 tnegsig = rdataset; 357 } 358 if (tnegsig == NULL) 359 return (ISC_R_NOTFOUND); 360 361 dns_name_clone(closest, name); 362 dns_rdataset_clone(tneg, neg); 363 dns_rdataset_clone(tnegsig, negsig); 364 return (ISC_R_SUCCESS); 365 } 366