rdataset.c revision 193149
1181641Skmacy/* 2181641Skmacy * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 3181641Skmacy * Copyright (C) 1999-2003 Internet Software Consortium. 4181641Skmacy * 5181641Skmacy * Permission to use, copy, modify, and/or distribute this software for any 6181641Skmacy * purpose with or without fee is hereby granted, provided that the above 7181641Skmacy * copyright notice and this permission notice appear in all copies. 8181641Skmacy * 9181641Skmacy * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10181641Skmacy * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11181641Skmacy * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12181641Skmacy * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13181641Skmacy * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14181641Skmacy * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15181641Skmacy * PERFORMANCE OF THIS SOFTWARE. 16181641Skmacy */ 17181641Skmacy 18181641Skmacy/* $Id: rdataset.c,v 1.82.50.2 2009/01/18 23:47:40 tbox Exp $ */ 19181641Skmacy 20181641Skmacy/*! \file */ 21181641Skmacy 22181641Skmacy#include <config.h> 23181641Skmacy 24181641Skmacy#include <stdlib.h> 25181641Skmacy 26181641Skmacy#include <isc/buffer.h> 27181641Skmacy#include <isc/mem.h> 28181641Skmacy#include <isc/random.h> 29181641Skmacy#include <isc/util.h> 30181641Skmacy 31181641Skmacy#include <dns/name.h> 32181641Skmacy#include <dns/ncache.h> 33181641Skmacy#include <dns/rdata.h> 34181641Skmacy#include <dns/rdataset.h> 35181641Skmacy#include <dns/compress.h> 36181641Skmacy 37181641Skmacyvoid 38181641Skmacydns_rdataset_init(dns_rdataset_t *rdataset) { 39181641Skmacy 40181641Skmacy /* 41181641Skmacy * Make 'rdataset' a valid, disassociated rdataset. 42181641Skmacy */ 43181641Skmacy 44181641Skmacy REQUIRE(rdataset != NULL); 45181641Skmacy 46181641Skmacy rdataset->magic = DNS_RDATASET_MAGIC; 47181641Skmacy rdataset->methods = NULL; 48181641Skmacy ISC_LINK_INIT(rdataset, link); 49181641Skmacy rdataset->rdclass = 0; 50181641Skmacy rdataset->type = 0; 51181641Skmacy rdataset->ttl = 0; 52181641Skmacy rdataset->trust = 0; 53181641Skmacy rdataset->covers = 0; 54181641Skmacy rdataset->attributes = 0; 55181641Skmacy rdataset->count = ISC_UINT32_MAX; 56181641Skmacy rdataset->private1 = NULL; 57181641Skmacy rdataset->private2 = NULL; 58181641Skmacy rdataset->private3 = NULL; 59181641Skmacy rdataset->privateuint4 = 0; 60181641Skmacy rdataset->private5 = NULL; 61181641Skmacy rdataset->private6 = NULL; 62181641Skmacy rdataset->resign = 0; 63181641Skmacy} 64181641Skmacy 65181641Skmacyvoid 66181641Skmacydns_rdataset_invalidate(dns_rdataset_t *rdataset) { 67181641Skmacy 68181641Skmacy /* 69181641Skmacy * Invalidate 'rdataset'. 70181641Skmacy */ 71181641Skmacy 72181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 73181641Skmacy REQUIRE(rdataset->methods == NULL); 74181641Skmacy 75181641Skmacy rdataset->magic = 0; 76181641Skmacy ISC_LINK_INIT(rdataset, link); 77181641Skmacy rdataset->rdclass = 0; 78181641Skmacy rdataset->type = 0; 79181641Skmacy rdataset->ttl = 0; 80181641Skmacy rdataset->trust = 0; 81181641Skmacy rdataset->covers = 0; 82181641Skmacy rdataset->attributes = 0; 83181641Skmacy rdataset->count = ISC_UINT32_MAX; 84181641Skmacy rdataset->private1 = NULL; 85181641Skmacy rdataset->private2 = NULL; 86181641Skmacy rdataset->private3 = NULL; 87181641Skmacy rdataset->privateuint4 = 0; 88181641Skmacy rdataset->private5 = NULL; 89181641Skmacy} 90181641Skmacy 91181641Skmacyvoid 92181641Skmacydns_rdataset_disassociate(dns_rdataset_t *rdataset) { 93181641Skmacy 94181641Skmacy /* 95181641Skmacy * Disassociate 'rdataset' from its rdata, allowing it to be reused. 96181641Skmacy */ 97181641Skmacy 98181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 99181641Skmacy REQUIRE(rdataset->methods != NULL); 100181641Skmacy 101181641Skmacy (rdataset->methods->disassociate)(rdataset); 102181641Skmacy rdataset->methods = NULL; 103181641Skmacy ISC_LINK_INIT(rdataset, link); 104181641Skmacy rdataset->rdclass = 0; 105181641Skmacy rdataset->type = 0; 106181641Skmacy rdataset->ttl = 0; 107181641Skmacy rdataset->trust = 0; 108181641Skmacy rdataset->covers = 0; 109181641Skmacy rdataset->attributes = 0; 110181641Skmacy rdataset->count = ISC_UINT32_MAX; 111181641Skmacy rdataset->private1 = NULL; 112181641Skmacy rdataset->private2 = NULL; 113181641Skmacy rdataset->private3 = NULL; 114181641Skmacy rdataset->privateuint4 = 0; 115181641Skmacy rdataset->private5 = NULL; 116181641Skmacy rdataset->private6 = NULL; 117181641Skmacy} 118181641Skmacy 119181641Skmacyisc_boolean_t 120181641Skmacydns_rdataset_isassociated(dns_rdataset_t *rdataset) { 121181641Skmacy /* 122195949Skib * Is 'rdataset' associated? 123181641Skmacy */ 124181641Skmacy 125181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 126181641Skmacy 127181641Skmacy if (rdataset->methods != NULL) 128181641Skmacy return (ISC_TRUE); 129181641Skmacy 130181641Skmacy return (ISC_FALSE); 131181641Skmacy} 132181641Skmacy 133181641Skmacystatic void 134181641Skmacyquestion_disassociate(dns_rdataset_t *rdataset) { 135181641Skmacy UNUSED(rdataset); 136181641Skmacy} 137181641Skmacy 138181641Skmacystatic isc_result_t 139181641Skmacyquestion_cursor(dns_rdataset_t *rdataset) { 140181641Skmacy UNUSED(rdataset); 141181641Skmacy 142181641Skmacy return (ISC_R_NOMORE); 143181641Skmacy} 144181641Skmacy 145181641Skmacystatic void 146181641Skmacyquestion_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 147181641Skmacy /* 148181641Skmacy * This routine should never be called. 149181641Skmacy */ 150181641Skmacy UNUSED(rdataset); 151181641Skmacy UNUSED(rdata); 152181641Skmacy 153181641Skmacy REQUIRE(0); 154181641Skmacy} 155181641Skmacy 156186557Skmacystatic void 157181641Skmacyquestion_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 158181641Skmacy *target = *source; 159181641Skmacy} 160181641Skmacy 161181641Skmacystatic unsigned int 162181641Skmacyquestion_count(dns_rdataset_t *rdataset) { 163181641Skmacy /* 164181641Skmacy * This routine should never be called. 165181641Skmacy */ 166181641Skmacy UNUSED(rdataset); 167181641Skmacy REQUIRE(0); 168181641Skmacy 169208651Salc return (0); 170181641Skmacy} 171208651Salc 172204041Sedstatic dns_rdatasetmethods_t question_methods = { 173208651Salc question_disassociate, 174204041Sed question_cursor, 175202628Sed question_cursor, 176204041Sed question_current, 177181641Skmacy question_clone, 178181641Skmacy question_count, 179181641Skmacy NULL, 180181641Skmacy NULL, 181181641Skmacy NULL, 182181641Skmacy NULL, 183181641Skmacy NULL, 184181641Skmacy NULL, 185181641Skmacy NULL 186181641Skmacy}; 187181641Skmacy 188181747Skmacyvoid 189181747Skmacydns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass, 190181747Skmacy dns_rdatatype_t type) 191181641Skmacy{ 192181641Skmacy 193181641Skmacy /* 194181641Skmacy * Make 'rdataset' a valid, associated, question rdataset, with a 195181641Skmacy * question class of 'rdclass' and type 'type'. 196181641Skmacy */ 197181641Skmacy 198181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 199181641Skmacy REQUIRE(rdataset->methods == NULL); 200181641Skmacy 201181641Skmacy rdataset->methods = &question_methods; 202181641Skmacy rdataset->rdclass = rdclass; 203181641Skmacy rdataset->type = type; 204181641Skmacy rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 205181641Skmacy} 206181641Skmacy 207181641Skmacyunsigned int 208181641Skmacydns_rdataset_count(dns_rdataset_t *rdataset) { 209181641Skmacy 210181641Skmacy /* 211181641Skmacy * Return the number of records in 'rdataset'. 212181641Skmacy */ 213181641Skmacy 214181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 215182902Skmacy REQUIRE(rdataset->methods != NULL); 216181641Skmacy 217181641Skmacy return ((rdataset->methods->count)(rdataset)); 218181641Skmacy} 219181641Skmacy 220181641Skmacyvoid 221181641Skmacydns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 222181641Skmacy 223196726Sadrian /* 224196726Sadrian * Make 'target' refer to the same rdataset as 'source'. 225181641Skmacy */ 226181641Skmacy 227181641Skmacy REQUIRE(DNS_RDATASET_VALID(source)); 228181641Skmacy REQUIRE(source->methods != NULL); 229181747Skmacy REQUIRE(DNS_RDATASET_VALID(target)); 230181641Skmacy REQUIRE(target->methods == NULL); 231181641Skmacy 232181641Skmacy (source->methods->clone)(source, target); 233181641Skmacy} 234181641Skmacy 235181641Skmacyisc_result_t 236181641Skmacydns_rdataset_first(dns_rdataset_t *rdataset) { 237181641Skmacy 238181641Skmacy /* 239181641Skmacy * Move the rdata cursor to the first rdata in the rdataset (if any). 240181641Skmacy */ 241181641Skmacy 242181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 243181641Skmacy REQUIRE(rdataset->methods != NULL); 244181641Skmacy 245181641Skmacy return ((rdataset->methods->first)(rdataset)); 246181641Skmacy} 247181641Skmacy 248204160Skmacyisc_result_t 249181641Skmacydns_rdataset_next(dns_rdataset_t *rdataset) { 250181641Skmacy 251181641Skmacy /* 252181641Skmacy * Move the rdata cursor to the next rdata in the rdataset (if any). 253181641Skmacy */ 254181641Skmacy 255181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 256181641Skmacy REQUIRE(rdataset->methods != NULL); 257181641Skmacy 258181641Skmacy return ((rdataset->methods->next)(rdataset)); 259181641Skmacy} 260181641Skmacy 261181641Skmacyvoid 262181641Skmacydns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 263181641Skmacy 264181641Skmacy /* 265181641Skmacy * Make 'rdata' refer to the current rdata. 266181641Skmacy */ 267181641Skmacy 268181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 269181641Skmacy REQUIRE(rdataset->methods != NULL); 270181641Skmacy 271181641Skmacy (rdataset->methods->current)(rdataset, rdata); 272181641Skmacy} 273181641Skmacy 274181641Skmacy#define MAX_SHUFFLE 32 275181641Skmacy#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0) 276181747Skmacy#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0) 277181747Skmacy 278199184Savgstruct towire_sort { 279181747Skmacy int key; 280181747Skmacy dns_rdata_t *rdata; 281181747Skmacy}; 282181747Skmacy 283181747Skmacystatic int 284181747Skmacytowire_compare(const void *av, const void *bv) { 285207419Skmacy const struct towire_sort *a = (const struct towire_sort *) av; 286207419Skmacy const struct towire_sort *b = (const struct towire_sort *) bv; 287181747Skmacy return (a->key - b->key); 288207419Skmacy} 289207419Skmacy 290207419Skmacystatic isc_result_t 291207419Skmacytowiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, 292181641Skmacy dns_compress_t *cctx, isc_buffer_t *target, 293181641Skmacy dns_rdatasetorderfunc_t order, const void *order_arg, 294208651Salc isc_boolean_t partial, unsigned int options, 295208651Salc unsigned int *countp, void **state) 296208651Salc{ 297181641Skmacy dns_rdata_t rdata = DNS_RDATA_INIT; 298181641Skmacy isc_region_t r; 299181641Skmacy isc_result_t result; 300181641Skmacy unsigned int i, count, added, choice; 301181641Skmacy isc_buffer_t savedbuffer, rdlen, rrbuffer; 302181641Skmacy unsigned int headlen; 303181641Skmacy isc_boolean_t question = ISC_FALSE; 304181641Skmacy isc_boolean_t shuffle = ISC_FALSE; 305181641Skmacy dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE]; 306181641Skmacy struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE]; 307181641Skmacy 308181641Skmacy UNUSED(state); 309181641Skmacy 310181641Skmacy /* 311181641Skmacy * Convert 'rdataset' to wire format, compressing names as specified 312181641Skmacy * in cctx, and storing the result in 'target'. 313181641Skmacy */ 314181641Skmacy 315181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 316181641Skmacy REQUIRE(countp != NULL); 317181641Skmacy REQUIRE((order == NULL) == (order_arg == NULL)); 318181747Skmacy REQUIRE(cctx != NULL && cctx->mctx != NULL); 319181641Skmacy 320196725Sadrian count = 0; 321181747Skmacy if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) { 322181641Skmacy question = ISC_TRUE; 323181641Skmacy count = 1; 324181641Skmacy result = dns_rdataset_first(rdataset); 325181641Skmacy INSIST(result == ISC_R_NOMORE); 326181641Skmacy } else if (rdataset->type == 0) { 327181641Skmacy /* 328181641Skmacy * This is a negative caching rdataset. 329181641Skmacy */ 330181641Skmacy unsigned int ncache_opts = 0; 331181641Skmacy if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0) 332181641Skmacy ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC; 333181641Skmacy return (dns_ncache_towire(rdataset, cctx, target, ncache_opts, 334181641Skmacy countp)); 335181641Skmacy } else { 336181641Skmacy count = (rdataset->methods->count)(rdataset); 337181641Skmacy result = dns_rdataset_first(rdataset); 338181641Skmacy if (result == ISC_R_NOMORE) 339181641Skmacy return (ISC_R_SUCCESS); 340181641Skmacy if (result != ISC_R_SUCCESS) 341181641Skmacy return (result); 342181641Skmacy } 343181641Skmacy 344181641Skmacy /* 345181641Skmacy * Do we want to shuffle this answer? 346181641Skmacy */ 347181641Skmacy if (!question && count > 1 && 348181641Skmacy (!WANT_FIXED(rdataset) || order != NULL) && 349181641Skmacy rdataset->type != dns_rdatatype_rrsig) 350181641Skmacy shuffle = ISC_TRUE; 351181641Skmacy 352181641Skmacy if (shuffle && count > MAX_SHUFFLE) { 353181641Skmacy shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled)); 354181641Skmacy sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted)); 355181641Skmacy if (shuffled == NULL || sorted == NULL) 356181641Skmacy shuffle = ISC_FALSE; 357181641Skmacy } else { 358181641Skmacy shuffled = shuffled_fixed; 359181641Skmacy sorted = sorted_fixed; 360181641Skmacy } 361181641Skmacy 362181641Skmacy if (shuffle) { 363181641Skmacy /* 364181641Skmacy * First we get handles to all of the rdata. 365181641Skmacy */ 366181641Skmacy i = 0; 367181641Skmacy do { 368181641Skmacy INSIST(i < count); 369181641Skmacy dns_rdata_init(&shuffled[i]); 370181641Skmacy dns_rdataset_current(rdataset, &shuffled[i]); 371181641Skmacy i++; 372181641Skmacy result = dns_rdataset_next(rdataset); 373181641Skmacy } while (result == ISC_R_SUCCESS); 374181641Skmacy if (result != ISC_R_NOMORE) 375181641Skmacy goto cleanup; 376181641Skmacy INSIST(i == count); 377181641Skmacy 378181641Skmacy /* 379181641Skmacy * Now we shuffle. 380181641Skmacy */ 381181641Skmacy if (WANT_FIXED(rdataset)) { 382181641Skmacy /* 383181641Skmacy * 'Fixed' order. 384181641Skmacy */ 385181641Skmacy INSIST(order != NULL); 386181641Skmacy for (i = 0; i < count; i++) { 387181641Skmacy sorted[i].key = (*order)(&shuffled[i], 388181641Skmacy order_arg); 389181641Skmacy sorted[i].rdata = &shuffled[i]; 390181641Skmacy } 391181641Skmacy } else if (WANT_RANDOM(rdataset)) { 392181641Skmacy /* 393181641Skmacy * 'Random' order. 394181641Skmacy */ 395181641Skmacy for (i = 0; i < count; i++) { 396181641Skmacy dns_rdata_t rdata; 397181641Skmacy isc_uint32_t val; 398181641Skmacy 399181641Skmacy isc_random_get(&val); 400181641Skmacy choice = i + (val % (count - i)); 401181641Skmacy rdata = shuffled[i]; 402181641Skmacy shuffled[i] = shuffled[choice]; 403181641Skmacy shuffled[choice] = rdata; 404181641Skmacy if (order != NULL) 405181641Skmacy sorted[i].key = (*order)(&shuffled[i], 406181641Skmacy order_arg); 407181641Skmacy else 408181641Skmacy sorted[i].key = 0; /* Unused */ 409181641Skmacy sorted[i].rdata = &shuffled[i]; 410181641Skmacy } 411181641Skmacy } else { 412181641Skmacy /* 413181641Skmacy * "Cyclic" order. 414181641Skmacy */ 415181641Skmacy isc_uint32_t val; 416181641Skmacy unsigned int j; 417181641Skmacy 418181641Skmacy val = rdataset->count; 419181641Skmacy if (val == ISC_UINT32_MAX) 420181641Skmacy isc_random_get(&val); 421181641Skmacy j = val % count; 422181641Skmacy for (i = 0; i < count; i++) { 423181641Skmacy if (order != NULL) 424181641Skmacy sorted[j].key = (*order)(&shuffled[i], 425181641Skmacy order_arg); 426181641Skmacy else 427181641Skmacy sorted[j].key = 0; /* Unused */ 428183342Skmacy sorted[j].rdata = &shuffled[i]; 429183342Skmacy j++; 430181641Skmacy if (j == count) 431181641Skmacy j = 0; /* Wrap around. */ 432181641Skmacy } 433181641Skmacy } 434181641Skmacy 435181641Skmacy /* 436181641Skmacy * Sorted order. 437181641Skmacy */ 438181641Skmacy if (order != NULL) 439181641Skmacy qsort(sorted, count, sizeof(sorted[0]), 440181641Skmacy towire_compare); 441181641Skmacy } 442181641Skmacy 443181641Skmacy savedbuffer = *target; 444181641Skmacy i = 0; 445181641Skmacy added = 0; 446181641Skmacy 447181641Skmacy do { 448181641Skmacy /* 449181641Skmacy * Copy out the name, type, class, ttl. 450204160Skmacy */ 451204160Skmacy 452181641Skmacy rrbuffer = *target; 453181641Skmacy dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); 454181641Skmacy result = dns_name_towire(owner_name, cctx, target); 455181641Skmacy if (result != ISC_R_SUCCESS) 456181641Skmacy goto rollback; 457181641Skmacy headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t); 458181641Skmacy if (!question) 459181641Skmacy headlen += sizeof(dns_ttl_t) 460181641Skmacy + 2; /* XXX 2 for rdata len */ 461181641Skmacy isc_buffer_availableregion(target, &r); 462181641Skmacy if (r.length < headlen) { 463181641Skmacy result = ISC_R_NOSPACE; 464181641Skmacy goto rollback; 465181641Skmacy } 466181641Skmacy isc_buffer_putuint16(target, rdataset->type); 467181641Skmacy isc_buffer_putuint16(target, rdataset->rdclass); 468181641Skmacy if (!question) { 469181641Skmacy isc_buffer_putuint32(target, rdataset->ttl); 470181641Skmacy 471181641Skmacy /* 472181641Skmacy * Save space for rdlen. 473181641Skmacy */ 474181641Skmacy rdlen = *target; 475181641Skmacy isc_buffer_add(target, 2); 476181641Skmacy 477181641Skmacy /* 478181641Skmacy * Copy out the rdata 479181641Skmacy */ 480181641Skmacy if (shuffle) 481181641Skmacy rdata = *(sorted[i].rdata); 482181641Skmacy else { 483181641Skmacy dns_rdata_reset(&rdata); 484181641Skmacy dns_rdataset_current(rdataset, &rdata); 485181641Skmacy } 486181641Skmacy result = dns_rdata_towire(&rdata, cctx, target); 487181641Skmacy if (result != ISC_R_SUCCESS) 488181641Skmacy goto rollback; 489181641Skmacy INSIST((target->used >= rdlen.used + 2) && 490181641Skmacy (target->used - rdlen.used - 2 < 65536)); 491181641Skmacy isc_buffer_putuint16(&rdlen, 492181641Skmacy (isc_uint16_t)(target->used - 493181641Skmacy rdlen.used - 2)); 494181641Skmacy added++; 495181641Skmacy } 496181641Skmacy 497181641Skmacy if (shuffle) { 498181641Skmacy i++; 499181641Skmacy if (i == count) 500181641Skmacy result = ISC_R_NOMORE; 501181641Skmacy else 502181641Skmacy result = ISC_R_SUCCESS; 503181641Skmacy } else { 504181641Skmacy result = dns_rdataset_next(rdataset); 505181641Skmacy } 506181641Skmacy } while (result == ISC_R_SUCCESS); 507181641Skmacy 508181641Skmacy if (result != ISC_R_NOMORE) 509181641Skmacy goto rollback; 510181641Skmacy 511181641Skmacy *countp += count; 512181641Skmacy 513181641Skmacy result = ISC_R_SUCCESS; 514181641Skmacy goto cleanup; 515181641Skmacy 516181641Skmacy rollback: 517181641Skmacy if (partial && result == ISC_R_NOSPACE) { 518181641Skmacy INSIST(rrbuffer.used < 65536); 519196726Sadrian dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used); 520197070Sjkim *countp += added; 521196726Sadrian *target = rrbuffer; 522196726Sadrian goto cleanup; 523196726Sadrian } 524196726Sadrian INSIST(savedbuffer.used < 65536); 525196726Sadrian dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); 526196726Sadrian *countp = 0; 527196726Sadrian *target = savedbuffer; 528196726Sadrian 529196726Sadrian cleanup: 530196726Sadrian if (sorted != NULL && sorted != sorted_fixed) 531196726Sadrian isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted)); 532196726Sadrian if (shuffled != NULL && shuffled != shuffled_fixed) 533196726Sadrian isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled)); 534196726Sadrian return (result); 535196726Sadrian} 536196726Sadrian 537196726Sadrianisc_result_t 538196726Sadriandns_rdataset_towiresorted(dns_rdataset_t *rdataset, 539196726Sadrian const dns_name_t *owner_name, 540196726Sadrian dns_compress_t *cctx, 541196726Sadrian isc_buffer_t *target, 542196726Sadrian dns_rdatasetorderfunc_t order, 543196726Sadrian const void *order_arg, 544196726Sadrian unsigned int options, 545196726Sadrian unsigned int *countp) 546196726Sadrian{ 547196726Sadrian return (towiresorted(rdataset, owner_name, cctx, target, 548196726Sadrian order, order_arg, ISC_FALSE, options, 549181641Skmacy countp, NULL)); 550181641Skmacy} 551181641Skmacy 552181641Skmacyisc_result_t 553181641Skmacydns_rdataset_towirepartial(dns_rdataset_t *rdataset, 554181641Skmacy const dns_name_t *owner_name, 555181641Skmacy dns_compress_t *cctx, 556181641Skmacy isc_buffer_t *target, 557181641Skmacy dns_rdatasetorderfunc_t order, 558181641Skmacy const void *order_arg, 559181641Skmacy unsigned int options, 560195649Salc unsigned int *countp, 561181641Skmacy void **state) 562181641Skmacy{ 563181641Skmacy REQUIRE(state == NULL); /* XXX remove when implemented */ 564181641Skmacy return (towiresorted(rdataset, owner_name, cctx, target, 565181641Skmacy order, order_arg, ISC_TRUE, options, 566181641Skmacy countp, state)); 567181641Skmacy} 568181641Skmacy 569181641Skmacyisc_result_t 570181641Skmacydns_rdataset_towire(dns_rdataset_t *rdataset, 571181641Skmacy dns_name_t *owner_name, 572181641Skmacy dns_compress_t *cctx, 573181641Skmacy isc_buffer_t *target, 574181641Skmacy unsigned int options, 575181641Skmacy unsigned int *countp) 576181641Skmacy{ 577181641Skmacy return (towiresorted(rdataset, owner_name, cctx, target, 578181641Skmacy NULL, NULL, ISC_FALSE, options, countp, NULL)); 579181641Skmacy} 580181641Skmacy 581181641Skmacyisc_result_t 582181641Skmacydns_rdataset_additionaldata(dns_rdataset_t *rdataset, 583181641Skmacy dns_additionaldatafunc_t add, void *arg) 584181641Skmacy{ 585181641Skmacy dns_rdata_t rdata = DNS_RDATA_INIT; 586181641Skmacy isc_result_t result; 587181641Skmacy 588181641Skmacy /* 589181641Skmacy * For each rdata in rdataset, call 'add' for each name and type in the 590181641Skmacy * rdata which is subject to additional section processing. 591181641Skmacy */ 592181641Skmacy 593181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 594181641Skmacy REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0); 595181641Skmacy 596181641Skmacy result = dns_rdataset_first(rdataset); 597181641Skmacy if (result != ISC_R_SUCCESS) 598181641Skmacy return (result); 599181641Skmacy 600181641Skmacy do { 601181641Skmacy dns_rdataset_current(rdataset, &rdata); 602181641Skmacy result = dns_rdata_additionaldata(&rdata, add, arg); 603181641Skmacy if (result == ISC_R_SUCCESS) 604181641Skmacy result = dns_rdataset_next(rdataset); 605181641Skmacy dns_rdata_reset(&rdata); 606181641Skmacy } while (result == ISC_R_SUCCESS); 607181641Skmacy 608181641Skmacy if (result != ISC_R_NOMORE) 609181641Skmacy return (result); 610181641Skmacy 611181641Skmacy return (ISC_R_SUCCESS); 612181641Skmacy} 613181641Skmacy 614181641Skmacyisc_result_t 615181641Skmacydns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) { 616181641Skmacy 617181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 618181641Skmacy REQUIRE(rdataset->methods != NULL); 619181641Skmacy if (rdataset->methods->addnoqname == NULL) 620181641Skmacy return (ISC_R_NOTIMPLEMENTED); 621181641Skmacy return((rdataset->methods->addnoqname)(rdataset, name)); 622181641Skmacy} 623181641Skmacy 624181641Skmacyisc_result_t 625181641Skmacydns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, 626181641Skmacy dns_rdataset_t *neg, dns_rdataset_t *negsig) 627181641Skmacy{ 628181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 629181641Skmacy REQUIRE(rdataset->methods != NULL); 630181641Skmacy 631181747Skmacy if (rdataset->methods->getnoqname == NULL) 632181747Skmacy return (ISC_R_NOTIMPLEMENTED); 633181747Skmacy return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig)); 634181641Skmacy} 635181641Skmacy 636181747Skmacyisc_result_t 637181747Skmacydns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) { 638181747Skmacy 639181747Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 640181808Skmacy REQUIRE(rdataset->methods != NULL); 641181747Skmacy if (rdataset->methods->addclosest == NULL) 642181747Skmacy return (ISC_R_NOTIMPLEMENTED); 643181747Skmacy return((rdataset->methods->addclosest)(rdataset, name)); 644181747Skmacy} 645181808Skmacy 646181747Skmacyisc_result_t 647181747Skmacydns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, 648181747Skmacy dns_rdataset_t *neg, dns_rdataset_t *negsig) 649181641Skmacy{ 650181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 651181641Skmacy REQUIRE(rdataset->methods != NULL); 652181641Skmacy 653181641Skmacy if (rdataset->methods->getclosest == NULL) 654181641Skmacy return (ISC_R_NOTIMPLEMENTED); 655181641Skmacy return((rdataset->methods->getclosest)(rdataset, name, neg, negsig)); 656181641Skmacy} 657181641Skmacy 658181641Skmacy/* 659181747Skmacy * Additional cache stuff 660181747Skmacy */ 661181747Skmacyisc_result_t 662181747Skmacydns_rdataset_getadditional(dns_rdataset_t *rdataset, 663181747Skmacy dns_rdatasetadditional_t type, 664181747Skmacy dns_rdatatype_t qtype, 665181747Skmacy dns_acache_t *acache, 666181747Skmacy dns_zone_t **zonep, 667181747Skmacy dns_db_t **dbp, 668181747Skmacy dns_dbversion_t **versionp, 669181747Skmacy dns_dbnode_t **nodep, 670181747Skmacy dns_name_t *fname, 671181747Skmacy dns_message_t *msg, 672181747Skmacy isc_stdtime_t now) 673181747Skmacy{ 674181747Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 675181747Skmacy REQUIRE(rdataset->methods != NULL); 676181747Skmacy REQUIRE(zonep == NULL || *zonep == NULL); 677181747Skmacy REQUIRE(dbp != NULL && *dbp == NULL); 678181747Skmacy REQUIRE(versionp != NULL && *versionp == NULL); 679181641Skmacy REQUIRE(nodep != NULL && *nodep == NULL); 680181641Skmacy REQUIRE(fname != NULL); 681181641Skmacy REQUIRE(msg != NULL); 682181641Skmacy 683181641Skmacy if (acache != NULL && rdataset->methods->getadditional != NULL) { 684181641Skmacy return ((rdataset->methods->getadditional)(rdataset, type, 685181641Skmacy qtype, acache, 686181641Skmacy zonep, dbp, 687181641Skmacy versionp, nodep, 688181641Skmacy fname, msg, now)); 689181641Skmacy } 690181641Skmacy 691181641Skmacy return (ISC_R_FAILURE); 692181641Skmacy} 693181641Skmacy 694181641Skmacyisc_result_t 695181641Skmacydns_rdataset_setadditional(dns_rdataset_t *rdataset, 696195949Skib dns_rdatasetadditional_t type, 697181641Skmacy dns_rdatatype_t qtype, 698181641Skmacy dns_acache_t *acache, 699181641Skmacy dns_zone_t *zone, 700181641Skmacy dns_db_t *db, 701181641Skmacy dns_dbversion_t *version, 702181641Skmacy dns_dbnode_t *node, 703181641Skmacy dns_name_t *fname) 704181641Skmacy{ 705181641Skmacy REQUIRE(DNS_RDATASET_VALID(rdataset)); 706181641Skmacy REQUIRE(rdataset->methods != NULL); 707181641Skmacy 708181641Skmacy if (acache != NULL && rdataset->methods->setadditional != NULL) { 709181641Skmacy return ((rdataset->methods->setadditional)(rdataset, type, 710181641Skmacy qtype, acache, zone, 711181641Skmacy db, version, 712181641Skmacy node, fname)); 713181641Skmacy } 714181641Skmacy 715181641Skmacy return (ISC_R_FAILURE); 716181641Skmacy} 717181641Skmacy 718181641Skmacyisc_result_t 719181641Skmacydns_rdataset_putadditional(dns_acache_t *acache, 720196726Sadrian dns_rdataset_t *rdataset, 721196726Sadrian dns_rdatasetadditional_t type, 722196726Sadrian dns_rdatatype_t qtype) 723196726Sadrian{ 724196726Sadrian REQUIRE(DNS_RDATASET_VALID(rdataset)); 725196726Sadrian REQUIRE(rdataset->methods != NULL); 726196726Sadrian 727196726Sadrian if (acache != NULL && rdataset->methods->putadditional != NULL) { 728196726Sadrian return ((rdataset->methods->putadditional)(acache, rdataset, 729196726Sadrian type, qtype)); 730196726Sadrian } 731196726Sadrian 732196726Sadrian return (ISC_R_FAILURE); 733196726Sadrian} 734196726Sadrian 735196726Sadrian