1 /* $NetBSD: rdatalist.c,v 1.7 2023/01/25 21:43:30 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 /*! \file */ 17 18 #include <stddef.h> 19 #include <string.h> 20 21 #include <isc/util.h> 22 23 #include <dns/name.h> 24 #include <dns/nsec3.h> 25 #include <dns/rdata.h> 26 #include <dns/rdatalist.h> 27 #include <dns/rdataset.h> 28 29 #include "rdatalist_p.h" 30 31 static dns_rdatasetmethods_t methods = { 32 isc__rdatalist_disassociate, 33 isc__rdatalist_first, 34 isc__rdatalist_next, 35 isc__rdatalist_current, 36 isc__rdatalist_clone, 37 isc__rdatalist_count, 38 isc__rdatalist_addnoqname, 39 isc__rdatalist_getnoqname, 40 isc__rdatalist_addclosest, 41 isc__rdatalist_getclosest, 42 NULL, /* settrust */ 43 NULL, /* expire */ 44 NULL, /* clearprefetch */ 45 isc__rdatalist_setownercase, 46 isc__rdatalist_getownercase, 47 NULL /* addglue */ 48 }; 49 50 void 51 dns_rdatalist_init(dns_rdatalist_t *rdatalist) { 52 REQUIRE(rdatalist != NULL); 53 54 /* 55 * Initialize rdatalist. 56 */ 57 58 rdatalist->rdclass = 0; 59 rdatalist->type = 0; 60 rdatalist->covers = 0; 61 rdatalist->ttl = 0; 62 ISC_LIST_INIT(rdatalist->rdata); 63 ISC_LINK_INIT(rdatalist, link); 64 memset(rdatalist->upper, 0xeb, sizeof(rdatalist->upper)); 65 /* 66 * Clear upper set bit. 67 */ 68 rdatalist->upper[0] &= ~0x01; 69 } 70 71 isc_result_t 72 dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist, dns_rdataset_t *rdataset) { 73 /* 74 * Make 'rdataset' refer to the rdata in 'rdatalist'. 75 */ 76 77 REQUIRE(rdatalist != NULL); 78 REQUIRE(DNS_RDATASET_VALID(rdataset)); 79 REQUIRE(!dns_rdataset_isassociated(rdataset)); 80 81 /* Check if dns_rdatalist_init has was called. */ 82 REQUIRE(rdatalist->upper[0] == 0xea); 83 84 rdataset->methods = &methods; 85 rdataset->rdclass = rdatalist->rdclass; 86 rdataset->type = rdatalist->type; 87 rdataset->covers = rdatalist->covers; 88 rdataset->ttl = rdatalist->ttl; 89 rdataset->trust = 0; 90 rdataset->private1 = rdatalist; 91 rdataset->private2 = NULL; 92 rdataset->private3 = NULL; 93 rdataset->privateuint4 = 0; 94 rdataset->private5 = NULL; 95 96 return (ISC_R_SUCCESS); 97 } 98 99 isc_result_t 100 dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset, 101 dns_rdatalist_t **rdatalist) { 102 REQUIRE(rdatalist != NULL && rdataset != NULL); 103 *rdatalist = rdataset->private1; 104 105 return (ISC_R_SUCCESS); 106 } 107 108 void 109 isc__rdatalist_disassociate(dns_rdataset_t *rdataset) { 110 UNUSED(rdataset); 111 } 112 113 isc_result_t 114 isc__rdatalist_first(dns_rdataset_t *rdataset) { 115 dns_rdatalist_t *rdatalist; 116 117 rdatalist = rdataset->private1; 118 rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata); 119 120 if (rdataset->private2 == NULL) { 121 return (ISC_R_NOMORE); 122 } 123 124 return (ISC_R_SUCCESS); 125 } 126 127 isc_result_t 128 isc__rdatalist_next(dns_rdataset_t *rdataset) { 129 dns_rdata_t *rdata; 130 131 REQUIRE(rdataset != NULL); 132 133 rdata = rdataset->private2; 134 if (rdata == NULL) { 135 return (ISC_R_NOMORE); 136 } 137 138 rdataset->private2 = ISC_LIST_NEXT(rdata, link); 139 140 if (rdataset->private2 == NULL) { 141 return (ISC_R_NOMORE); 142 } 143 144 return (ISC_R_SUCCESS); 145 } 146 147 void 148 isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 149 dns_rdata_t *list_rdata; 150 151 REQUIRE(rdataset != NULL); 152 153 list_rdata = rdataset->private2; 154 INSIST(list_rdata != NULL); 155 156 dns_rdata_clone(list_rdata, rdata); 157 } 158 159 void 160 isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 161 REQUIRE(source != NULL); 162 REQUIRE(target != NULL); 163 164 *target = *source; 165 166 /* 167 * Reset iterator state. 168 */ 169 target->private2 = NULL; 170 } 171 172 unsigned int 173 isc__rdatalist_count(dns_rdataset_t *rdataset) { 174 dns_rdatalist_t *rdatalist; 175 dns_rdata_t *rdata; 176 unsigned int count; 177 178 REQUIRE(rdataset != NULL); 179 180 rdatalist = rdataset->private1; 181 182 count = 0; 183 for (rdata = ISC_LIST_HEAD(rdatalist->rdata); rdata != NULL; 184 rdata = ISC_LIST_NEXT(rdata, link)) 185 { 186 count++; 187 } 188 189 return (count); 190 } 191 192 isc_result_t 193 isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, const dns_name_t *name) { 194 dns_rdataset_t *neg = NULL; 195 dns_rdataset_t *negsig = NULL; 196 dns_rdataset_t *rdset; 197 dns_ttl_t ttl; 198 199 REQUIRE(rdataset != NULL); 200 201 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL; 202 rdset = ISC_LIST_NEXT(rdset, link)) 203 { 204 if (rdset->rdclass != rdataset->rdclass) { 205 continue; 206 } 207 if (rdset->type == dns_rdatatype_nsec || 208 rdset->type == dns_rdatatype_nsec3) 209 { 210 neg = rdset; 211 } 212 } 213 if (neg == NULL) { 214 return (ISC_R_NOTFOUND); 215 } 216 217 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL; 218 rdset = ISC_LIST_NEXT(rdset, link)) 219 { 220 if (rdset->type == dns_rdatatype_rrsig && 221 rdset->covers == neg->type) 222 { 223 negsig = rdset; 224 } 225 } 226 227 if (negsig == NULL) { 228 return (ISC_R_NOTFOUND); 229 } 230 /* 231 * Minimise ttl. 232 */ 233 ttl = rdataset->ttl; 234 if (neg->ttl < ttl) { 235 ttl = neg->ttl; 236 } 237 if (negsig->ttl < ttl) { 238 ttl = negsig->ttl; 239 } 240 rdataset->ttl = neg->ttl = negsig->ttl = ttl; 241 rdataset->attributes |= DNS_RDATASETATTR_NOQNAME; 242 rdataset->private6 = name; 243 return (ISC_R_SUCCESS); 244 } 245 246 isc_result_t 247 isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, 248 dns_rdataset_t *neg, dns_rdataset_t *negsig) { 249 dns_rdataclass_t rdclass; 250 dns_rdataset_t *tneg = NULL; 251 dns_rdataset_t *tnegsig = NULL; 252 const dns_name_t *noqname; 253 254 REQUIRE(rdataset != NULL); 255 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0); 256 257 rdclass = rdataset->rdclass; 258 noqname = rdataset->private6; 259 260 (void)dns_name_dynamic(noqname); /* Sanity Check. */ 261 262 for (rdataset = ISC_LIST_HEAD(noqname->list); rdataset != NULL; 263 rdataset = ISC_LIST_NEXT(rdataset, link)) 264 { 265 if (rdataset->rdclass != rdclass) { 266 continue; 267 } 268 if (rdataset->type == dns_rdatatype_nsec || 269 rdataset->type == dns_rdatatype_nsec3) 270 { 271 tneg = rdataset; 272 } 273 } 274 if (tneg == NULL) { 275 return (ISC_R_NOTFOUND); 276 } 277 278 for (rdataset = ISC_LIST_HEAD(noqname->list); rdataset != NULL; 279 rdataset = ISC_LIST_NEXT(rdataset, link)) 280 { 281 if (rdataset->type == dns_rdatatype_rrsig && 282 rdataset->covers == tneg->type) 283 { 284 tnegsig = rdataset; 285 } 286 } 287 if (tnegsig == NULL) { 288 return (ISC_R_NOTFOUND); 289 } 290 291 dns_name_clone(noqname, name); 292 dns_rdataset_clone(tneg, neg); 293 dns_rdataset_clone(tnegsig, negsig); 294 return (ISC_R_SUCCESS); 295 } 296 297 isc_result_t 298 isc__rdatalist_addclosest(dns_rdataset_t *rdataset, const dns_name_t *name) { 299 dns_rdataset_t *neg = NULL; 300 dns_rdataset_t *negsig = NULL; 301 dns_rdataset_t *rdset; 302 dns_ttl_t ttl; 303 304 REQUIRE(rdataset != NULL); 305 306 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL; 307 rdset = ISC_LIST_NEXT(rdset, link)) 308 { 309 if (rdset->rdclass != rdataset->rdclass) { 310 continue; 311 } 312 if (rdset->type == dns_rdatatype_nsec || 313 rdset->type == dns_rdatatype_nsec3) 314 { 315 neg = rdset; 316 } 317 } 318 if (neg == NULL) { 319 return (ISC_R_NOTFOUND); 320 } 321 322 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL; 323 rdset = ISC_LIST_NEXT(rdset, link)) 324 { 325 if (rdset->type == dns_rdatatype_rrsig && 326 rdset->covers == neg->type) 327 { 328 negsig = rdset; 329 } 330 } 331 332 if (negsig == NULL) { 333 return (ISC_R_NOTFOUND); 334 } 335 /* 336 * Minimise ttl. 337 */ 338 ttl = rdataset->ttl; 339 if (neg->ttl < ttl) { 340 ttl = neg->ttl; 341 } 342 if (negsig->ttl < ttl) { 343 ttl = negsig->ttl; 344 } 345 rdataset->ttl = neg->ttl = negsig->ttl = ttl; 346 rdataset->attributes |= DNS_RDATASETATTR_CLOSEST; 347 rdataset->private7 = name; 348 return (ISC_R_SUCCESS); 349 } 350 351 isc_result_t 352 isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, 353 dns_rdataset_t *neg, dns_rdataset_t *negsig) { 354 dns_rdataclass_t rdclass; 355 dns_rdataset_t *tneg = NULL; 356 dns_rdataset_t *tnegsig = NULL; 357 const dns_name_t *closest; 358 359 REQUIRE(rdataset != NULL); 360 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0); 361 362 rdclass = rdataset->rdclass; 363 closest = rdataset->private7; 364 365 (void)dns_name_dynamic(closest); /* Sanity Check. */ 366 367 for (rdataset = ISC_LIST_HEAD(closest->list); rdataset != NULL; 368 rdataset = ISC_LIST_NEXT(rdataset, link)) 369 { 370 if (rdataset->rdclass != rdclass) { 371 continue; 372 } 373 if (rdataset->type == dns_rdatatype_nsec || 374 rdataset->type == dns_rdatatype_nsec3) 375 { 376 tneg = rdataset; 377 } 378 } 379 if (tneg == NULL) { 380 return (ISC_R_NOTFOUND); 381 } 382 383 for (rdataset = ISC_LIST_HEAD(closest->list); rdataset != NULL; 384 rdataset = ISC_LIST_NEXT(rdataset, link)) 385 { 386 if (rdataset->type == dns_rdatatype_rrsig && 387 rdataset->covers == tneg->type) 388 { 389 tnegsig = rdataset; 390 } 391 } 392 if (tnegsig == NULL) { 393 return (ISC_R_NOTFOUND); 394 } 395 396 dns_name_clone(closest, name); 397 dns_rdataset_clone(tneg, neg); 398 dns_rdataset_clone(tnegsig, negsig); 399 return (ISC_R_SUCCESS); 400 } 401 402 void 403 isc__rdatalist_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) { 404 dns_rdatalist_t *rdatalist; 405 unsigned int i; 406 407 /* 408 * We do not need to worry about label lengths as they are all 409 * less than or equal to 63. 410 */ 411 rdatalist = rdataset->private1; 412 memset(rdatalist->upper, 0, sizeof(rdatalist->upper)); 413 for (i = 1; i < name->length; i++) { 414 if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) { 415 rdatalist->upper[i / 8] |= 1 << (i % 8); 416 /* 417 * Record that upper has been set. 418 */ 419 } 420 } 421 /* 422 * Record that upper has been set. 423 */ 424 rdatalist->upper[0] |= 0x01; 425 } 426 427 void 428 isc__rdatalist_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) { 429 dns_rdatalist_t *rdatalist; 430 unsigned int i; 431 432 rdatalist = rdataset->private1; 433 if ((rdatalist->upper[0] & 0x01) == 0) { 434 return; 435 } 436 for (i = 0; i < name->length; i++) { 437 /* 438 * Set the case bit if it does not match the recorded bit. 439 */ 440 if (name->ndata[i] >= 0x61 && name->ndata[i] <= 0x7a && 441 (rdatalist->upper[i / 8] & (1 << (i % 8))) != 0) 442 { 443 name->ndata[i] &= ~0x20; /* clear the lower case bit */ 444 } else if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a && 445 (rdatalist->upper[i / 8] & (1 << (i % 8))) == 0) 446 { 447 name->ndata[i] |= 0x20; /* set the lower case bit */ 448 } 449 } 450 } 451