ncache.c revision 287410
1226048Sobrien/* 2226048Sobrien * Copyright (C) 2004, 2005, 2007, 2008, 2010-2013 Internet Systems Consortium, Inc. ("ISC") 3362844Sdelphij * Copyright (C) 1999-2003 Internet Software Consortium. 4226048Sobrien * 5226048Sobrien * Permission to use, copy, modify, and/or distribute this software for any 6226048Sobrien * purpose with or without fee is hereby granted, provided that the above 7226048Sobrien * copyright notice and this permission notice appear in all copies. 8354939Sdelphij * 9354939Sdelphij * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10354939Sdelphij * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11354939Sdelphij * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12226048Sobrien * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13354939Sdelphij * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14354939Sdelphij * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15354939Sdelphij * PERFORMANCE OF THIS SOFTWARE. 16354939Sdelphij */ 17354939Sdelphij 18354939Sdelphij/* $Id$ */ 19354939Sdelphij 20354939Sdelphij/*! \file */ 21354939Sdelphij 22354939Sdelphij#include <config.h> 23354939Sdelphij 24354939Sdelphij#include <isc/buffer.h> 25354939Sdelphij#include <isc/util.h> 26354939Sdelphij 27354939Sdelphij#include <dns/db.h> 28354939Sdelphij#include <dns/message.h> 29354939Sdelphij#include <dns/ncache.h> 30354939Sdelphij#include <dns/rdata.h> 31354939Sdelphij#include <dns/rdatalist.h> 32354939Sdelphij#include <dns/rdataset.h> 33354939Sdelphij#include <dns/rdatastruct.h> 34354939Sdelphij 35354939Sdelphij#define DNS_NCACHE_RDATA 20U 36354939Sdelphij 37354939Sdelphij/* 38354939Sdelphij * The format of an ncache rdata is a sequence of zero or more records of 39354939Sdelphij * the following format: 40354939Sdelphij * 41354939Sdelphij * owner name 42354939Sdelphij * type 43354939Sdelphij * trust 44354939Sdelphij * rdata count 45354939Sdelphij * rdata length These two occur 'rdata count' 46354939Sdelphij * rdata times. 47354939Sdelphij * 48354939Sdelphij */ 49354939Sdelphij 50354939Sdelphijstatic isc_result_t 51354939Sdelphijaddoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, 52354939Sdelphij dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl, 53354939Sdelphij isc_boolean_t optout, isc_boolean_t secure, 54354939Sdelphij dns_rdataset_t *addedrdataset); 55354939Sdelphij 56354939Sdelphijstatic inline isc_result_t 57354939Sdelphijcopy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) { 58354939Sdelphij isc_result_t result; 59354939Sdelphij unsigned int count; 60354939Sdelphij isc_region_t ar, r; 61354939Sdelphij dns_rdata_t rdata = DNS_RDATA_INIT; 62354939Sdelphij 63354939Sdelphij /* 64354939Sdelphij * Copy the rdataset count to the buffer. 65354939Sdelphij */ 66354939Sdelphij isc_buffer_availableregion(buffer, &ar); 67354939Sdelphij if (ar.length < 2) 68354939Sdelphij return (ISC_R_NOSPACE); 69354939Sdelphij count = dns_rdataset_count(rdataset); 70354939Sdelphij INSIST(count <= 65535); 71354939Sdelphij isc_buffer_putuint16(buffer, (isc_uint16_t)count); 72226048Sobrien 73354939Sdelphij result = dns_rdataset_first(rdataset); 74354939Sdelphij while (result == ISC_R_SUCCESS) { 75354939Sdelphij dns_rdataset_current(rdataset, &rdata); 76354939Sdelphij dns_rdata_toregion(&rdata, &r); 77354939Sdelphij INSIST(r.length <= 65535); 78354939Sdelphij isc_buffer_availableregion(buffer, &ar); 79354939Sdelphij if (ar.length < 2) 80354939Sdelphij return (ISC_R_NOSPACE); 81354939Sdelphij /* 82354939Sdelphij * Copy the rdata length to the buffer. 83354939Sdelphij */ 84354939Sdelphij isc_buffer_putuint16(buffer, (isc_uint16_t)r.length); 85354939Sdelphij /* 86354939Sdelphij * Copy the rdata to the buffer. 87354939Sdelphij */ 88354939Sdelphij result = isc_buffer_copyregion(buffer, &r); 89354939Sdelphij if (result != ISC_R_SUCCESS) 90354939Sdelphij return (result); 91354939Sdelphij dns_rdata_reset(&rdata); 92354939Sdelphij result = dns_rdataset_next(rdataset); 93354939Sdelphij } 94354939Sdelphij if (result != ISC_R_NOMORE) 95354939Sdelphij return (result); 96354939Sdelphij 97354939Sdelphij return (ISC_R_SUCCESS); 98354939Sdelphij} 99354939Sdelphij 100354939Sdelphijisc_result_t 101354939Sdelphijdns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, 102354939Sdelphij dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl, 103354939Sdelphij dns_rdataset_t *addedrdataset) 104354939Sdelphij{ 105354939Sdelphij return (addoptout(message, cache, node, covers, now, maxttl, 106354939Sdelphij ISC_FALSE, ISC_FALSE, addedrdataset)); 107354939Sdelphij} 108354939Sdelphij 109354939Sdelphijisc_result_t 110354939Sdelphijdns_ncache_addoptout(dns_message_t *message, dns_db_t *cache, 111354939Sdelphij dns_dbnode_t *node, dns_rdatatype_t covers, 112354939Sdelphij isc_stdtime_t now, dns_ttl_t maxttl, 113354939Sdelphij isc_boolean_t optout, dns_rdataset_t *addedrdataset) 114354939Sdelphij{ 115354939Sdelphij return (addoptout(message, cache, node, covers, now, maxttl, 116354939Sdelphij optout, ISC_TRUE, addedrdataset)); 117354939Sdelphij} 118354939Sdelphij 119354939Sdelphijstatic isc_result_t 120354939Sdelphijaddoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, 121354939Sdelphij dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl, 122354939Sdelphij isc_boolean_t optout, isc_boolean_t secure, 123354939Sdelphij dns_rdataset_t *addedrdataset) 124354939Sdelphij{ 125354939Sdelphij isc_result_t result; 126354939Sdelphij isc_buffer_t buffer; 127354939Sdelphij isc_region_t r; 128354939Sdelphij dns_rdataset_t *rdataset; 129354939Sdelphij dns_rdatatype_t type; 130354939Sdelphij dns_name_t *name; 131354939Sdelphij dns_ttl_t ttl; 132354939Sdelphij dns_trust_t trust; 133354939Sdelphij dns_rdata_t rdata[DNS_NCACHE_RDATA]; 134354939Sdelphij dns_rdataset_t ncrdataset; 135354939Sdelphij dns_rdatalist_t ncrdatalist; 136354939Sdelphij unsigned char data[4096]; 137354939Sdelphij unsigned int next = 0; 138354939Sdelphij 139354939Sdelphij /* 140354939Sdelphij * Convert the authority data from 'message' into a negative cache 141354939Sdelphij * rdataset, and store it in 'cache' at 'node'. 142354939Sdelphij */ 143354939Sdelphij 144354939Sdelphij REQUIRE(message != NULL); 145354939Sdelphij 146354939Sdelphij /* 147354939Sdelphij * We assume that all data in the authority section has been 148354939Sdelphij * validated by the caller. 149354939Sdelphij */ 150354939Sdelphij 151354939Sdelphij /* 152354939Sdelphij * Initialize the list. 153354939Sdelphij */ 154354939Sdelphij ncrdatalist.rdclass = dns_db_class(cache); 155354939Sdelphij ncrdatalist.type = 0; 156354939Sdelphij ncrdatalist.covers = covers; 157354939Sdelphij ncrdatalist.ttl = maxttl; 158354939Sdelphij ISC_LIST_INIT(ncrdatalist.rdata); 159354939Sdelphij ISC_LINK_INIT(&ncrdatalist, link); 160354939Sdelphij 161354939Sdelphij /* 162354939Sdelphij * Build an ncache rdatas into buffer. 163354939Sdelphij */ 164354939Sdelphij ttl = maxttl; 165354939Sdelphij trust = 0xffff; 166354939Sdelphij isc_buffer_init(&buffer, data, sizeof(data)); 167354939Sdelphij if (message->counts[DNS_SECTION_AUTHORITY]) 168354939Sdelphij result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); 169354939Sdelphij else 170354939Sdelphij result = ISC_R_NOMORE; 171354939Sdelphij while (result == ISC_R_SUCCESS) { 172354939Sdelphij name = NULL; 173354939Sdelphij dns_message_currentname(message, DNS_SECTION_AUTHORITY, 174354939Sdelphij &name); 175354939Sdelphij if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) { 176354939Sdelphij for (rdataset = ISC_LIST_HEAD(name->list); 177354939Sdelphij rdataset != NULL; 178354939Sdelphij rdataset = ISC_LIST_NEXT(rdataset, link)) { 179354939Sdelphij if ((rdataset->attributes & 180354939Sdelphij DNS_RDATASETATTR_NCACHE) == 0) 181354939Sdelphij continue; 182354939Sdelphij type = rdataset->type; 183354939Sdelphij if (type == dns_rdatatype_rrsig) 184354939Sdelphij type = rdataset->covers; 185354939Sdelphij if (type == dns_rdatatype_soa || 186354939Sdelphij type == dns_rdatatype_nsec || 187354939Sdelphij type == dns_rdatatype_nsec3) { 188354939Sdelphij if (ttl > rdataset->ttl) 189354939Sdelphij ttl = rdataset->ttl; 190354939Sdelphij if (trust > rdataset->trust) 191354939Sdelphij trust = rdataset->trust; 192354939Sdelphij /* 193354939Sdelphij * Copy the owner name to the buffer. 194354939Sdelphij */ 195267843Sdelphij dns_name_toregion(name, &r); 196267843Sdelphij result = isc_buffer_copyregion(&buffer, 197267843Sdelphij &r); 198267843Sdelphij if (result != ISC_R_SUCCESS) 199267843Sdelphij return (result); 200267843Sdelphij /* 201267843Sdelphij * Copy the type to the buffer. 202267843Sdelphij */ 203267843Sdelphij isc_buffer_availableregion(&buffer, 204267843Sdelphij &r); 205267843Sdelphij if (r.length < 3) 206267843Sdelphij return (ISC_R_NOSPACE); 207267843Sdelphij isc_buffer_putuint16(&buffer, 208267843Sdelphij rdataset->type); 209267843Sdelphij isc_buffer_putuint8(&buffer, 210267843Sdelphij (unsigned char)rdataset->trust); 211267843Sdelphij /* 212267843Sdelphij * Copy the rdataset into the buffer. 213267843Sdelphij */ 214267843Sdelphij result = copy_rdataset(rdataset, 215267843Sdelphij &buffer); 216267843Sdelphij if (result != ISC_R_SUCCESS) 217267843Sdelphij return (result); 218267843Sdelphij 219267843Sdelphij if (next >= DNS_NCACHE_RDATA) 220267843Sdelphij return (ISC_R_NOSPACE); 221267843Sdelphij dns_rdata_init(&rdata[next]); 222354939Sdelphij isc_buffer_remainingregion(&buffer, &r); 223267843Sdelphij rdata[next].data = r.base; 224267843Sdelphij rdata[next].length = r.length; 225267843Sdelphij rdata[next].rdclass = 226267843Sdelphij ncrdatalist.rdclass; 227267843Sdelphij rdata[next].type = 0; 228267843Sdelphij rdata[next].flags = 0; 229354939Sdelphij ISC_LIST_APPEND(ncrdatalist.rdata, 230354939Sdelphij &rdata[next], link); 231354939Sdelphij isc_buffer_forward(&buffer, r.length); 232267843Sdelphij next++; 233267843Sdelphij } 234267843Sdelphij } 235267843Sdelphij } 236267843Sdelphij result = dns_message_nextname(message, DNS_SECTION_AUTHORITY); 237267843Sdelphij } 238267843Sdelphij if (result != ISC_R_NOMORE) 239267843Sdelphij return (result); 240267843Sdelphij 241267843Sdelphij if (trust == 0xffff) { 242267843Sdelphij if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 && 243267843Sdelphij message->counts[DNS_SECTION_ANSWER] == 0) { 244267843Sdelphij /* 245267843Sdelphij * The response has aa set and we haven't followed 246267843Sdelphij * any CNAME or DNAME chains. 247267843Sdelphij */ 248267843Sdelphij trust = dns_trust_authauthority; 249267843Sdelphij } else 250267843Sdelphij trust = dns_trust_additional; 251267843Sdelphij ttl = 0; 252267843Sdelphij } 253354939Sdelphij 254267843Sdelphij INSIST(trust != 0xffff); 255267843Sdelphij 256267843Sdelphij ncrdatalist.ttl = ttl; 257267843Sdelphij 258267843Sdelphij dns_rdataset_init(&ncrdataset); 259267843Sdelphij RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset) 260267843Sdelphij == ISC_R_SUCCESS); 261267843Sdelphij if (!secure && trust > dns_trust_answer) 262267843Sdelphij trust = dns_trust_answer; 263267843Sdelphij ncrdataset.trust = trust; 264267843Sdelphij ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE; 265267843Sdelphij if (message->rcode == dns_rcode_nxdomain) 266267843Sdelphij ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN; 267267843Sdelphij if (optout) 268267843Sdelphij ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT; 269267843Sdelphij 270267843Sdelphij return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 271267843Sdelphij 0, addedrdataset)); 272267843Sdelphij} 273267843Sdelphij 274267843Sdelphijisc_result_t 275267843Sdelphijdns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx, 276267843Sdelphij isc_buffer_t *target, unsigned int options, 277267843Sdelphij unsigned int *countp) 278267843Sdelphij{ 279267843Sdelphij dns_rdata_t rdata = DNS_RDATA_INIT; 280267843Sdelphij isc_result_t result; 281267843Sdelphij isc_region_t remaining, tavailable; 282267843Sdelphij isc_buffer_t source, savedbuffer, rdlen; 283267843Sdelphij dns_name_t name; 284267843Sdelphij dns_rdatatype_t type; 285267843Sdelphij unsigned int i, rcount, count; 286267843Sdelphij 287267843Sdelphij /* 288267843Sdelphij * Convert the negative caching rdataset 'rdataset' to wire format, 289354939Sdelphij * compressing names as specified in 'cctx', and storing the result in 290267843Sdelphij * 'target'. 291267843Sdelphij */ 292267843Sdelphij 293226048Sobrien REQUIRE(rdataset != NULL); 294234250Sobrien REQUIRE(rdataset->type == 0); 295234250Sobrien REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 296234250Sobrien 297234250Sobrien savedbuffer = *target; 298234250Sobrien count = 0; 299267843Sdelphij 300267843Sdelphij result = dns_rdataset_first(rdataset); 301267843Sdelphij while (result == ISC_R_SUCCESS) { 302267843Sdelphij dns_rdataset_current(rdataset, &rdata); 303267843Sdelphij isc_buffer_init(&source, rdata.data, rdata.length); 304267843Sdelphij isc_buffer_add(&source, rdata.length); 305267843Sdelphij dns_name_init(&name, NULL); 306267843Sdelphij isc_buffer_remainingregion(&source, &remaining); 307267843Sdelphij dns_name_fromregion(&name, &remaining); 308 INSIST(remaining.length >= name.length); 309 isc_buffer_forward(&source, name.length); 310 remaining.length -= name.length; 311 312 INSIST(remaining.length >= 5); 313 type = isc_buffer_getuint16(&source); 314 isc_buffer_forward(&source, 1); 315 rcount = isc_buffer_getuint16(&source); 316 317 for (i = 0; i < rcount; i++) { 318 /* 319 * Get the length of this rdata and set up an 320 * rdata structure for it. 321 */ 322 isc_buffer_remainingregion(&source, &remaining); 323 INSIST(remaining.length >= 2); 324 dns_rdata_reset(&rdata); 325 rdata.length = isc_buffer_getuint16(&source); 326 isc_buffer_remainingregion(&source, &remaining); 327 rdata.data = remaining.base; 328 rdata.type = type; 329 rdata.rdclass = rdataset->rdclass; 330 INSIST(remaining.length >= rdata.length); 331 isc_buffer_forward(&source, rdata.length); 332 333 if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 && 334 dns_rdatatype_isdnssec(type)) 335 continue; 336 337 /* 338 * Write the name. 339 */ 340 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); 341 result = dns_name_towire(&name, cctx, target); 342 if (result != ISC_R_SUCCESS) 343 goto rollback; 344 345 /* 346 * See if we have space for type, class, ttl, and 347 * rdata length. Write the type, class, and ttl. 348 */ 349 isc_buffer_availableregion(target, &tavailable); 350 if (tavailable.length < 10) { 351 result = ISC_R_NOSPACE; 352 goto rollback; 353 } 354 isc_buffer_putuint16(target, type); 355 isc_buffer_putuint16(target, rdataset->rdclass); 356 isc_buffer_putuint32(target, rdataset->ttl); 357 358 /* 359 * Save space for rdata length. 360 */ 361 rdlen = *target; 362 isc_buffer_add(target, 2); 363 364 /* 365 * Write the rdata. 366 */ 367 result = dns_rdata_towire(&rdata, cctx, target); 368 if (result != ISC_R_SUCCESS) 369 goto rollback; 370 371 /* 372 * Set the rdata length field to the compressed 373 * length. 374 */ 375 INSIST((target->used >= rdlen.used + 2) && 376 (target->used - rdlen.used - 2 < 65536)); 377 isc_buffer_putuint16(&rdlen, 378 (isc_uint16_t)(target->used - 379 rdlen.used - 2)); 380 381 count++; 382 } 383 INSIST(isc_buffer_remaininglength(&source) == 0); 384 result = dns_rdataset_next(rdataset); 385 dns_rdata_reset(&rdata); 386 } 387 if (result != ISC_R_NOMORE) 388 goto rollback; 389 390 *countp = count; 391 392 return (ISC_R_SUCCESS); 393 394 rollback: 395 INSIST(savedbuffer.used < 65536); 396 dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); 397 *countp = 0; 398 *target = savedbuffer; 399 400 return (result); 401} 402 403static void 404rdataset_disassociate(dns_rdataset_t *rdataset) { 405 UNUSED(rdataset); 406} 407 408static isc_result_t 409rdataset_first(dns_rdataset_t *rdataset) { 410 unsigned char *raw = rdataset->private3; 411 unsigned int count; 412 413 count = raw[0] * 256 + raw[1]; 414 if (count == 0) { 415 rdataset->private5 = NULL; 416 return (ISC_R_NOMORE); 417 } 418 raw += 2; 419 /* 420 * The privateuint4 field is the number of rdata beyond the cursor 421 * position, so we decrement the total count by one before storing 422 * it. 423 */ 424 count--; 425 rdataset->privateuint4 = count; 426 rdataset->private5 = raw; 427 428 return (ISC_R_SUCCESS); 429} 430 431static isc_result_t 432rdataset_next(dns_rdataset_t *rdataset) { 433 unsigned int count; 434 unsigned int length; 435 unsigned char *raw; 436 437 count = rdataset->privateuint4; 438 if (count == 0) 439 return (ISC_R_NOMORE); 440 count--; 441 rdataset->privateuint4 = count; 442 raw = rdataset->private5; 443 length = raw[0] * 256 + raw[1]; 444 raw += length + 2; 445 rdataset->private5 = raw; 446 447 return (ISC_R_SUCCESS); 448} 449 450static void 451rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 452 unsigned char *raw = rdataset->private5; 453 isc_region_t r; 454 455 REQUIRE(raw != NULL); 456 457 r.length = raw[0] * 256 + raw[1]; 458 raw += 2; 459 r.base = raw; 460 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); 461} 462 463static void 464rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 465 *target = *source; 466 467 /* 468 * Reset iterator state. 469 */ 470 target->privateuint4 = 0; 471 target->private5 = NULL; 472} 473 474static unsigned int 475rdataset_count(dns_rdataset_t *rdataset) { 476 unsigned char *raw = rdataset->private3; 477 unsigned int count; 478 479 count = raw[0] * 256 + raw[1]; 480 481 return (count); 482} 483 484static void 485rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { 486 unsigned char *raw = rdataset->private3; 487 488 raw[-1] = (unsigned char)trust; 489} 490 491static dns_rdatasetmethods_t rdataset_methods = { 492 rdataset_disassociate, 493 rdataset_first, 494 rdataset_next, 495 rdataset_current, 496 rdataset_clone, 497 rdataset_count, 498 NULL, 499 NULL, 500 NULL, 501 NULL, 502 NULL, 503 NULL, 504 NULL, 505 rdataset_settrust, 506 NULL 507}; 508 509isc_result_t 510dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, 511 dns_rdatatype_t type, dns_rdataset_t *rdataset) 512{ 513 isc_result_t result; 514 dns_rdata_t rdata = DNS_RDATA_INIT; 515 isc_region_t remaining; 516 isc_buffer_t source; 517 dns_name_t tname; 518 dns_rdatatype_t ttype; 519 dns_trust_t trust = dns_trust_none; 520 dns_rdataset_t clone; 521 522 REQUIRE(ncacherdataset != NULL); 523 REQUIRE(ncacherdataset->type == 0); 524 REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 525 REQUIRE(name != NULL); 526 REQUIRE(!dns_rdataset_isassociated(rdataset)); 527 REQUIRE(type != dns_rdatatype_rrsig); 528 529 dns_rdataset_init(&clone); 530 dns_rdataset_clone(ncacherdataset, &clone); 531 result = dns_rdataset_first(&clone); 532 while (result == ISC_R_SUCCESS) { 533 dns_rdataset_current(&clone, &rdata); 534 isc_buffer_init(&source, rdata.data, rdata.length); 535 isc_buffer_add(&source, rdata.length); 536 dns_name_init(&tname, NULL); 537 isc_buffer_remainingregion(&source, &remaining); 538 dns_name_fromregion(&tname, &remaining); 539 INSIST(remaining.length >= tname.length); 540 isc_buffer_forward(&source, tname.length); 541 remaining.length -= tname.length; 542 543 INSIST(remaining.length >= 3); 544 ttype = isc_buffer_getuint16(&source); 545 546 if (ttype == type && dns_name_equal(&tname, name)) { 547 trust = isc_buffer_getuint8(&source); 548 INSIST(trust <= dns_trust_ultimate); 549 isc_buffer_remainingregion(&source, &remaining); 550 break; 551 } 552 result = dns_rdataset_next(&clone); 553 dns_rdata_reset(&rdata); 554 } 555 dns_rdataset_disassociate(&clone); 556 if (result == ISC_R_NOMORE) 557 return (ISC_R_NOTFOUND); 558 if (result != ISC_R_SUCCESS) 559 return (result); 560 561 INSIST(remaining.length != 0); 562 563 rdataset->methods = &rdataset_methods; 564 rdataset->rdclass = ncacherdataset->rdclass; 565 rdataset->type = type; 566 rdataset->covers = 0; 567 rdataset->ttl = ncacherdataset->ttl; 568 rdataset->trust = trust; 569 rdataset->private1 = NULL; 570 rdataset->private2 = NULL; 571 572 rdataset->private3 = remaining.base; 573 574 /* 575 * Reset iterator state. 576 */ 577 rdataset->privateuint4 = 0; 578 rdataset->private5 = NULL; 579 rdataset->private6 = NULL; 580 return (ISC_R_SUCCESS); 581} 582 583isc_result_t 584dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, 585 dns_rdatatype_t covers, dns_rdataset_t *rdataset) 586{ 587 dns_name_t tname; 588 dns_rdata_rrsig_t rrsig; 589 dns_rdata_t rdata = DNS_RDATA_INIT; 590 dns_rdataset_t clone; 591 dns_rdatatype_t type; 592 dns_trust_t trust = dns_trust_none; 593 isc_buffer_t source; 594 isc_region_t remaining, sigregion; 595 isc_result_t result; 596 unsigned char *raw; 597 unsigned int count; 598 599 REQUIRE(ncacherdataset != NULL); 600 REQUIRE(ncacherdataset->type == 0); 601 REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 602 REQUIRE(name != NULL); 603 REQUIRE(!dns_rdataset_isassociated(rdataset)); 604 605 dns_rdataset_init(&clone); 606 dns_rdataset_clone(ncacherdataset, &clone); 607 result = dns_rdataset_first(&clone); 608 while (result == ISC_R_SUCCESS) { 609 dns_rdataset_current(&clone, &rdata); 610 isc_buffer_init(&source, rdata.data, rdata.length); 611 isc_buffer_add(&source, rdata.length); 612 dns_name_init(&tname, NULL); 613 isc_buffer_remainingregion(&source, &remaining); 614 dns_name_fromregion(&tname, &remaining); 615 INSIST(remaining.length >= tname.length); 616 isc_buffer_forward(&source, tname.length); 617 isc_region_consume(&remaining, tname.length); 618 619 INSIST(remaining.length >= 2); 620 type = isc_buffer_getuint16(&source); 621 isc_region_consume(&remaining, 2); 622 623 if (type != dns_rdatatype_rrsig || 624 !dns_name_equal(&tname, name)) { 625 result = dns_rdataset_next(&clone); 626 dns_rdata_reset(&rdata); 627 continue; 628 } 629 630 INSIST(remaining.length >= 1); 631 trust = isc_buffer_getuint8(&source); 632 INSIST(trust <= dns_trust_ultimate); 633 isc_region_consume(&remaining, 1); 634 635 raw = remaining.base; 636 count = raw[0] * 256 + raw[1]; 637 INSIST(count > 0); 638 raw += 2; 639 sigregion.length = raw[0] * 256 + raw[1]; 640 raw += 2; 641 sigregion.base = raw; 642 dns_rdata_reset(&rdata); 643 dns_rdata_fromregion(&rdata, rdataset->rdclass, 644 dns_rdatatype_rrsig, &sigregion); 645 (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); 646 if (rrsig.covered == covers) { 647 isc_buffer_remainingregion(&source, &remaining); 648 break; 649 } 650 651 result = dns_rdataset_next(&clone); 652 dns_rdata_reset(&rdata); 653 } 654 dns_rdataset_disassociate(&clone); 655 if (result == ISC_R_NOMORE) 656 return (ISC_R_NOTFOUND); 657 if (result != ISC_R_SUCCESS) 658 return (result); 659 660 INSIST(remaining.length != 0); 661 662 rdataset->methods = &rdataset_methods; 663 rdataset->rdclass = ncacherdataset->rdclass; 664 rdataset->type = dns_rdatatype_rrsig; 665 rdataset->covers = covers; 666 rdataset->ttl = ncacherdataset->ttl; 667 rdataset->trust = trust; 668 rdataset->private1 = NULL; 669 rdataset->private2 = NULL; 670 671 rdataset->private3 = remaining.base; 672 673 /* 674 * Reset iterator state. 675 */ 676 rdataset->privateuint4 = 0; 677 rdataset->private5 = NULL; 678 rdataset->private6 = NULL; 679 return (ISC_R_SUCCESS); 680} 681 682void 683dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found, 684 dns_rdataset_t *rdataset) 685{ 686 dns_rdata_t rdata = DNS_RDATA_INIT; 687 dns_trust_t trust; 688 isc_region_t remaining, sigregion; 689 isc_buffer_t source; 690 dns_name_t tname; 691 dns_rdatatype_t type; 692 unsigned int count; 693 dns_rdata_rrsig_t rrsig; 694 unsigned char *raw; 695 696 REQUIRE(ncacherdataset != NULL); 697 REQUIRE(ncacherdataset->type == 0); 698 REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 699 REQUIRE(found != NULL); 700 REQUIRE(!dns_rdataset_isassociated(rdataset)); 701 702 dns_rdataset_current(ncacherdataset, &rdata); 703 isc_buffer_init(&source, rdata.data, rdata.length); 704 isc_buffer_add(&source, rdata.length); 705 706 dns_name_init(&tname, NULL); 707 isc_buffer_remainingregion(&source, &remaining); 708 dns_name_fromregion(found, &remaining); 709 INSIST(remaining.length >= found->length); 710 isc_buffer_forward(&source, found->length); 711 remaining.length -= found->length; 712 713 INSIST(remaining.length >= 5); 714 type = isc_buffer_getuint16(&source); 715 trust = isc_buffer_getuint8(&source); 716 INSIST(trust <= dns_trust_ultimate); 717 isc_buffer_remainingregion(&source, &remaining); 718 719 rdataset->methods = &rdataset_methods; 720 rdataset->rdclass = ncacherdataset->rdclass; 721 rdataset->type = type; 722 if (type == dns_rdatatype_rrsig) { 723 /* 724 * Extract covers from RRSIG. 725 */ 726 raw = remaining.base; 727 count = raw[0] * 256 + raw[1]; 728 INSIST(count > 0); 729 raw += 2; 730 sigregion.length = raw[0] * 256 + raw[1]; 731 raw += 2; 732 sigregion.base = raw; 733 dns_rdata_reset(&rdata); 734 dns_rdata_fromregion(&rdata, rdataset->rdclass, 735 rdataset->type, &sigregion); 736 (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); 737 rdataset->covers = rrsig.covered; 738 } else 739 rdataset->covers = 0; 740 rdataset->ttl = ncacherdataset->ttl; 741 rdataset->trust = trust; 742 rdataset->private1 = NULL; 743 rdataset->private2 = NULL; 744 745 rdataset->private3 = remaining.base; 746 747 /* 748 * Reset iterator state. 749 */ 750 rdataset->privateuint4 = 0; 751 rdataset->private5 = NULL; 752 rdataset->private6 = NULL; 753} 754