xref: /minix/external/bsd/bind/dist/lib/dns/rdatalist.c (revision 00b67f09)
1 /*	$NetBSD: rdatalist.c,v 1.6 2015/07/08 17:28:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007, 2008, 2010-2012, 2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id */
21 
22 /*! \file */
23 
24 #include <config.h>
25 
26 #include <stddef.h>
27 
28 #include <isc/util.h>
29 
30 #include <dns/name.h>
31 #include <dns/nsec3.h>
32 #include <dns/rdata.h>
33 #include <dns/rdatalist.h>
34 #include <dns/rdataset.h>
35 
36 #include "rdatalist_p.h"
37 
38 static dns_rdatasetmethods_t methods = {
39 	isc__rdatalist_disassociate,
40 	isc__rdatalist_first,
41 	isc__rdatalist_next,
42 	isc__rdatalist_current,
43 	isc__rdatalist_clone,
44 	isc__rdatalist_count,
45 	isc__rdatalist_addnoqname,
46 	isc__rdatalist_getnoqname,
47 	isc__rdatalist_addclosest,
48 	isc__rdatalist_getclosest,
49 	NULL,
50 	NULL,
51 	NULL,
52 	NULL,
53 	NULL,
54 	NULL
55 };
56 
57 void
dns_rdatalist_init(dns_rdatalist_t * rdatalist)58 dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
59 
60 	REQUIRE(rdatalist != NULL);
61 
62 	/*
63 	 * Initialize rdatalist.
64 	 */
65 
66 	rdatalist->rdclass = 0;
67 	rdatalist->type = 0;
68 	rdatalist->covers = 0;
69 	rdatalist->ttl = 0;
70 	ISC_LIST_INIT(rdatalist->rdata);
71 	ISC_LINK_INIT(rdatalist, link);
72 }
73 
74 isc_result_t
dns_rdatalist_tordataset(dns_rdatalist_t * rdatalist,dns_rdataset_t * rdataset)75 dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
76 			 dns_rdataset_t *rdataset)
77 {
78 	/*
79 	 * Make 'rdataset' refer to the rdata in 'rdatalist'.
80 	 */
81 
82 	REQUIRE(rdatalist != NULL);
83 	REQUIRE(DNS_RDATASET_VALID(rdataset));
84 	REQUIRE(! dns_rdataset_isassociated(rdataset));
85 
86 	rdataset->methods = &methods;
87 	rdataset->rdclass = rdatalist->rdclass;
88 	rdataset->type = rdatalist->type;
89 	rdataset->covers = rdatalist->covers;
90 	rdataset->ttl = rdatalist->ttl;
91 	rdataset->trust = 0;
92 	rdataset->private1 = rdatalist;
93 	rdataset->private2 = NULL;
94 	rdataset->private3 = NULL;
95 	rdataset->privateuint4 = 0;
96 	rdataset->private5 = NULL;
97 
98 	return (ISC_R_SUCCESS);
99 }
100 
101 isc_result_t
dns_rdatalist_fromrdataset(dns_rdataset_t * rdataset,dns_rdatalist_t ** rdatalist)102 dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
103 			   dns_rdatalist_t **rdatalist)
104 {
105 	REQUIRE(rdatalist != NULL && rdataset != NULL);
106 	*rdatalist = rdataset->private1;
107 
108 	return (ISC_R_SUCCESS);
109 }
110 
111 void
isc__rdatalist_disassociate(dns_rdataset_t * rdataset)112 isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
113 	UNUSED(rdataset);
114 }
115 
116 isc_result_t
isc__rdatalist_first(dns_rdataset_t * rdataset)117 isc__rdatalist_first(dns_rdataset_t *rdataset) {
118 	dns_rdatalist_t *rdatalist;
119 
120 	rdatalist = rdataset->private1;
121 	rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata);
122 
123 	if (rdataset->private2 == NULL)
124 		return (ISC_R_NOMORE);
125 
126 	return (ISC_R_SUCCESS);
127 }
128 
129 isc_result_t
isc__rdatalist_next(dns_rdataset_t * rdataset)130 isc__rdatalist_next(dns_rdataset_t *rdataset) {
131 	dns_rdata_t *rdata;
132 
133 	REQUIRE(rdataset != NULL);
134 
135 	rdata = rdataset->private2;
136 	if (rdata == NULL)
137 		return (ISC_R_NOMORE);
138 
139 	rdataset->private2 = ISC_LIST_NEXT(rdata, link);
140 
141 	if (rdataset->private2 == NULL)
142 		return (ISC_R_NOMORE);
143 
144 	return (ISC_R_SUCCESS);
145 }
146 
147 void
isc__rdatalist_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)148 isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
149 	dns_rdata_t *list_rdata;
150 
151 	REQUIRE(rdataset != NULL);
152 
153 	list_rdata = rdataset->private2;
154 	INSIST(list_rdata != NULL);
155 
156 	dns_rdata_clone(list_rdata, rdata);
157 }
158 
159 void
isc__rdatalist_clone(dns_rdataset_t * source,dns_rdataset_t * target)160 isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
161 
162 	REQUIRE(source != NULL);
163 	REQUIRE(target != NULL);
164 
165 	*target = *source;
166 
167 	/*
168 	 * Reset iterator state.
169 	 */
170 	target->private2 = NULL;
171 }
172 
173 unsigned int
isc__rdatalist_count(dns_rdataset_t * rdataset)174 isc__rdatalist_count(dns_rdataset_t *rdataset) {
175 	dns_rdatalist_t *rdatalist;
176 	dns_rdata_t *rdata;
177 	unsigned int count;
178 
179 	REQUIRE(rdataset != NULL);
180 
181 	rdatalist = rdataset->private1;
182 
183 	count = 0;
184 	for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
185 	     rdata != NULL;
186 	     rdata = ISC_LIST_NEXT(rdata, link))
187 		count++;
188 
189 	return (count);
190 }
191 
192 isc_result_t
isc__rdatalist_addnoqname(dns_rdataset_t * rdataset,dns_name_t * name)193 isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
194 	dns_rdataset_t *neg = NULL;
195 	dns_rdataset_t *negsig = NULL;
196 	dns_rdataset_t *rdset;
197 	dns_ttl_t ttl;
198 
199 	REQUIRE(rdataset != NULL);
200 
201 	for (rdset = ISC_LIST_HEAD(name->list);
202 	     rdset != NULL;
203 	     rdset = ISC_LIST_NEXT(rdset, link))
204 	{
205 		if (rdset->rdclass != rdataset->rdclass)
206 			continue;
207 		if (rdset->type == dns_rdatatype_nsec ||
208 		    rdset->type == dns_rdatatype_nsec3)
209 			neg = rdset;
210 	}
211 	if (neg == NULL)
212 		return (ISC_R_NOTFOUND);
213 
214 	for (rdset = ISC_LIST_HEAD(name->list);
215 	     rdset != NULL;
216 	     rdset = ISC_LIST_NEXT(rdset, link))
217 	{
218 		if (rdset->type == dns_rdatatype_rrsig &&
219 		    rdset->covers == neg->type)
220 			negsig = rdset;
221 	}
222 
223 	if (negsig == NULL)
224 		return (ISC_R_NOTFOUND);
225 	/*
226 	 * Minimise ttl.
227 	 */
228 	ttl = rdataset->ttl;
229 	if (neg->ttl < ttl)
230 		ttl = neg->ttl;
231 	if (negsig->ttl < ttl)
232 		ttl = negsig->ttl;
233 	rdataset->ttl = neg->ttl = negsig->ttl = ttl;
234 	rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
235 	rdataset->private6 = name;
236 	return (ISC_R_SUCCESS);
237 }
238 
239 isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)240 isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
241 			  dns_rdataset_t *neg, dns_rdataset_t *negsig)
242 {
243 	dns_rdataclass_t rdclass = rdataset->rdclass;
244 	dns_rdataset_t *tneg = NULL;
245 	dns_rdataset_t *tnegsig = NULL;
246 	dns_name_t *noqname = rdataset->private6;
247 
248 	REQUIRE(rdataset != NULL);
249 	REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
250 
251 	(void)dns_name_dynamic(noqname);	/* Sanity Check. */
252 
253 	for (rdataset = ISC_LIST_HEAD(noqname->list);
254 	     rdataset != NULL;
255 	     rdataset = ISC_LIST_NEXT(rdataset, link))
256 	{
257 		if (rdataset->rdclass != rdclass)
258 			continue;
259 		if (rdataset->type == dns_rdatatype_nsec ||
260 		    rdataset->type == dns_rdatatype_nsec3)
261 			tneg = rdataset;
262 	}
263 	if (tneg == NULL)
264 		return (ISC_R_NOTFOUND);
265 
266 	for (rdataset = ISC_LIST_HEAD(noqname->list);
267 	     rdataset != NULL;
268 	     rdataset = ISC_LIST_NEXT(rdataset, link))
269 	{
270 		if (rdataset->type == dns_rdatatype_rrsig &&
271 		    rdataset->covers == tneg->type)
272 			tnegsig = rdataset;
273 	}
274 	if (tnegsig == NULL)
275 		return (ISC_R_NOTFOUND);
276 
277 	dns_name_clone(noqname, name);
278 	dns_rdataset_clone(tneg, neg);
279 	dns_rdataset_clone(tnegsig, negsig);
280 	return (ISC_R_SUCCESS);
281 }
282 
283 isc_result_t
isc__rdatalist_addclosest(dns_rdataset_t * rdataset,dns_name_t * name)284 isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
285 	dns_rdataset_t *neg = NULL;
286 	dns_rdataset_t *negsig = NULL;
287 	dns_rdataset_t *rdset;
288 	dns_ttl_t ttl;
289 
290 	REQUIRE(rdataset != NULL);
291 
292 	for (rdset = ISC_LIST_HEAD(name->list);
293 	     rdset != NULL;
294 	     rdset = ISC_LIST_NEXT(rdset, link))
295 	{
296 		if (rdset->rdclass != rdataset->rdclass)
297 			continue;
298 		if (rdset->type == dns_rdatatype_nsec ||
299 		    rdset->type == dns_rdatatype_nsec3)
300 			neg = rdset;
301 	}
302 	if (neg == NULL)
303 		return (ISC_R_NOTFOUND);
304 
305 	for (rdset = ISC_LIST_HEAD(name->list);
306 	     rdset != NULL;
307 	     rdset = ISC_LIST_NEXT(rdset, link))
308 	{
309 		if (rdset->type == dns_rdatatype_rrsig &&
310 		    rdset->covers == neg->type)
311 			negsig = rdset;
312 	}
313 
314 	if (negsig == NULL)
315 		return (ISC_R_NOTFOUND);
316 	/*
317 	 * Minimise ttl.
318 	 */
319 	ttl = rdataset->ttl;
320 	if (neg->ttl < ttl)
321 		ttl = neg->ttl;
322 	if (negsig->ttl < ttl)
323 		ttl = negsig->ttl;
324 	rdataset->ttl = neg->ttl = negsig->ttl = ttl;
325 	rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
326 	rdataset->private7 = name;
327 	return (ISC_R_SUCCESS);
328 }
329 
330 isc_result_t
isc__rdatalist_getclosest(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)331 isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
332 			  dns_rdataset_t *neg, dns_rdataset_t *negsig)
333 {
334 	dns_rdataclass_t rdclass = rdataset->rdclass;
335 	dns_rdataset_t *tneg = NULL;
336 	dns_rdataset_t *tnegsig = NULL;
337 	dns_name_t *closest = rdataset->private7;
338 
339 	REQUIRE(rdataset != NULL);
340 	REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
341 
342 	(void)dns_name_dynamic(closest);	/* Sanity Check. */
343 
344 	for (rdataset = ISC_LIST_HEAD(closest->list);
345 	     rdataset != NULL;
346 	     rdataset = ISC_LIST_NEXT(rdataset, link))
347 	{
348 		if (rdataset->rdclass != rdclass)
349 			continue;
350 		if (rdataset->type == dns_rdatatype_nsec ||
351 		    rdataset->type == dns_rdatatype_nsec3)
352 			tneg = rdataset;
353 	}
354 	if (tneg == NULL)
355 		return (ISC_R_NOTFOUND);
356 
357 	for (rdataset = ISC_LIST_HEAD(closest->list);
358 	     rdataset != NULL;
359 	     rdataset = ISC_LIST_NEXT(rdataset, link))
360 	{
361 		if (rdataset->type == dns_rdatatype_rrsig &&
362 		    rdataset->covers == tneg->type)
363 			tnegsig = rdataset;
364 	}
365 	if (tnegsig == NULL)
366 		return (ISC_R_NOTFOUND);
367 
368 	dns_name_clone(closest, name);
369 	dns_rdataset_clone(tneg, neg);
370 	dns_rdataset_clone(tnegsig, negsig);
371 	return (ISC_R_SUCCESS);
372 }
373