rdataset.c 17.4 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
Automatic Updater's avatar
Automatic Updater committed
2
 * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1999-2003  Internet Software Consortium.
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
Bob Halley's avatar
Bob Halley committed
6 7
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9 10 11 12 13 14 15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
Bob Halley's avatar
Bob Halley committed
16 17
 */

Francis Dupont's avatar
Francis Dupont committed
18
/* $Id: rdataset.c,v 1.83 2009/01/17 14:53:36 fdupont Exp $ */
19 20

/*! \file */
David Lawrence's avatar
David Lawrence committed
21

Michael Graff's avatar
Michael Graff committed
22 23
#include <config.h>

24
#include <stdlib.h>
Bob Halley's avatar
Bob Halley committed
25

26
#include <isc/buffer.h>
27
#include <isc/mem.h>
28
#include <isc/random.h>
Bob Halley's avatar
Bob Halley committed
29
#include <isc/util.h>
Bob Halley's avatar
Bob Halley committed
30

31
#include <dns/name.h>
32
#include <dns/ncache.h>
Bob Halley's avatar
Bob Halley committed
33
#include <dns/rdata.h>
Bob Halley's avatar
Bob Halley committed
34
#include <dns/rdataset.h>
Mark Andrews's avatar
Mark Andrews committed
35
#include <dns/compress.h>
Bob Halley's avatar
Bob Halley committed
36 37 38 39 40 41 42 43 44 45

void
dns_rdataset_init(dns_rdataset_t *rdataset) {

	/*
	 * Make 'rdataset' a valid, disassociated rdataset.
	 */

	REQUIRE(rdataset != NULL);

Bob Halley's avatar
Bob Halley committed
46
	rdataset->magic = DNS_RDATASET_MAGIC;
Bob Halley's avatar
Bob Halley committed
47 48
	rdataset->methods = NULL;
	ISC_LINK_INIT(rdataset, link);
Bob Halley's avatar
Bob Halley committed
49
	rdataset->rdclass = 0;
Bob Halley's avatar
Bob Halley committed
50 51
	rdataset->type = 0;
	rdataset->ttl = 0;
Bob Halley's avatar
Bob Halley committed
52
	rdataset->trust = 0;
Bob Halley's avatar
Bob Halley committed
53
	rdataset->covers = 0;
Michael Graff's avatar
Michael Graff committed
54
	rdataset->attributes = 0;
55
	rdataset->count = ISC_UINT32_MAX;
Bob Halley's avatar
Bob Halley committed
56 57 58
	rdataset->private1 = NULL;
	rdataset->private2 = NULL;
	rdataset->private3 = NULL;
59
	rdataset->privateuint4 = 0;
Bob Halley's avatar
Bob Halley committed
60
	rdataset->private5 = NULL;
61
	rdataset->private6 = NULL;
62
	rdataset->resign = 0;
Bob Halley's avatar
Bob Halley committed
63 64 65 66 67 68 69 70 71
}

void
dns_rdataset_invalidate(dns_rdataset_t *rdataset) {

	/*
	 * Invalidate 'rdataset'.
	 */

Bob Halley's avatar
Bob Halley committed
72
	REQUIRE(DNS_RDATASET_VALID(rdataset));
Bob Halley's avatar
Bob Halley committed
73
	REQUIRE(rdataset->methods == NULL);
74

Bob Halley's avatar
Bob Halley committed
75 76
	rdataset->magic = 0;
	ISC_LINK_INIT(rdataset, link);
Bob Halley's avatar
Bob Halley committed
77
	rdataset->rdclass = 0;
Bob Halley's avatar
Bob Halley committed
78 79
	rdataset->type = 0;
	rdataset->ttl = 0;
Bob Halley's avatar
Bob Halley committed
80
	rdataset->trust = 0;
Bob Halley's avatar
Bob Halley committed
81
	rdataset->covers = 0;
Michael Graff's avatar
Michael Graff committed
82
	rdataset->attributes = 0;
83
	rdataset->count = ISC_UINT32_MAX;
Bob Halley's avatar
Bob Halley committed
84 85 86
	rdataset->private1 = NULL;
	rdataset->private2 = NULL;
	rdataset->private3 = NULL;
87
	rdataset->privateuint4 = 0;
Bob Halley's avatar
Bob Halley committed
88
	rdataset->private5 = NULL;
Bob Halley's avatar
Bob Halley committed
89 90 91 92 93 94
}

void
dns_rdataset_disassociate(dns_rdataset_t *rdataset) {

	/*
Bob Halley's avatar
Bob Halley committed
95
	 * Disassociate 'rdataset' from its rdata, allowing it to be reused.
Bob Halley's avatar
Bob Halley committed
96 97
	 */

Bob Halley's avatar
Bob Halley committed
98
	REQUIRE(DNS_RDATASET_VALID(rdataset));
99
	REQUIRE(rdataset->methods != NULL);
Bob Halley's avatar
Bob Halley committed
100 101 102 103

	(rdataset->methods->disassociate)(rdataset);
	rdataset->methods = NULL;
	ISC_LINK_INIT(rdataset, link);
Bob Halley's avatar
Bob Halley committed
104
	rdataset->rdclass = 0;
Bob Halley's avatar
Bob Halley committed
105 106
	rdataset->type = 0;
	rdataset->ttl = 0;
Bob Halley's avatar
Bob Halley committed
107
	rdataset->trust = 0;
Bob Halley's avatar
Bob Halley committed
108
	rdataset->covers = 0;
Michael Graff's avatar
Michael Graff committed
109
	rdataset->attributes = 0;
110
	rdataset->count = ISC_UINT32_MAX;
Bob Halley's avatar
Bob Halley committed
111 112 113
	rdataset->private1 = NULL;
	rdataset->private2 = NULL;
	rdataset->private3 = NULL;
114
	rdataset->privateuint4 = 0;
Bob Halley's avatar
Bob Halley committed
115
	rdataset->private5 = NULL;
116
	rdataset->private6 = NULL;
Bob Halley's avatar
Bob Halley committed
117 118
}

Bob Halley's avatar
Bob Halley committed
119 120 121 122 123
isc_boolean_t
dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
	/*
	 * Is 'rdataset' associated?
	 */
124

Bob Halley's avatar
Bob Halley committed
125 126 127 128 129 130 131 132
	REQUIRE(DNS_RDATASET_VALID(rdataset));

	if (rdataset->methods != NULL)
		return (ISC_TRUE);

	return (ISC_FALSE);
}

Bob Halley's avatar
Bob Halley committed
133 134
static void
question_disassociate(dns_rdataset_t *rdataset) {
Andreas Gustafsson's avatar
Andreas Gustafsson committed
135
	UNUSED(rdataset);
Bob Halley's avatar
Bob Halley committed
136 137
}

138
static isc_result_t
Bob Halley's avatar
Bob Halley committed
139
question_cursor(dns_rdataset_t *rdataset) {
Andreas Gustafsson's avatar
Andreas Gustafsson committed
140
	UNUSED(rdataset);
Automatic Updater's avatar
Automatic Updater committed
141

142
	return (ISC_R_NOMORE);
Bob Halley's avatar
Bob Halley committed
143 144 145 146 147 148 149
}

static void
question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
	/*
	 * This routine should never be called.
	 */
Andreas Gustafsson's avatar
Andreas Gustafsson committed
150 151
	UNUSED(rdataset);
	UNUSED(rdata);
Automatic Updater's avatar
Automatic Updater committed
152

Bob Halley's avatar
Bob Halley committed
153 154 155
	REQUIRE(0);
}

Bob Halley's avatar
Bob Halley committed
156 157 158 159 160
static void
question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
	*target = *source;
}

Bob Halley's avatar
Bob Halley committed
161 162 163 164 165
static unsigned int
question_count(dns_rdataset_t *rdataset) {
	/*
	 * This routine should never be called.
	 */
Andreas Gustafsson's avatar
Andreas Gustafsson committed
166
	UNUSED(rdataset);
Bob Halley's avatar
Bob Halley committed
167 168 169 170 171
	REQUIRE(0);

	return (0);
}

Bob Halley's avatar
Bob Halley committed
172 173 174 175
static dns_rdatasetmethods_t question_methods = {
	question_disassociate,
	question_cursor,
	question_cursor,
Bob Halley's avatar
Bob Halley committed
176
	question_current,
Bob Halley's avatar
Bob Halley committed
177
	question_clone,
178 179
	question_count,
	NULL,
180 181 182
	NULL,
	NULL,
	NULL,
183 184
	NULL,
	NULL,
185
	NULL
Bob Halley's avatar
Bob Halley committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
};

void
dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
			  dns_rdatatype_t type)
{

	/*
	 * Make 'rdataset' a valid, associated, question rdataset, with a
	 * question class of 'rdclass' and type 'type'.
	 */

	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods == NULL);

	rdataset->methods = &question_methods;
	rdataset->rdclass = rdclass;
	rdataset->type = type;
	rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
}

Bob Halley's avatar
Bob Halley committed
207 208 209 210 211 212 213 214 215 216 217 218 219
unsigned int
dns_rdataset_count(dns_rdataset_t *rdataset) {

	/*
	 * Return the number of records in 'rdataset'.
	 */

	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);

	return ((rdataset->methods->count)(rdataset));
}

Bob Halley's avatar
Bob Halley committed
220 221 222 223 224 225 226 227 228 229 230
void
dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {

	/*
	 * Make 'target' refer to the same rdataset as 'source'.
	 */

	REQUIRE(DNS_RDATASET_VALID(source));
	REQUIRE(source->methods != NULL);
	REQUIRE(DNS_RDATASET_VALID(target));
	REQUIRE(target->methods == NULL);
231

Bob Halley's avatar
Bob Halley committed
232 233 234
	(source->methods->clone)(source, target);
}

235
isc_result_t
Bob Halley's avatar
Bob Halley committed
236 237 238 239 240 241
dns_rdataset_first(dns_rdataset_t *rdataset) {

	/*
	 * Move the rdata cursor to the first rdata in the rdataset (if any).
	 */

Bob Halley's avatar
Bob Halley committed
242
	REQUIRE(DNS_RDATASET_VALID(rdataset));
243
	REQUIRE(rdataset->methods != NULL);
Bob Halley's avatar
Bob Halley committed
244 245 246 247

	return ((rdataset->methods->first)(rdataset));
}

248
isc_result_t
Bob Halley's avatar
Bob Halley committed
249 250 251 252 253 254
dns_rdataset_next(dns_rdataset_t *rdataset) {

	/*
	 * Move the rdata cursor to the next rdata in the rdataset (if any).
	 */

Bob Halley's avatar
Bob Halley committed
255
	REQUIRE(DNS_RDATASET_VALID(rdataset));
256
	REQUIRE(rdataset->methods != NULL);
Bob Halley's avatar
Bob Halley committed
257 258 259 260 261 262 263 264 265 266 267

	return ((rdataset->methods->next)(rdataset));
}

void
dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {

	/*
	 * Make 'rdata' refer to the current rdata.
	 */

Bob Halley's avatar
Bob Halley committed
268
	REQUIRE(DNS_RDATASET_VALID(rdataset));
269
	REQUIRE(rdataset->methods != NULL);
Bob Halley's avatar
Bob Halley committed
270 271 272 273

	(rdataset->methods->current)(rdataset, rdata);
}

274 275
#define MAX_SHUFFLE	32
#define WANT_FIXED(r)	(((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
276
#define WANT_RANDOM(r)	(((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
277

278 279 280 281 282 283 284 285 286 287 288
struct towire_sort {
	int key;
	dns_rdata_t *rdata;
};

static int
towire_compare(const void *av, const void *bv) {
	const struct towire_sort *a = (const struct towire_sort *) av;
	const struct towire_sort *b = (const struct towire_sort *) bv;
	return (a->key - b->key);
}
289

290
static isc_result_t
291
towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
292
	     dns_compress_t *cctx, isc_buffer_t *target,
293
	     dns_rdatasetorderfunc_t order, const void *order_arg,
294 295
	     isc_boolean_t partial, unsigned int options,
	     unsigned int *countp, void **state)
Bob Halley's avatar
Bob Halley committed
296
{
Mark Andrews's avatar
Mark Andrews committed
297
	dns_rdata_t rdata = DNS_RDATA_INIT;
298
	isc_region_t r;
299
	isc_result_t result;
300
	unsigned int i, count, added, choice;
Mark Andrews's avatar
Mark Andrews committed
301
	isc_buffer_t savedbuffer, rdlen, rrbuffer;
302
	unsigned int headlen;
Bob Halley's avatar
Bob Halley committed
303
	isc_boolean_t question = ISC_FALSE;
304
	isc_boolean_t shuffle = ISC_FALSE;
305 306
	dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
	struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
Bob Halley's avatar
Bob Halley committed
307

308 309
	UNUSED(state);

Bob Halley's avatar
Bob Halley committed
310 311 312 313 314
	/*
	 * Convert 'rdataset' to wire format, compressing names as specified
	 * in cctx, and storing the result in 'target'.
	 */

Bob Halley's avatar
Bob Halley committed
315
	REQUIRE(DNS_RDATASET_VALID(rdataset));
316
	REQUIRE(countp != NULL);
317
	REQUIRE((order == NULL) == (order_arg == NULL));
318
	REQUIRE(cctx != NULL && cctx->mctx != NULL);
Bob Halley's avatar
Bob Halley committed
319

320
	count = 0;
321
	if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
Bob Halley's avatar
Bob Halley committed
322
		question = ISC_TRUE;
323
		count = 1;
324
		result = dns_rdataset_first(rdataset);
325
		INSIST(result == ISC_R_NOMORE);
326 327 328 329
	} else if (rdataset->type == 0) {
		/*
		 * This is a negative caching rdataset.
		 */
330 331 332 333
		unsigned int ncache_opts = 0;
		if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
			ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
		return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
334
					  countp));
335
	} else {
336
		count = (rdataset->methods->count)(rdataset);
Bob Halley's avatar
Bob Halley committed
337
		result = dns_rdataset_first(rdataset);
338 339 340
		if (result == ISC_R_NOMORE)
			return (ISC_R_SUCCESS);
		if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
341 342 343
			return (result);
	}

344
	/*
Francis Dupont's avatar
Francis Dupont committed
345
	 * Do we want to shuffle this answer?
346
	 */
347
	if (!question && count > 1 &&
348
	    (!WANT_FIXED(rdataset) || order != NULL) &&
349
	    rdataset->type != dns_rdatatype_rrsig)
350
		shuffle = ISC_TRUE;
351 352 353 354 355 356 357 358 359 360 361 362

	if (shuffle && count > MAX_SHUFFLE) {
		shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
		sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
		if (shuffled == NULL || sorted == NULL)
			shuffle = ISC_FALSE;
	} else {
		shuffled = shuffled_fixed;
		sorted = sorted_fixed;
	}

	if (shuffle) {
363 364 365 366 367 368 369 370 371 372 373 374
		/*
		 * First we get handles to all of the rdata.
		 */
		i = 0;
		do {
			INSIST(i < count);
			dns_rdata_init(&shuffled[i]);
			dns_rdataset_current(rdataset, &shuffled[i]);
			i++;
			result = dns_rdataset_next(rdataset);
		} while (result == ISC_R_SUCCESS);
		if (result != ISC_R_NOMORE)
375
			goto cleanup;
376
		INSIST(i == count);
377

378
		/*
379
		 * Now we shuffle.
380
		 */
381
		if (WANT_FIXED(rdataset)) {
382
			/*
383
			 * 'Fixed' order.
384
			 */
385
			INSIST(order != NULL);
386 387 388 389 390
			for (i = 0; i < count; i++) {
				sorted[i].key = (*order)(&shuffled[i],
							 order_arg);
				sorted[i].rdata = &shuffled[i];
			}
391 392 393 394 395 396
		} else if (WANT_RANDOM(rdataset)) {
			/*
			 * 'Random' order.
			 */
			for (i = 0; i < count; i++) {
				dns_rdata_t rdata;
397 398 399 400
				isc_uint32_t val;

				isc_random_get(&val);
				choice = i + (val % (count - i));
401 402 403 404 405 406 407 408 409 410
				rdata = shuffled[i];
				shuffled[i] = shuffled[choice];
				shuffled[choice] = rdata;
				if (order != NULL)
					sorted[i].key = (*order)(&shuffled[i],
								 order_arg);
				else
					sorted[i].key = 0; /* Unused */
				sorted[i].rdata = &shuffled[i];
			}
411
		} else {
412
			/*
413
			 * "Cyclic" order.
414
			 */
415 416 417
			isc_uint32_t val;
			unsigned int j;

418 419 420
			val = rdataset->count;
			if (val == ISC_UINT32_MAX)
				isc_random_get(&val);
421
			j = val % count;
422
			for (i = 0; i < count; i++) {
423
				if (order != NULL)
424
					sorted[j].key = (*order)(&shuffled[i],
425 426 427
								 order_arg);
				else
					sorted[j].key = 0; /* Unused */
428 429 430 431
				sorted[j].rdata = &shuffled[i];
				j++;
				if (j == count)
					j = 0; /* Wrap around. */
432 433
			}
		}
434 435 436 437 438 439 440

		/*
		 * Sorted order.
		 */
		if (order != NULL)
			qsort(sorted, count, sizeof(sorted[0]),
			      towire_compare);
441 442
	}

443
	savedbuffer = *target;
444
	i = 0;
445
	added = 0;
446

447 448
	do {
		/*
449
		 * Copy out the name, type, class, ttl.
450
		 */
Automatic Updater's avatar
Automatic Updater committed
451

Mark Andrews's avatar
Mark Andrews committed
452
		rrbuffer = *target;
453
		dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
454
		result = dns_name_towire(owner_name, cctx, target);
455
		if (result != ISC_R_SUCCESS)
456
			goto rollback;
457
		headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
Bob Halley's avatar
Bob Halley committed
458
		if (!question)
459 460
			headlen += sizeof(dns_ttl_t)
				+ 2;  /* XXX 2 for rdata len */
461
		isc_buffer_availableregion(target, &r);
462
		if (r.length < headlen) {
463 464
			result = ISC_R_NOSPACE;
			goto rollback;
Mark Andrews's avatar
Mark Andrews committed
465
		}
466
		isc_buffer_putuint16(target, rdataset->type);
Bob Halley's avatar
Bob Halley committed
467
		isc_buffer_putuint16(target, rdataset->rdclass);
Bob Halley's avatar
Bob Halley committed
468
		if (!question) {
469 470 471 472 473 474 475 476 477
			isc_buffer_putuint32(target, rdataset->ttl);

			/*
			 * Save space for rdlen.
			 */
			rdlen = *target;
			isc_buffer_add(target, 2);

			/*
478
			 * Copy out the rdata
479
			 */
480
			if (shuffle)
481
				rdata = *(sorted[i].rdata);
482
			else {
483
				dns_rdata_reset(&rdata);
484
				dns_rdataset_current(rdataset, &rdata);
485
			}
486
			result = dns_rdata_towire(&rdata, cctx, target);
487
			if (result != ISC_R_SUCCESS)
488
				goto rollback;
489 490
			INSIST((target->used >= rdlen.used + 2) &&
			       (target->used - rdlen.used - 2 < 65536));
491
			isc_buffer_putuint16(&rdlen,
492 493
					     (isc_uint16_t)(target->used -
							    rdlen.used - 2));
494
			added++;
Mark Andrews's avatar
Mark Andrews committed
495
		}
496

497 498 499
		if (shuffle) {
			i++;
			if (i == count)
500
				result = ISC_R_NOMORE;
501 502
			else
				result = ISC_R_SUCCESS;
503
		} else {
504
			result = dns_rdataset_next(rdataset);
505
		}
506
	} while (result == ISC_R_SUCCESS);
507

508
	if (result != ISC_R_NOMORE)
509
		goto rollback;
510

511 512
	*countp += count;

513 514
	result = ISC_R_SUCCESS;
	goto cleanup;
515 516

 rollback:
517
	if (partial && result == ISC_R_NOSPACE) {
Mark Andrews's avatar
Mark Andrews committed
518 519
		INSIST(rrbuffer.used < 65536);
		dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
520
		*countp += added;
Mark Andrews's avatar
Mark Andrews committed
521
		*target = rrbuffer;
522
		goto cleanup;
523
	}
524 525
	INSIST(savedbuffer.used < 65536);
	dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
526 527 528
	*countp = 0;
	*target = savedbuffer;

529 530 531 532 533
 cleanup:
	if (sorted != NULL && sorted != sorted_fixed)
		isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
	if (shuffled != NULL && shuffled != shuffled_fixed)
		isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
534
	return (result);
Bob Halley's avatar
Bob Halley committed
535
}
536

537 538
isc_result_t
dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
539
			  const dns_name_t *owner_name,
540 541 542
			  dns_compress_t *cctx,
			  isc_buffer_t *target,
			  dns_rdatasetorderfunc_t order,
543
			  const void *order_arg,
544
			  unsigned int options,
545 546 547
			  unsigned int *countp)
{
	return (towiresorted(rdataset, owner_name, cctx, target,
548 549
			     order, order_arg, ISC_FALSE, options,
			     countp, NULL));
550 551 552 553
}

isc_result_t
dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
554
			   const dns_name_t *owner_name,
555 556 557
			   dns_compress_t *cctx,
			   isc_buffer_t *target,
			   dns_rdatasetorderfunc_t order,
558
			   const void *order_arg,
559
			   unsigned int options,
560 561 562 563 564
			   unsigned int *countp,
			   void **state)
{
	REQUIRE(state == NULL);	/* XXX remove when implemented */
	return (towiresorted(rdataset, owner_name, cctx, target,
565 566
			     order, order_arg, ISC_TRUE, options,
			     countp, state));
567 568
}

569 570 571 572 573
isc_result_t
dns_rdataset_towire(dns_rdataset_t *rdataset,
		    dns_name_t *owner_name,
		    dns_compress_t *cctx,
		    isc_buffer_t *target,
574
		    unsigned int options,
575 576
		    unsigned int *countp)
{
577
	return (towiresorted(rdataset, owner_name, cctx, target,
578
			     NULL, NULL, ISC_FALSE, options, countp, NULL));
579 580
}

581
isc_result_t
582 583 584
dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
			    dns_additionaldatafunc_t add, void *arg)
{
Mark Andrews's avatar
Mark Andrews committed
585
	dns_rdata_t rdata = DNS_RDATA_INIT;
586
	isc_result_t result;
587 588 589 590 591 592 593 594 595 596

	/*
	 * For each rdata in rdataset, call 'add' for each name and type in the
	 * rdata which is subject to additional section processing.
	 */

	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);

	result = dns_rdataset_first(rdataset);
597
	if (result != ISC_R_SUCCESS)
598 599 600 601 602
		return (result);

	do {
		dns_rdataset_current(rdataset, &rdata);
		result = dns_rdata_additionaldata(&rdata, add, arg);
603
		if (result == ISC_R_SUCCESS)
604
			result = dns_rdataset_next(rdataset);
605
		dns_rdata_reset(&rdata);
606
	} while (result == ISC_R_SUCCESS);
607

608
	if (result != ISC_R_NOMORE)
609 610
		return (result);

611
	return (ISC_R_SUCCESS);
612
}
613 614 615 616 617 618 619 620 621 622 623 624 625

isc_result_t
dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {

	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);
	if (rdataset->methods->addnoqname == NULL)
		return (ISC_R_NOTIMPLEMENTED);
	return((rdataset->methods->addnoqname)(rdataset, name));
}

isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
626
			dns_rdataset_t *neg, dns_rdataset_t *negsig)
627 628 629 630 631 632
{
	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);

	if (rdataset->methods->getnoqname == NULL)
		return (ISC_R_NOTIMPLEMENTED);
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
	return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
}

isc_result_t
dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {

	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);
	if (rdataset->methods->addclosest == NULL)
		return (ISC_R_NOTIMPLEMENTED);
	return((rdataset->methods->addclosest)(rdataset, name));
}

isc_result_t
dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
			dns_rdataset_t *neg, dns_rdataset_t *negsig)
{
	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);

	if (rdataset->methods->getclosest == NULL)
		return (ISC_R_NOTIMPLEMENTED);
	return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
656
}
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734

/*
 * Additional cache stuff
 */
isc_result_t
dns_rdataset_getadditional(dns_rdataset_t *rdataset,
			   dns_rdatasetadditional_t type,
			   dns_rdatatype_t qtype,
			   dns_acache_t *acache,
			   dns_zone_t **zonep,
			   dns_db_t **dbp,
			   dns_dbversion_t **versionp,
			   dns_dbnode_t **nodep,
			   dns_name_t *fname,
			   dns_message_t *msg,
			   isc_stdtime_t now)
{
	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);
	REQUIRE(zonep == NULL || *zonep == NULL);
	REQUIRE(dbp != NULL && *dbp == NULL);
	REQUIRE(versionp != NULL && *versionp == NULL);
	REQUIRE(nodep != NULL && *nodep == NULL);
	REQUIRE(fname != NULL);
	REQUIRE(msg != NULL);

	if (acache != NULL && rdataset->methods->getadditional != NULL) {
		return ((rdataset->methods->getadditional)(rdataset, type,
							   qtype, acache,
							   zonep, dbp,
							   versionp, nodep,
							   fname, msg, now));
	}

	return (ISC_R_FAILURE);
}

isc_result_t
dns_rdataset_setadditional(dns_rdataset_t *rdataset,
			   dns_rdatasetadditional_t type,
			   dns_rdatatype_t qtype,
			   dns_acache_t *acache,
			   dns_zone_t *zone,
			   dns_db_t *db,
			   dns_dbversion_t *version,
			   dns_dbnode_t *node,
			   dns_name_t *fname)
{
	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);

	if (acache != NULL && rdataset->methods->setadditional != NULL) {
		return ((rdataset->methods->setadditional)(rdataset, type,
							   qtype, acache, zone,
							   db, version,
							   node, fname));
	}

	return (ISC_R_FAILURE);
}

isc_result_t
dns_rdataset_putadditional(dns_acache_t *acache,
			   dns_rdataset_t *rdataset,
			   dns_rdatasetadditional_t type,
			   dns_rdatatype_t qtype)
{
	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(rdataset->methods != NULL);

	if (acache != NULL && rdataset->methods->putadditional != NULL) {
		return ((rdataset->methods->putadditional)(acache, rdataset,
							   type, qtype));
	}

	return (ISC_R_FAILURE);
}