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