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