rdataset.c revision 225361
1135446Strhodes/* 2223812Sdougb * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2003 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18225361Sdougb/* $Id: rdataset.c,v 1.86.148.4 2011-06-08 23:02:42 each Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <stdlib.h> 25135446Strhodes 26135446Strhodes#include <isc/buffer.h> 27135446Strhodes#include <isc/mem.h> 28135446Strhodes#include <isc/random.h> 29135446Strhodes#include <isc/util.h> 30135446Strhodes 31135446Strhodes#include <dns/name.h> 32135446Strhodes#include <dns/ncache.h> 33135446Strhodes#include <dns/rdata.h> 34135446Strhodes#include <dns/rdataset.h> 35135446Strhodes#include <dns/compress.h> 36135446Strhodes 37222395Sdougbstatic const char *trustnames[] = { 38222395Sdougb "none", 39222395Sdougb "pending-additional", 40222395Sdougb "pending-answer", 41222395Sdougb "additional", 42222395Sdougb "glue", 43222395Sdougb "answer", 44222395Sdougb "authauthority", 45222395Sdougb "authanswer", 46222395Sdougb "secure", 47222395Sdougb "local" /* aka ultimate */ 48222395Sdougb}; 49222395Sdougb 50222395Sdougbconst char * 51222395Sdougbdns_trust_totext(dns_trust_t trust) { 52222395Sdougb if (trust >= sizeof(trustnames)/sizeof(*trustnames)) 53222395Sdougb return ("bad"); 54222395Sdougb return (trustnames[trust]); 55222395Sdougb} 56222395Sdougb 57135446Strhodesvoid 58135446Strhodesdns_rdataset_init(dns_rdataset_t *rdataset) { 59135446Strhodes 60135446Strhodes /* 61135446Strhodes * Make 'rdataset' a valid, disassociated rdataset. 62135446Strhodes */ 63135446Strhodes 64135446Strhodes REQUIRE(rdataset != NULL); 65135446Strhodes 66135446Strhodes rdataset->magic = DNS_RDATASET_MAGIC; 67135446Strhodes rdataset->methods = NULL; 68135446Strhodes ISC_LINK_INIT(rdataset, link); 69135446Strhodes rdataset->rdclass = 0; 70135446Strhodes rdataset->type = 0; 71135446Strhodes rdataset->ttl = 0; 72135446Strhodes rdataset->trust = 0; 73135446Strhodes rdataset->covers = 0; 74135446Strhodes rdataset->attributes = 0; 75135446Strhodes rdataset->count = ISC_UINT32_MAX; 76135446Strhodes rdataset->private1 = NULL; 77135446Strhodes rdataset->private2 = NULL; 78135446Strhodes rdataset->private3 = NULL; 79135446Strhodes rdataset->privateuint4 = 0; 80135446Strhodes rdataset->private5 = NULL; 81135446Strhodes rdataset->private6 = NULL; 82193149Sdougb rdataset->resign = 0; 83135446Strhodes} 84135446Strhodes 85135446Strhodesvoid 86135446Strhodesdns_rdataset_invalidate(dns_rdataset_t *rdataset) { 87135446Strhodes 88135446Strhodes /* 89135446Strhodes * Invalidate 'rdataset'. 90135446Strhodes */ 91135446Strhodes 92135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 93135446Strhodes REQUIRE(rdataset->methods == NULL); 94135446Strhodes 95135446Strhodes rdataset->magic = 0; 96135446Strhodes ISC_LINK_INIT(rdataset, link); 97135446Strhodes rdataset->rdclass = 0; 98135446Strhodes rdataset->type = 0; 99135446Strhodes rdataset->ttl = 0; 100135446Strhodes rdataset->trust = 0; 101135446Strhodes rdataset->covers = 0; 102135446Strhodes rdataset->attributes = 0; 103135446Strhodes rdataset->count = ISC_UINT32_MAX; 104135446Strhodes rdataset->private1 = NULL; 105135446Strhodes rdataset->private2 = NULL; 106135446Strhodes rdataset->private3 = NULL; 107135446Strhodes rdataset->privateuint4 = 0; 108135446Strhodes rdataset->private5 = NULL; 109135446Strhodes} 110135446Strhodes 111135446Strhodesvoid 112135446Strhodesdns_rdataset_disassociate(dns_rdataset_t *rdataset) { 113135446Strhodes 114135446Strhodes /* 115135446Strhodes * Disassociate 'rdataset' from its rdata, allowing it to be reused. 116135446Strhodes */ 117135446Strhodes 118135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 119135446Strhodes REQUIRE(rdataset->methods != NULL); 120135446Strhodes 121135446Strhodes (rdataset->methods->disassociate)(rdataset); 122135446Strhodes rdataset->methods = NULL; 123135446Strhodes ISC_LINK_INIT(rdataset, link); 124135446Strhodes rdataset->rdclass = 0; 125135446Strhodes rdataset->type = 0; 126135446Strhodes rdataset->ttl = 0; 127135446Strhodes rdataset->trust = 0; 128135446Strhodes rdataset->covers = 0; 129135446Strhodes rdataset->attributes = 0; 130135446Strhodes rdataset->count = ISC_UINT32_MAX; 131135446Strhodes rdataset->private1 = NULL; 132135446Strhodes rdataset->private2 = NULL; 133135446Strhodes rdataset->private3 = NULL; 134135446Strhodes rdataset->privateuint4 = 0; 135135446Strhodes rdataset->private5 = NULL; 136135446Strhodes rdataset->private6 = NULL; 137135446Strhodes} 138135446Strhodes 139135446Strhodesisc_boolean_t 140135446Strhodesdns_rdataset_isassociated(dns_rdataset_t *rdataset) { 141135446Strhodes /* 142135446Strhodes * Is 'rdataset' associated? 143135446Strhodes */ 144135446Strhodes 145135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 146135446Strhodes 147135446Strhodes if (rdataset->methods != NULL) 148135446Strhodes return (ISC_TRUE); 149135446Strhodes 150135446Strhodes return (ISC_FALSE); 151135446Strhodes} 152135446Strhodes 153135446Strhodesstatic void 154135446Strhodesquestion_disassociate(dns_rdataset_t *rdataset) { 155135446Strhodes UNUSED(rdataset); 156135446Strhodes} 157135446Strhodes 158135446Strhodesstatic isc_result_t 159135446Strhodesquestion_cursor(dns_rdataset_t *rdataset) { 160135446Strhodes UNUSED(rdataset); 161193149Sdougb 162135446Strhodes return (ISC_R_NOMORE); 163135446Strhodes} 164135446Strhodes 165135446Strhodesstatic void 166135446Strhodesquestion_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 167135446Strhodes /* 168135446Strhodes * This routine should never be called. 169135446Strhodes */ 170135446Strhodes UNUSED(rdataset); 171135446Strhodes UNUSED(rdata); 172193149Sdougb 173135446Strhodes REQUIRE(0); 174135446Strhodes} 175135446Strhodes 176135446Strhodesstatic void 177135446Strhodesquestion_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 178135446Strhodes *target = *source; 179135446Strhodes} 180135446Strhodes 181135446Strhodesstatic unsigned int 182135446Strhodesquestion_count(dns_rdataset_t *rdataset) { 183135446Strhodes /* 184135446Strhodes * This routine should never be called. 185135446Strhodes */ 186135446Strhodes UNUSED(rdataset); 187135446Strhodes REQUIRE(0); 188135446Strhodes 189135446Strhodes return (0); 190135446Strhodes} 191135446Strhodes 192135446Strhodesstatic dns_rdatasetmethods_t question_methods = { 193135446Strhodes question_disassociate, 194135446Strhodes question_cursor, 195135446Strhodes question_cursor, 196135446Strhodes question_current, 197135446Strhodes question_clone, 198135446Strhodes question_count, 199135446Strhodes NULL, 200170222Sdougb NULL, 201170222Sdougb NULL, 202170222Sdougb NULL, 203193149Sdougb NULL, 204193149Sdougb NULL, 205205292Sdougb NULL, 206205292Sdougb NULL, 207135446Strhodes NULL 208135446Strhodes}; 209135446Strhodes 210135446Strhodesvoid 211135446Strhodesdns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass, 212135446Strhodes dns_rdatatype_t type) 213135446Strhodes{ 214135446Strhodes 215135446Strhodes /* 216135446Strhodes * Make 'rdataset' a valid, associated, question rdataset, with a 217135446Strhodes * question class of 'rdclass' and type 'type'. 218135446Strhodes */ 219135446Strhodes 220135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 221135446Strhodes REQUIRE(rdataset->methods == NULL); 222135446Strhodes 223135446Strhodes rdataset->methods = &question_methods; 224135446Strhodes rdataset->rdclass = rdclass; 225135446Strhodes rdataset->type = type; 226135446Strhodes rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 227135446Strhodes} 228135446Strhodes 229135446Strhodesunsigned int 230135446Strhodesdns_rdataset_count(dns_rdataset_t *rdataset) { 231135446Strhodes 232135446Strhodes /* 233135446Strhodes * Return the number of records in 'rdataset'. 234135446Strhodes */ 235135446Strhodes 236135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 237135446Strhodes REQUIRE(rdataset->methods != NULL); 238135446Strhodes 239135446Strhodes return ((rdataset->methods->count)(rdataset)); 240135446Strhodes} 241135446Strhodes 242135446Strhodesvoid 243135446Strhodesdns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 244135446Strhodes 245135446Strhodes /* 246135446Strhodes * Make 'target' refer to the same rdataset as 'source'. 247135446Strhodes */ 248135446Strhodes 249135446Strhodes REQUIRE(DNS_RDATASET_VALID(source)); 250135446Strhodes REQUIRE(source->methods != NULL); 251135446Strhodes REQUIRE(DNS_RDATASET_VALID(target)); 252135446Strhodes REQUIRE(target->methods == NULL); 253135446Strhodes 254135446Strhodes (source->methods->clone)(source, target); 255135446Strhodes} 256135446Strhodes 257135446Strhodesisc_result_t 258135446Strhodesdns_rdataset_first(dns_rdataset_t *rdataset) { 259135446Strhodes 260135446Strhodes /* 261135446Strhodes * Move the rdata cursor to the first rdata in the rdataset (if any). 262135446Strhodes */ 263135446Strhodes 264135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 265135446Strhodes REQUIRE(rdataset->methods != NULL); 266135446Strhodes 267135446Strhodes return ((rdataset->methods->first)(rdataset)); 268135446Strhodes} 269135446Strhodes 270135446Strhodesisc_result_t 271135446Strhodesdns_rdataset_next(dns_rdataset_t *rdataset) { 272135446Strhodes 273135446Strhodes /* 274135446Strhodes * Move the rdata cursor to the next rdata in the rdataset (if any). 275135446Strhodes */ 276135446Strhodes 277135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 278135446Strhodes REQUIRE(rdataset->methods != NULL); 279135446Strhodes 280135446Strhodes return ((rdataset->methods->next)(rdataset)); 281135446Strhodes} 282135446Strhodes 283135446Strhodesvoid 284135446Strhodesdns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 285135446Strhodes 286135446Strhodes /* 287135446Strhodes * Make 'rdata' refer to the current rdata. 288135446Strhodes */ 289135446Strhodes 290135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 291135446Strhodes REQUIRE(rdataset->methods != NULL); 292135446Strhodes 293135446Strhodes (rdataset->methods->current)(rdataset, rdata); 294135446Strhodes} 295135446Strhodes 296135446Strhodes#define MAX_SHUFFLE 32 297135446Strhodes#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0) 298135446Strhodes#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0) 299135446Strhodes 300135446Strhodesstruct towire_sort { 301135446Strhodes int key; 302135446Strhodes dns_rdata_t *rdata; 303135446Strhodes}; 304135446Strhodes 305135446Strhodesstatic int 306135446Strhodestowire_compare(const void *av, const void *bv) { 307135446Strhodes const struct towire_sort *a = (const struct towire_sort *) av; 308135446Strhodes const struct towire_sort *b = (const struct towire_sort *) bv; 309135446Strhodes return (a->key - b->key); 310135446Strhodes} 311135446Strhodes 312135446Strhodesstatic isc_result_t 313165071Sdougbtowiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, 314135446Strhodes dns_compress_t *cctx, isc_buffer_t *target, 315165071Sdougb dns_rdatasetorderfunc_t order, const void *order_arg, 316135446Strhodes isc_boolean_t partial, unsigned int options, 317135446Strhodes unsigned int *countp, void **state) 318135446Strhodes{ 319135446Strhodes dns_rdata_t rdata = DNS_RDATA_INIT; 320135446Strhodes isc_region_t r; 321135446Strhodes isc_result_t result; 322225361Sdougb unsigned int i, count = 0, added, choice; 323135446Strhodes isc_buffer_t savedbuffer, rdlen, rrbuffer; 324135446Strhodes unsigned int headlen; 325135446Strhodes isc_boolean_t question = ISC_FALSE; 326135446Strhodes isc_boolean_t shuffle = ISC_FALSE; 327135446Strhodes dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE]; 328135446Strhodes struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE]; 329135446Strhodes 330135446Strhodes UNUSED(state); 331135446Strhodes 332135446Strhodes /* 333135446Strhodes * Convert 'rdataset' to wire format, compressing names as specified 334135446Strhodes * in cctx, and storing the result in 'target'. 335135446Strhodes */ 336135446Strhodes 337135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 338135446Strhodes REQUIRE(countp != NULL); 339135446Strhodes REQUIRE((order == NULL) == (order_arg == NULL)); 340135446Strhodes REQUIRE(cctx != NULL && cctx->mctx != NULL); 341135446Strhodes 342135446Strhodes if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) { 343135446Strhodes question = ISC_TRUE; 344135446Strhodes count = 1; 345135446Strhodes result = dns_rdataset_first(rdataset); 346135446Strhodes INSIST(result == ISC_R_NOMORE); 347223812Sdougb } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { 348135446Strhodes /* 349135446Strhodes * This is a negative caching rdataset. 350135446Strhodes */ 351135446Strhodes unsigned int ncache_opts = 0; 352135446Strhodes if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0) 353135446Strhodes ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC; 354135446Strhodes return (dns_ncache_towire(rdataset, cctx, target, ncache_opts, 355135446Strhodes countp)); 356135446Strhodes } else { 357135446Strhodes count = (rdataset->methods->count)(rdataset); 358135446Strhodes result = dns_rdataset_first(rdataset); 359135446Strhodes if (result == ISC_R_NOMORE) 360135446Strhodes return (ISC_R_SUCCESS); 361135446Strhodes if (result != ISC_R_SUCCESS) 362135446Strhodes return (result); 363135446Strhodes } 364135446Strhodes 365135446Strhodes /* 366193149Sdougb * Do we want to shuffle this answer? 367135446Strhodes */ 368135446Strhodes if (!question && count > 1 && 369135446Strhodes (!WANT_FIXED(rdataset) || order != NULL) && 370135446Strhodes rdataset->type != dns_rdatatype_rrsig) 371135446Strhodes shuffle = ISC_TRUE; 372135446Strhodes 373135446Strhodes if (shuffle && count > MAX_SHUFFLE) { 374135446Strhodes shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled)); 375135446Strhodes sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted)); 376135446Strhodes if (shuffled == NULL || sorted == NULL) 377135446Strhodes shuffle = ISC_FALSE; 378135446Strhodes } else { 379135446Strhodes shuffled = shuffled_fixed; 380135446Strhodes sorted = sorted_fixed; 381135446Strhodes } 382135446Strhodes 383135446Strhodes if (shuffle) { 384135446Strhodes /* 385135446Strhodes * First we get handles to all of the rdata. 386135446Strhodes */ 387135446Strhodes i = 0; 388135446Strhodes do { 389135446Strhodes INSIST(i < count); 390135446Strhodes dns_rdata_init(&shuffled[i]); 391135446Strhodes dns_rdataset_current(rdataset, &shuffled[i]); 392135446Strhodes i++; 393135446Strhodes result = dns_rdataset_next(rdataset); 394135446Strhodes } while (result == ISC_R_SUCCESS); 395135446Strhodes if (result != ISC_R_NOMORE) 396135446Strhodes goto cleanup; 397135446Strhodes INSIST(i == count); 398135446Strhodes 399135446Strhodes /* 400135446Strhodes * Now we shuffle. 401135446Strhodes */ 402135446Strhodes if (WANT_FIXED(rdataset)) { 403135446Strhodes /* 404135446Strhodes * 'Fixed' order. 405135446Strhodes */ 406135446Strhodes INSIST(order != NULL); 407135446Strhodes for (i = 0; i < count; i++) { 408135446Strhodes sorted[i].key = (*order)(&shuffled[i], 409135446Strhodes order_arg); 410135446Strhodes sorted[i].rdata = &shuffled[i]; 411135446Strhodes } 412135446Strhodes } else if (WANT_RANDOM(rdataset)) { 413135446Strhodes /* 414135446Strhodes * 'Random' order. 415135446Strhodes */ 416135446Strhodes for (i = 0; i < count; i++) { 417135446Strhodes dns_rdata_t rdata; 418135446Strhodes isc_uint32_t val; 419135446Strhodes 420135446Strhodes isc_random_get(&val); 421135446Strhodes choice = i + (val % (count - i)); 422135446Strhodes rdata = shuffled[i]; 423135446Strhodes shuffled[i] = shuffled[choice]; 424135446Strhodes shuffled[choice] = rdata; 425135446Strhodes if (order != NULL) 426135446Strhodes sorted[i].key = (*order)(&shuffled[i], 427135446Strhodes order_arg); 428135446Strhodes else 429135446Strhodes sorted[i].key = 0; /* Unused */ 430135446Strhodes sorted[i].rdata = &shuffled[i]; 431135446Strhodes } 432135446Strhodes } else { 433135446Strhodes /* 434135446Strhodes * "Cyclic" order. 435135446Strhodes */ 436135446Strhodes isc_uint32_t val; 437135446Strhodes unsigned int j; 438135446Strhodes 439135446Strhodes val = rdataset->count; 440135446Strhodes if (val == ISC_UINT32_MAX) 441135446Strhodes isc_random_get(&val); 442135446Strhodes j = val % count; 443135446Strhodes for (i = 0; i < count; i++) { 444135446Strhodes if (order != NULL) 445135446Strhodes sorted[j].key = (*order)(&shuffled[i], 446135446Strhodes order_arg); 447135446Strhodes else 448135446Strhodes sorted[j].key = 0; /* Unused */ 449135446Strhodes sorted[j].rdata = &shuffled[i]; 450135446Strhodes j++; 451135446Strhodes if (j == count) 452135446Strhodes j = 0; /* Wrap around. */ 453135446Strhodes } 454135446Strhodes } 455135446Strhodes 456135446Strhodes /* 457135446Strhodes * Sorted order. 458135446Strhodes */ 459135446Strhodes if (order != NULL) 460135446Strhodes qsort(sorted, count, sizeof(sorted[0]), 461135446Strhodes towire_compare); 462135446Strhodes } 463135446Strhodes 464135446Strhodes savedbuffer = *target; 465135446Strhodes i = 0; 466135446Strhodes added = 0; 467135446Strhodes 468135446Strhodes do { 469135446Strhodes /* 470135446Strhodes * Copy out the name, type, class, ttl. 471135446Strhodes */ 472193149Sdougb 473135446Strhodes rrbuffer = *target; 474135446Strhodes dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); 475135446Strhodes result = dns_name_towire(owner_name, cctx, target); 476135446Strhodes if (result != ISC_R_SUCCESS) 477135446Strhodes goto rollback; 478135446Strhodes headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t); 479135446Strhodes if (!question) 480135446Strhodes headlen += sizeof(dns_ttl_t) 481135446Strhodes + 2; /* XXX 2 for rdata len */ 482135446Strhodes isc_buffer_availableregion(target, &r); 483135446Strhodes if (r.length < headlen) { 484135446Strhodes result = ISC_R_NOSPACE; 485135446Strhodes goto rollback; 486135446Strhodes } 487135446Strhodes isc_buffer_putuint16(target, rdataset->type); 488135446Strhodes isc_buffer_putuint16(target, rdataset->rdclass); 489135446Strhodes if (!question) { 490135446Strhodes isc_buffer_putuint32(target, rdataset->ttl); 491135446Strhodes 492135446Strhodes /* 493135446Strhodes * Save space for rdlen. 494135446Strhodes */ 495135446Strhodes rdlen = *target; 496135446Strhodes isc_buffer_add(target, 2); 497135446Strhodes 498135446Strhodes /* 499135446Strhodes * Copy out the rdata 500135446Strhodes */ 501135446Strhodes if (shuffle) 502135446Strhodes rdata = *(sorted[i].rdata); 503135446Strhodes else { 504135446Strhodes dns_rdata_reset(&rdata); 505135446Strhodes dns_rdataset_current(rdataset, &rdata); 506135446Strhodes } 507135446Strhodes result = dns_rdata_towire(&rdata, cctx, target); 508135446Strhodes if (result != ISC_R_SUCCESS) 509135446Strhodes goto rollback; 510135446Strhodes INSIST((target->used >= rdlen.used + 2) && 511135446Strhodes (target->used - rdlen.used - 2 < 65536)); 512135446Strhodes isc_buffer_putuint16(&rdlen, 513135446Strhodes (isc_uint16_t)(target->used - 514135446Strhodes rdlen.used - 2)); 515135446Strhodes added++; 516135446Strhodes } 517135446Strhodes 518135446Strhodes if (shuffle) { 519135446Strhodes i++; 520135446Strhodes if (i == count) 521135446Strhodes result = ISC_R_NOMORE; 522135446Strhodes else 523135446Strhodes result = ISC_R_SUCCESS; 524135446Strhodes } else { 525135446Strhodes result = dns_rdataset_next(rdataset); 526135446Strhodes } 527135446Strhodes } while (result == ISC_R_SUCCESS); 528135446Strhodes 529135446Strhodes if (result != ISC_R_NOMORE) 530135446Strhodes goto rollback; 531135446Strhodes 532135446Strhodes *countp += count; 533135446Strhodes 534135446Strhodes result = ISC_R_SUCCESS; 535135446Strhodes goto cleanup; 536135446Strhodes 537135446Strhodes rollback: 538135446Strhodes if (partial && result == ISC_R_NOSPACE) { 539135446Strhodes INSIST(rrbuffer.used < 65536); 540135446Strhodes dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used); 541135446Strhodes *countp += added; 542135446Strhodes *target = rrbuffer; 543135446Strhodes goto cleanup; 544135446Strhodes } 545135446Strhodes INSIST(savedbuffer.used < 65536); 546135446Strhodes dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); 547135446Strhodes *countp = 0; 548135446Strhodes *target = savedbuffer; 549135446Strhodes 550135446Strhodes cleanup: 551135446Strhodes if (sorted != NULL && sorted != sorted_fixed) 552135446Strhodes isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted)); 553135446Strhodes if (shuffled != NULL && shuffled != shuffled_fixed) 554135446Strhodes isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled)); 555135446Strhodes return (result); 556135446Strhodes} 557135446Strhodes 558135446Strhodesisc_result_t 559135446Strhodesdns_rdataset_towiresorted(dns_rdataset_t *rdataset, 560165071Sdougb const dns_name_t *owner_name, 561135446Strhodes dns_compress_t *cctx, 562135446Strhodes isc_buffer_t *target, 563135446Strhodes dns_rdatasetorderfunc_t order, 564165071Sdougb const void *order_arg, 565135446Strhodes unsigned int options, 566135446Strhodes unsigned int *countp) 567135446Strhodes{ 568135446Strhodes return (towiresorted(rdataset, owner_name, cctx, target, 569135446Strhodes order, order_arg, ISC_FALSE, options, 570135446Strhodes countp, NULL)); 571135446Strhodes} 572135446Strhodes 573135446Strhodesisc_result_t 574135446Strhodesdns_rdataset_towirepartial(dns_rdataset_t *rdataset, 575165071Sdougb const dns_name_t *owner_name, 576135446Strhodes dns_compress_t *cctx, 577135446Strhodes isc_buffer_t *target, 578135446Strhodes dns_rdatasetorderfunc_t order, 579165071Sdougb const void *order_arg, 580135446Strhodes unsigned int options, 581135446Strhodes unsigned int *countp, 582135446Strhodes void **state) 583135446Strhodes{ 584135446Strhodes REQUIRE(state == NULL); /* XXX remove when implemented */ 585135446Strhodes return (towiresorted(rdataset, owner_name, cctx, target, 586135446Strhodes order, order_arg, ISC_TRUE, options, 587135446Strhodes countp, state)); 588135446Strhodes} 589135446Strhodes 590135446Strhodesisc_result_t 591135446Strhodesdns_rdataset_towire(dns_rdataset_t *rdataset, 592135446Strhodes dns_name_t *owner_name, 593135446Strhodes dns_compress_t *cctx, 594135446Strhodes isc_buffer_t *target, 595135446Strhodes unsigned int options, 596135446Strhodes unsigned int *countp) 597135446Strhodes{ 598135446Strhodes return (towiresorted(rdataset, owner_name, cctx, target, 599135446Strhodes NULL, NULL, ISC_FALSE, options, countp, NULL)); 600135446Strhodes} 601135446Strhodes 602135446Strhodesisc_result_t 603135446Strhodesdns_rdataset_additionaldata(dns_rdataset_t *rdataset, 604135446Strhodes dns_additionaldatafunc_t add, void *arg) 605135446Strhodes{ 606135446Strhodes dns_rdata_t rdata = DNS_RDATA_INIT; 607135446Strhodes isc_result_t result; 608135446Strhodes 609135446Strhodes /* 610135446Strhodes * For each rdata in rdataset, call 'add' for each name and type in the 611135446Strhodes * rdata which is subject to additional section processing. 612135446Strhodes */ 613135446Strhodes 614135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 615135446Strhodes REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0); 616135446Strhodes 617135446Strhodes result = dns_rdataset_first(rdataset); 618135446Strhodes if (result != ISC_R_SUCCESS) 619135446Strhodes return (result); 620135446Strhodes 621135446Strhodes do { 622135446Strhodes dns_rdataset_current(rdataset, &rdata); 623135446Strhodes result = dns_rdata_additionaldata(&rdata, add, arg); 624135446Strhodes if (result == ISC_R_SUCCESS) 625135446Strhodes result = dns_rdataset_next(rdataset); 626135446Strhodes dns_rdata_reset(&rdata); 627135446Strhodes } while (result == ISC_R_SUCCESS); 628135446Strhodes 629135446Strhodes if (result != ISC_R_NOMORE) 630135446Strhodes return (result); 631135446Strhodes 632135446Strhodes return (ISC_R_SUCCESS); 633135446Strhodes} 634135446Strhodes 635135446Strhodesisc_result_t 636135446Strhodesdns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) { 637135446Strhodes 638135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 639135446Strhodes REQUIRE(rdataset->methods != NULL); 640135446Strhodes if (rdataset->methods->addnoqname == NULL) 641135446Strhodes return (ISC_R_NOTIMPLEMENTED); 642135446Strhodes return((rdataset->methods->addnoqname)(rdataset, name)); 643135446Strhodes} 644135446Strhodes 645135446Strhodesisc_result_t 646135446Strhodesdns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, 647193149Sdougb dns_rdataset_t *neg, dns_rdataset_t *negsig) 648135446Strhodes{ 649135446Strhodes REQUIRE(DNS_RDATASET_VALID(rdataset)); 650135446Strhodes REQUIRE(rdataset->methods != NULL); 651135446Strhodes 652135446Strhodes if (rdataset->methods->getnoqname == NULL) 653135446Strhodes return (ISC_R_NOTIMPLEMENTED); 654193149Sdougb return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig)); 655135446Strhodes} 656170222Sdougb 657193149Sdougbisc_result_t 658193149Sdougbdns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) { 659193149Sdougb 660193149Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 661193149Sdougb REQUIRE(rdataset->methods != NULL); 662193149Sdougb if (rdataset->methods->addclosest == NULL) 663193149Sdougb return (ISC_R_NOTIMPLEMENTED); 664193149Sdougb return((rdataset->methods->addclosest)(rdataset, name)); 665193149Sdougb} 666193149Sdougb 667193149Sdougbisc_result_t 668193149Sdougbdns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, 669193149Sdougb dns_rdataset_t *neg, dns_rdataset_t *negsig) 670193149Sdougb{ 671193149Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 672193149Sdougb REQUIRE(rdataset->methods != NULL); 673193149Sdougb 674193149Sdougb if (rdataset->methods->getclosest == NULL) 675193149Sdougb return (ISC_R_NOTIMPLEMENTED); 676193149Sdougb return((rdataset->methods->getclosest)(rdataset, name, neg, negsig)); 677193149Sdougb} 678193149Sdougb 679170222Sdougb/* 680170222Sdougb * Additional cache stuff 681170222Sdougb */ 682170222Sdougbisc_result_t 683170222Sdougbdns_rdataset_getadditional(dns_rdataset_t *rdataset, 684170222Sdougb dns_rdatasetadditional_t type, 685170222Sdougb dns_rdatatype_t qtype, 686170222Sdougb dns_acache_t *acache, 687170222Sdougb dns_zone_t **zonep, 688170222Sdougb dns_db_t **dbp, 689170222Sdougb dns_dbversion_t **versionp, 690170222Sdougb dns_dbnode_t **nodep, 691170222Sdougb dns_name_t *fname, 692170222Sdougb dns_message_t *msg, 693170222Sdougb isc_stdtime_t now) 694170222Sdougb{ 695170222Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 696170222Sdougb REQUIRE(rdataset->methods != NULL); 697170222Sdougb REQUIRE(zonep == NULL || *zonep == NULL); 698170222Sdougb REQUIRE(dbp != NULL && *dbp == NULL); 699170222Sdougb REQUIRE(versionp != NULL && *versionp == NULL); 700170222Sdougb REQUIRE(nodep != NULL && *nodep == NULL); 701170222Sdougb REQUIRE(fname != NULL); 702170222Sdougb REQUIRE(msg != NULL); 703170222Sdougb 704170222Sdougb if (acache != NULL && rdataset->methods->getadditional != NULL) { 705170222Sdougb return ((rdataset->methods->getadditional)(rdataset, type, 706170222Sdougb qtype, acache, 707170222Sdougb zonep, dbp, 708170222Sdougb versionp, nodep, 709170222Sdougb fname, msg, now)); 710170222Sdougb } 711170222Sdougb 712170222Sdougb return (ISC_R_FAILURE); 713170222Sdougb} 714170222Sdougb 715170222Sdougbisc_result_t 716170222Sdougbdns_rdataset_setadditional(dns_rdataset_t *rdataset, 717170222Sdougb dns_rdatasetadditional_t type, 718170222Sdougb dns_rdatatype_t qtype, 719170222Sdougb dns_acache_t *acache, 720170222Sdougb dns_zone_t *zone, 721170222Sdougb dns_db_t *db, 722170222Sdougb dns_dbversion_t *version, 723170222Sdougb dns_dbnode_t *node, 724170222Sdougb dns_name_t *fname) 725170222Sdougb{ 726170222Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 727170222Sdougb REQUIRE(rdataset->methods != NULL); 728170222Sdougb 729170222Sdougb if (acache != NULL && rdataset->methods->setadditional != NULL) { 730170222Sdougb return ((rdataset->methods->setadditional)(rdataset, type, 731170222Sdougb qtype, acache, zone, 732170222Sdougb db, version, 733170222Sdougb node, fname)); 734170222Sdougb } 735170222Sdougb 736170222Sdougb return (ISC_R_FAILURE); 737170222Sdougb} 738170222Sdougb 739170222Sdougbisc_result_t 740170222Sdougbdns_rdataset_putadditional(dns_acache_t *acache, 741170222Sdougb dns_rdataset_t *rdataset, 742170222Sdougb dns_rdatasetadditional_t type, 743170222Sdougb dns_rdatatype_t qtype) 744170222Sdougb{ 745170222Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 746170222Sdougb REQUIRE(rdataset->methods != NULL); 747170222Sdougb 748170222Sdougb if (acache != NULL && rdataset->methods->putadditional != NULL) { 749170222Sdougb return ((rdataset->methods->putadditional)(acache, rdataset, 750170222Sdougb type, qtype)); 751170222Sdougb } 752170222Sdougb 753170222Sdougb return (ISC_R_FAILURE); 754170222Sdougb} 755170222Sdougb 756205292Sdougbvoid 757205292Sdougbdns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { 758205292Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 759205292Sdougb REQUIRE(rdataset->methods != NULL); 760205292Sdougb 761205292Sdougb if (rdataset->methods->settrust != NULL) 762205292Sdougb (rdataset->methods->settrust)(rdataset, trust); 763205292Sdougb else 764205292Sdougb rdataset->trust = trust; 765205292Sdougb} 766205292Sdougb 767205292Sdougbvoid 768205292Sdougbdns_rdataset_expire(dns_rdataset_t *rdataset) { 769205292Sdougb REQUIRE(DNS_RDATASET_VALID(rdataset)); 770205292Sdougb REQUIRE(rdataset->methods != NULL); 771205292Sdougb 772205292Sdougb if (rdataset->methods->expire != NULL) 773205292Sdougb (rdataset->methods->expire)(rdataset); 774205292Sdougb} 775