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