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