1 /*
2  * Copyright (C) 2004-2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* $Id$ */
19 
20 /*! \file */
21 
22 #include <config.h>
23 
24 #include <stdlib.h>
25 
26 #include <isc/buffer.h>
27 #include <isc/mem.h>
28 #include <isc/random.h>
29 #include <isc/serial.h>
30 #include <isc/util.h>
31 
32 #include <dns/name.h>
33 #include <dns/ncache.h>
34 #include <dns/rdata.h>
35 #include <dns/rdataset.h>
36 #include <dns/compress.h>
37 
38 static const char *trustnames[] = {
39 	"none",
40 	"pending-additional",
41 	"pending-answer",
42 	"additional",
43 	"glue",
44 	"answer",
45 	"authauthority",
46 	"authanswer",
47 	"secure",
48 	"local" /* aka ultimate */
49 };
50 
51 const char *
dns_trust_totext(dns_trust_t trust)52 dns_trust_totext(dns_trust_t trust) {
53 	if (trust >= sizeof(trustnames)/sizeof(*trustnames))
54 		return ("bad");
55 	return (trustnames[trust]);
56 }
57 
58 void
dns_rdataset_init(dns_rdataset_t * rdataset)59 dns_rdataset_init(dns_rdataset_t *rdataset) {
60 
61 	/*
62 	 * Make 'rdataset' a valid, disassociated rdataset.
63 	 */
64 
65 	REQUIRE(rdataset != NULL);
66 
67 	rdataset->magic = DNS_RDATASET_MAGIC;
68 	rdataset->methods = NULL;
69 	ISC_LINK_INIT(rdataset, link);
70 	rdataset->rdclass = 0;
71 	rdataset->type = 0;
72 	rdataset->ttl = 0;
73 	rdataset->trust = 0;
74 	rdataset->covers = 0;
75 	rdataset->attributes = 0;
76 	rdataset->count = ISC_UINT32_MAX;
77 	rdataset->private1 = NULL;
78 	rdataset->private2 = NULL;
79 	rdataset->private3 = NULL;
80 	rdataset->privateuint4 = 0;
81 	rdataset->private5 = NULL;
82 	rdataset->private6 = NULL;
83 	rdataset->private7 = NULL;
84 	rdataset->resign = 0;
85 }
86 
87 void
dns_rdataset_invalidate(dns_rdataset_t * rdataset)88 dns_rdataset_invalidate(dns_rdataset_t *rdataset) {
89 
90 	/*
91 	 * Invalidate 'rdataset'.
92 	 */
93 
94 	REQUIRE(DNS_RDATASET_VALID(rdataset));
95 	REQUIRE(rdataset->methods == NULL);
96 
97 	rdataset->magic = 0;
98 	ISC_LINK_INIT(rdataset, link);
99 	rdataset->rdclass = 0;
100 	rdataset->type = 0;
101 	rdataset->ttl = 0;
102 	rdataset->trust = 0;
103 	rdataset->covers = 0;
104 	rdataset->attributes = 0;
105 	rdataset->count = ISC_UINT32_MAX;
106 	rdataset->private1 = NULL;
107 	rdataset->private2 = NULL;
108 	rdataset->private3 = NULL;
109 	rdataset->privateuint4 = 0;
110 	rdataset->private5 = NULL;
111 }
112 
113 void
dns_rdataset_disassociate(dns_rdataset_t * rdataset)114 dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
115 
116 	/*
117 	 * Disassociate 'rdataset' from its rdata, allowing it to be reused.
118 	 */
119 
120 	REQUIRE(DNS_RDATASET_VALID(rdataset));
121 	REQUIRE(rdataset->methods != NULL);
122 
123 	(rdataset->methods->disassociate)(rdataset);
124 	rdataset->methods = NULL;
125 	ISC_LINK_INIT(rdataset, link);
126 	rdataset->rdclass = 0;
127 	rdataset->type = 0;
128 	rdataset->ttl = 0;
129 	rdataset->trust = 0;
130 	rdataset->covers = 0;
131 	rdataset->attributes = 0;
132 	rdataset->count = ISC_UINT32_MAX;
133 	rdataset->private1 = NULL;
134 	rdataset->private2 = NULL;
135 	rdataset->private3 = NULL;
136 	rdataset->privateuint4 = 0;
137 	rdataset->private5 = NULL;
138 	rdataset->private6 = NULL;
139 }
140 
141 isc_boolean_t
dns_rdataset_isassociated(dns_rdataset_t * rdataset)142 dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
143 	/*
144 	 * Is 'rdataset' associated?
145 	 */
146 
147 	REQUIRE(DNS_RDATASET_VALID(rdataset));
148 
149 	if (rdataset->methods != NULL)
150 		return (ISC_TRUE);
151 
152 	return (ISC_FALSE);
153 }
154 
155 static void
question_disassociate(dns_rdataset_t * rdataset)156 question_disassociate(dns_rdataset_t *rdataset) {
157 	UNUSED(rdataset);
158 }
159 
160 static isc_result_t
question_cursor(dns_rdataset_t * rdataset)161 question_cursor(dns_rdataset_t *rdataset) {
162 	UNUSED(rdataset);
163 
164 	return (ISC_R_NOMORE);
165 }
166 
167 static void
question_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)168 question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
169 	/*
170 	 * This routine should never be called.
171 	 */
172 	UNUSED(rdataset);
173 	UNUSED(rdata);
174 
175 	REQUIRE(0);
176 }
177 
178 static void
question_clone(dns_rdataset_t * source,dns_rdataset_t * target)179 question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
180 	*target = *source;
181 }
182 
183 static unsigned int
question_count(dns_rdataset_t * rdataset)184 question_count(dns_rdataset_t *rdataset) {
185 	/*
186 	 * This routine should never be called.
187 	 */
188 	UNUSED(rdataset);
189 	REQUIRE(0);
190 
191 	return (0);
192 }
193 
194 static dns_rdatasetmethods_t question_methods = {
195 	question_disassociate,
196 	question_cursor,
197 	question_cursor,
198 	question_current,
199 	question_clone,
200 	question_count,
201 	NULL,
202 	NULL,
203 	NULL,
204 	NULL,
205 	NULL,
206 	NULL,
207 	NULL,
208 	NULL,
209 	NULL
210 };
211 
212 void
dns_rdataset_makequestion(dns_rdataset_t * rdataset,dns_rdataclass_t rdclass,dns_rdatatype_t type)213 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
214 			  dns_rdatatype_t type)
215 {
216 
217 	/*
218 	 * Make 'rdataset' a valid, associated, question rdataset, with a
219 	 * question class of 'rdclass' and type 'type'.
220 	 */
221 
222 	REQUIRE(DNS_RDATASET_VALID(rdataset));
223 	REQUIRE(rdataset->methods == NULL);
224 
225 	rdataset->methods = &question_methods;
226 	rdataset->rdclass = rdclass;
227 	rdataset->type = type;
228 	rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
229 }
230 
231 unsigned int
dns_rdataset_count(dns_rdataset_t * rdataset)232 dns_rdataset_count(dns_rdataset_t *rdataset) {
233 
234 	/*
235 	 * Return the number of records in 'rdataset'.
236 	 */
237 
238 	REQUIRE(DNS_RDATASET_VALID(rdataset));
239 	REQUIRE(rdataset->methods != NULL);
240 
241 	return ((rdataset->methods->count)(rdataset));
242 }
243 
244 void
dns_rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)245 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
246 
247 	/*
248 	 * Make 'target' refer to the same rdataset as 'source'.
249 	 */
250 
251 	REQUIRE(DNS_RDATASET_VALID(source));
252 	REQUIRE(source->methods != NULL);
253 	REQUIRE(DNS_RDATASET_VALID(target));
254 	REQUIRE(target->methods == NULL);
255 
256 	(source->methods->clone)(source, target);
257 }
258 
259 isc_result_t
dns_rdataset_first(dns_rdataset_t * rdataset)260 dns_rdataset_first(dns_rdataset_t *rdataset) {
261 
262 	/*
263 	 * Move the rdata cursor to the first rdata in the rdataset (if any).
264 	 */
265 
266 	REQUIRE(DNS_RDATASET_VALID(rdataset));
267 	REQUIRE(rdataset->methods != NULL);
268 
269 	return ((rdataset->methods->first)(rdataset));
270 }
271 
272 isc_result_t
dns_rdataset_next(dns_rdataset_t * rdataset)273 dns_rdataset_next(dns_rdataset_t *rdataset) {
274 
275 	/*
276 	 * Move the rdata cursor to the next rdata in the rdataset (if any).
277 	 */
278 
279 	REQUIRE(DNS_RDATASET_VALID(rdataset));
280 	REQUIRE(rdataset->methods != NULL);
281 
282 	return ((rdataset->methods->next)(rdataset));
283 }
284 
285 void
dns_rdataset_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)286 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
287 
288 	/*
289 	 * Make 'rdata' refer to the current rdata.
290 	 */
291 
292 	REQUIRE(DNS_RDATASET_VALID(rdataset));
293 	REQUIRE(rdataset->methods != NULL);
294 
295 	(rdataset->methods->current)(rdataset, rdata);
296 }
297 
298 #define MAX_SHUFFLE	32
299 #define WANT_FIXED(r)	(((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
300 #define WANT_RANDOM(r)	(((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
301 
302 struct towire_sort {
303 	int key;
304 	dns_rdata_t *rdata;
305 };
306 
307 static int
towire_compare(const void * av,const void * bv)308 towire_compare(const void *av, const void *bv) {
309 	const struct towire_sort *a = (const struct towire_sort *) av;
310 	const struct towire_sort *b = (const struct towire_sort *) bv;
311 	return (a->key - b->key);
312 }
313 
314 static isc_result_t
towiresorted(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,dns_rdatasetorderfunc_t order,const void * order_arg,isc_boolean_t partial,unsigned int options,unsigned int * countp,void ** state)315 towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
316 	     dns_compress_t *cctx, isc_buffer_t *target,
317 	     dns_rdatasetorderfunc_t order, const void *order_arg,
318 	     isc_boolean_t partial, unsigned int options,
319 	     unsigned int *countp, void **state)
320 {
321 	dns_rdata_t rdata = DNS_RDATA_INIT;
322 	isc_region_t r;
323 	isc_result_t result;
324 	unsigned int i, count = 0, added, choice;
325 	isc_buffer_t savedbuffer, rdlen, rrbuffer;
326 	unsigned int headlen;
327 	isc_boolean_t question = ISC_FALSE;
328 	isc_boolean_t shuffle = ISC_FALSE;
329 	dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
330 	struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
331 
332 	UNUSED(state);
333 
334 	/*
335 	 * Convert 'rdataset' to wire format, compressing names as specified
336 	 * in cctx, and storing the result in 'target'.
337 	 */
338 
339 	REQUIRE(DNS_RDATASET_VALID(rdataset));
340 	REQUIRE(countp != NULL);
341 	REQUIRE((order == NULL) == (order_arg == NULL));
342 	REQUIRE(cctx != NULL && cctx->mctx != NULL);
343 
344 	if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
345 		question = ISC_TRUE;
346 		count = 1;
347 		result = dns_rdataset_first(rdataset);
348 		INSIST(result == ISC_R_NOMORE);
349 	} else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
350 		/*
351 		 * This is a negative caching rdataset.
352 		 */
353 		unsigned int ncache_opts = 0;
354 		if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
355 			ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
356 		return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
357 					  countp));
358 	} else {
359 		count = (rdataset->methods->count)(rdataset);
360 		result = dns_rdataset_first(rdataset);
361 		if (result == ISC_R_NOMORE)
362 			return (ISC_R_SUCCESS);
363 		if (result != ISC_R_SUCCESS)
364 			return (result);
365 	}
366 
367 	/*
368 	 * Do we want to shuffle this answer?
369 	 */
370 	if (!question && count > 1 &&
371 	    (!WANT_FIXED(rdataset) || order != NULL) &&
372 	    rdataset->type != dns_rdatatype_rrsig)
373 		shuffle = ISC_TRUE;
374 
375 	if (shuffle && count > MAX_SHUFFLE) {
376 		shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
377 		sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
378 		if (shuffled == NULL || sorted == NULL)
379 			shuffle = ISC_FALSE;
380 	} else {
381 		shuffled = shuffled_fixed;
382 		sorted = sorted_fixed;
383 	}
384 
385 	if (shuffle) {
386 		/*
387 		 * First we get handles to all of the rdata.
388 		 */
389 		i = 0;
390 		do {
391 			INSIST(i < count);
392 			dns_rdata_init(&shuffled[i]);
393 			dns_rdataset_current(rdataset, &shuffled[i]);
394 			i++;
395 			result = dns_rdataset_next(rdataset);
396 		} while (result == ISC_R_SUCCESS);
397 		if (result != ISC_R_NOMORE)
398 			goto cleanup;
399 		INSIST(i == count);
400 
401 		/*
402 		 * Now we shuffle.
403 		 */
404 		if (WANT_FIXED(rdataset)) {
405 			/*
406 			 * 'Fixed' order.
407 			 */
408 			INSIST(order != NULL);
409 			for (i = 0; i < count; i++) {
410 				sorted[i].key = (*order)(&shuffled[i],
411 							 order_arg);
412 				sorted[i].rdata = &shuffled[i];
413 			}
414 		} else if (WANT_RANDOM(rdataset)) {
415 			/*
416 			 * 'Random' order.
417 			 */
418 			for (i = 0; i < count; i++) {
419 				isc_uint32_t val;
420 
421 				isc_random_get(&val);
422 				choice = i + (val % (count - i));
423 				rdata = shuffled[i];
424 				shuffled[i] = shuffled[choice];
425 				shuffled[choice] = rdata;
426 				if (order != NULL)
427 					sorted[i].key = (*order)(&shuffled[i],
428 								 order_arg);
429 				else
430 					sorted[i].key = 0; /* Unused */
431 				sorted[i].rdata = &shuffled[i];
432 			}
433 		} else {
434 			/*
435 			 * "Cyclic" order.
436 			 */
437 			isc_uint32_t val;
438 			unsigned int j;
439 
440 			val = rdataset->count;
441 			if (val == ISC_UINT32_MAX)
442 				isc_random_get(&val);
443 			j = val % count;
444 			for (i = 0; i < count; i++) {
445 				if (order != NULL)
446 					sorted[i].key = (*order)(&shuffled[j],
447 								 order_arg);
448 				else
449 					sorted[i].key = 0; /* Unused */
450 				sorted[i].rdata = &shuffled[j];
451 				j++;
452 				if (j == count)
453 					j = 0; /* Wrap around. */
454 			}
455 		}
456 
457 		/*
458 		 * Sorted order.
459 		 */
460 		if (order != NULL)
461 			qsort(sorted, count, sizeof(sorted[0]),
462 			      towire_compare);
463 	}
464 
465 	savedbuffer = *target;
466 	i = 0;
467 	added = 0;
468 
469 	do {
470 		/*
471 		 * Copy out the name, type, class, ttl.
472 		 */
473 
474 		rrbuffer = *target;
475 		dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
476 		result = dns_name_towire(owner_name, cctx, target);
477 		if (result != ISC_R_SUCCESS)
478 			goto rollback;
479 		headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
480 		if (!question)
481 			headlen += sizeof(dns_ttl_t)
482 				+ 2;  /* XXX 2 for rdata len */
483 		isc_buffer_availableregion(target, &r);
484 		if (r.length < headlen) {
485 			result = ISC_R_NOSPACE;
486 			goto rollback;
487 		}
488 		isc_buffer_putuint16(target, rdataset->type);
489 		isc_buffer_putuint16(target, rdataset->rdclass);
490 		if (!question) {
491 			isc_buffer_putuint32(target, rdataset->ttl);
492 
493 			/*
494 			 * Save space for rdlen.
495 			 */
496 			rdlen = *target;
497 			isc_buffer_add(target, 2);
498 
499 			/*
500 			 * Copy out the rdata
501 			 */
502 			if (shuffle)
503 				rdata = *(sorted[i].rdata);
504 			else {
505 				dns_rdata_reset(&rdata);
506 				dns_rdataset_current(rdataset, &rdata);
507 			}
508 			result = dns_rdata_towire(&rdata, cctx, target);
509 			if (result != ISC_R_SUCCESS)
510 				goto rollback;
511 			INSIST((target->used >= rdlen.used + 2) &&
512 			       (target->used - rdlen.used - 2 < 65536));
513 			isc_buffer_putuint16(&rdlen,
514 					     (isc_uint16_t)(target->used -
515 							    rdlen.used - 2));
516 			added++;
517 		}
518 
519 		if (shuffle) {
520 			i++;
521 			if (i == count)
522 				result = ISC_R_NOMORE;
523 			else
524 				result = ISC_R_SUCCESS;
525 		} else {
526 			result = dns_rdataset_next(rdataset);
527 		}
528 	} while (result == ISC_R_SUCCESS);
529 
530 	if (result != ISC_R_NOMORE)
531 		goto rollback;
532 
533 	*countp += count;
534 
535 	result = ISC_R_SUCCESS;
536 	goto cleanup;
537 
538  rollback:
539 	if (partial && result == ISC_R_NOSPACE) {
540 		INSIST(rrbuffer.used < 65536);
541 		dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
542 		*countp += added;
543 		*target = rrbuffer;
544 		goto cleanup;
545 	}
546 	INSIST(savedbuffer.used < 65536);
547 	dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
548 	*countp = 0;
549 	*target = savedbuffer;
550 
551  cleanup:
552 	if (sorted != NULL && sorted != sorted_fixed)
553 		isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
554 	if (shuffled != NULL && shuffled != shuffled_fixed)
555 		isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
556 	return (result);
557 }
558 
559 isc_result_t
dns_rdataset_towiresorted(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,dns_rdatasetorderfunc_t order,const void * order_arg,unsigned int options,unsigned int * countp)560 dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
561 			  const dns_name_t *owner_name,
562 			  dns_compress_t *cctx,
563 			  isc_buffer_t *target,
564 			  dns_rdatasetorderfunc_t order,
565 			  const void *order_arg,
566 			  unsigned int options,
567 			  unsigned int *countp)
568 {
569 	return (towiresorted(rdataset, owner_name, cctx, target,
570 			     order, order_arg, ISC_FALSE, options,
571 			     countp, NULL));
572 }
573 
574 isc_result_t
dns_rdataset_towirepartial(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,dns_rdatasetorderfunc_t order,const void * order_arg,unsigned int options,unsigned int * countp,void ** state)575 dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
576 			   const dns_name_t *owner_name,
577 			   dns_compress_t *cctx,
578 			   isc_buffer_t *target,
579 			   dns_rdatasetorderfunc_t order,
580 			   const void *order_arg,
581 			   unsigned int options,
582 			   unsigned int *countp,
583 			   void **state)
584 {
585 	REQUIRE(state == NULL);	/* XXX remove when implemented */
586 	return (towiresorted(rdataset, owner_name, cctx, target,
587 			     order, order_arg, ISC_TRUE, options,
588 			     countp, state));
589 }
590 
591 isc_result_t
dns_rdataset_towire(dns_rdataset_t * rdataset,dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,unsigned int options,unsigned int * countp)592 dns_rdataset_towire(dns_rdataset_t *rdataset,
593 		    dns_name_t *owner_name,
594 		    dns_compress_t *cctx,
595 		    isc_buffer_t *target,
596 		    unsigned int options,
597 		    unsigned int *countp)
598 {
599 	return (towiresorted(rdataset, owner_name, cctx, target,
600 			     NULL, NULL, ISC_FALSE, options, countp, NULL));
601 }
602 
603 isc_result_t
dns_rdataset_additionaldata(dns_rdataset_t * rdataset,dns_additionaldatafunc_t add,void * arg)604 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
605 			    dns_additionaldatafunc_t add, void *arg)
606 {
607 	dns_rdata_t rdata = DNS_RDATA_INIT;
608 	isc_result_t result;
609 
610 	/*
611 	 * For each rdata in rdataset, call 'add' for each name and type in the
612 	 * rdata which is subject to additional section processing.
613 	 */
614 
615 	REQUIRE(DNS_RDATASET_VALID(rdataset));
616 	REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
617 
618 	result = dns_rdataset_first(rdataset);
619 	if (result != ISC_R_SUCCESS)
620 		return (result);
621 
622 	do {
623 		dns_rdataset_current(rdataset, &rdata);
624 		result = dns_rdata_additionaldata(&rdata, add, arg);
625 		if (result == ISC_R_SUCCESS)
626 			result = dns_rdataset_next(rdataset);
627 		dns_rdata_reset(&rdata);
628 	} while (result == ISC_R_SUCCESS);
629 
630 	if (result != ISC_R_NOMORE)
631 		return (result);
632 
633 	return (ISC_R_SUCCESS);
634 }
635 
636 isc_result_t
dns_rdataset_addnoqname(dns_rdataset_t * rdataset,dns_name_t * name)637 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
638 
639 	REQUIRE(DNS_RDATASET_VALID(rdataset));
640 	REQUIRE(rdataset->methods != NULL);
641 	if (rdataset->methods->addnoqname == NULL)
642 		return (ISC_R_NOTIMPLEMENTED);
643 	return((rdataset->methods->addnoqname)(rdataset, name));
644 }
645 
646 isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)647 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
648 			dns_rdataset_t *neg, dns_rdataset_t *negsig)
649 {
650 	REQUIRE(DNS_RDATASET_VALID(rdataset));
651 	REQUIRE(rdataset->methods != NULL);
652 
653 	if (rdataset->methods->getnoqname == NULL)
654 		return (ISC_R_NOTIMPLEMENTED);
655 	return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
656 }
657 
658 isc_result_t
dns_rdataset_addclosest(dns_rdataset_t * rdataset,dns_name_t * name)659 dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
660 
661 	REQUIRE(DNS_RDATASET_VALID(rdataset));
662 	REQUIRE(rdataset->methods != NULL);
663 	if (rdataset->methods->addclosest == NULL)
664 		return (ISC_R_NOTIMPLEMENTED);
665 	return((rdataset->methods->addclosest)(rdataset, name));
666 }
667 
668 isc_result_t
dns_rdataset_getclosest(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)669 dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
670 			dns_rdataset_t *neg, dns_rdataset_t *negsig)
671 {
672 	REQUIRE(DNS_RDATASET_VALID(rdataset));
673 	REQUIRE(rdataset->methods != NULL);
674 
675 	if (rdataset->methods->getclosest == NULL)
676 		return (ISC_R_NOTIMPLEMENTED);
677 	return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
678 }
679 
680 /*
681  * Additional cache stuff
682  */
683 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)684 dns_rdataset_getadditional(dns_rdataset_t *rdataset,
685 			   dns_rdatasetadditional_t type,
686 			   dns_rdatatype_t qtype,
687 			   dns_acache_t *acache,
688 			   dns_zone_t **zonep,
689 			   dns_db_t **dbp,
690 			   dns_dbversion_t **versionp,
691 			   dns_dbnode_t **nodep,
692 			   dns_name_t *fname,
693 			   dns_message_t *msg,
694 			   isc_stdtime_t now)
695 {
696 	REQUIRE(DNS_RDATASET_VALID(rdataset));
697 	REQUIRE(rdataset->methods != NULL);
698 	REQUIRE(zonep == NULL || *zonep == NULL);
699 	REQUIRE(dbp != NULL && *dbp == NULL);
700 	REQUIRE(versionp != NULL && *versionp == NULL);
701 	REQUIRE(nodep != NULL && *nodep == NULL);
702 	REQUIRE(fname != NULL);
703 	REQUIRE(msg != NULL);
704 
705 	if (acache != NULL && rdataset->methods->getadditional != NULL) {
706 		return ((rdataset->methods->getadditional)(rdataset, type,
707 							   qtype, acache,
708 							   zonep, dbp,
709 							   versionp, nodep,
710 							   fname, msg, now));
711 	}
712 
713 	return (ISC_R_FAILURE);
714 }
715 
716 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)717 dns_rdataset_setadditional(dns_rdataset_t *rdataset,
718 			   dns_rdatasetadditional_t type,
719 			   dns_rdatatype_t qtype,
720 			   dns_acache_t *acache,
721 			   dns_zone_t *zone,
722 			   dns_db_t *db,
723 			   dns_dbversion_t *version,
724 			   dns_dbnode_t *node,
725 			   dns_name_t *fname)
726 {
727 	REQUIRE(DNS_RDATASET_VALID(rdataset));
728 	REQUIRE(rdataset->methods != NULL);
729 
730 	if (acache != NULL && rdataset->methods->setadditional != NULL) {
731 		return ((rdataset->methods->setadditional)(rdataset, type,
732 							   qtype, acache, zone,
733 							   db, version,
734 							   node, fname));
735 	}
736 
737 	return (ISC_R_FAILURE);
738 }
739 
740 isc_result_t
dns_rdataset_putadditional(dns_acache_t * acache,dns_rdataset_t * rdataset,dns_rdatasetadditional_t type,dns_rdatatype_t qtype)741 dns_rdataset_putadditional(dns_acache_t *acache,
742 			   dns_rdataset_t *rdataset,
743 			   dns_rdatasetadditional_t type,
744 			   dns_rdatatype_t qtype)
745 {
746 	REQUIRE(DNS_RDATASET_VALID(rdataset));
747 	REQUIRE(rdataset->methods != NULL);
748 
749 	if (acache != NULL && rdataset->methods->putadditional != NULL) {
750 		return ((rdataset->methods->putadditional)(acache, rdataset,
751 							   type, qtype));
752 	}
753 
754 	return (ISC_R_FAILURE);
755 }
756 
757 void
dns_rdataset_settrust(dns_rdataset_t * rdataset,dns_trust_t trust)758 dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
759 	REQUIRE(DNS_RDATASET_VALID(rdataset));
760 	REQUIRE(rdataset->methods != NULL);
761 
762 	if (rdataset->methods->settrust != NULL)
763 		(rdataset->methods->settrust)(rdataset, trust);
764 	else
765 		rdataset->trust = trust;
766 }
767 
768 void
dns_rdataset_expire(dns_rdataset_t * rdataset)769 dns_rdataset_expire(dns_rdataset_t *rdataset) {
770 	REQUIRE(DNS_RDATASET_VALID(rdataset));
771 	REQUIRE(rdataset->methods != NULL);
772 
773 	if (rdataset->methods->expire != NULL)
774 		(rdataset->methods->expire)(rdataset);
775 }
776 
777 void
dns_rdataset_trimttl(dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,dns_rdata_rrsig_t * rrsig,isc_stdtime_t now,isc_boolean_t acceptexpired)778 dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
779 		     dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
780 		     isc_boolean_t acceptexpired)
781 {
782 	isc_uint32_t ttl = 0;
783 
784 	REQUIRE(DNS_RDATASET_VALID(rdataset));
785 	REQUIRE(DNS_RDATASET_VALID(sigrdataset));
786 	REQUIRE(rrsig != NULL);
787 
788 	/*
789 	 * If we accept expired RRsets keep them for no more than 120 seconds.
790 	 */
791 	if (acceptexpired &&
792 	    (isc_serial_le(rrsig->timeexpire, ((now + 120) & 0xffffffff)) ||
793 	     isc_serial_le(rrsig->timeexpire, now)))
794 		ttl = 120;
795 	else if (isc_serial_ge(rrsig->timeexpire, now))
796 		ttl = rrsig->timeexpire - now;
797 
798 	ttl = ISC_MIN(ISC_MIN(rdataset->ttl, sigrdataset->ttl),
799 		      ISC_MIN(rrsig->originalttl, ttl));
800 	rdataset->ttl = ttl;
801 	sigrdataset->ttl = ttl;
802 }
803