]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/bind9/lib/dns/rdatalist.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / bind9 / lib / dns / rdatalist.c
1 /*
2  * Copyright (C) 2004, 2005, 2007, 2008, 2010  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001, 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: rdatalist.c,v 1.36.336.2 2010/02/25 10:57:12 tbox Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <stddef.h>
25
26 #include <isc/util.h>
27
28 #include <dns/name.h>
29 #include <dns/nsec3.h>
30 #include <dns/rdata.h>
31 #include <dns/rdatalist.h>
32 #include <dns/rdataset.h>
33
34 #include "rdatalist_p.h"
35
36 static dns_rdatasetmethods_t methods = {
37         isc__rdatalist_disassociate,
38         isc__rdatalist_first,
39         isc__rdatalist_next,
40         isc__rdatalist_current,
41         isc__rdatalist_clone,
42         isc__rdatalist_count,
43         isc__rdatalist_addnoqname,
44         isc__rdatalist_getnoqname,
45         isc__rdatalist_addclosest,
46         isc__rdatalist_getclosest,
47         NULL,
48         NULL,
49         NULL,
50         NULL,
51         NULL
52 };
53
54 void
55 dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
56
57         /*
58          * Initialize rdatalist.
59          */
60
61         rdatalist->rdclass = 0;
62         rdatalist->type = 0;
63         rdatalist->covers = 0;
64         rdatalist->ttl = 0;
65         ISC_LIST_INIT(rdatalist->rdata);
66         ISC_LINK_INIT(rdatalist, link);
67 }
68
69 isc_result_t
70 dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
71                          dns_rdataset_t *rdataset)
72 {
73         /*
74          * Make 'rdataset' refer to the rdata in 'rdatalist'.
75          */
76
77         REQUIRE(rdatalist != NULL);
78         REQUIRE(DNS_RDATASET_VALID(rdataset));
79         REQUIRE(! dns_rdataset_isassociated(rdataset));
80
81         rdataset->methods = &methods;
82         rdataset->rdclass = rdatalist->rdclass;
83         rdataset->type = rdatalist->type;
84         rdataset->covers = rdatalist->covers;
85         rdataset->ttl = rdatalist->ttl;
86         rdataset->trust = 0;
87         rdataset->private1 = rdatalist;
88         rdataset->private2 = NULL;
89         rdataset->private3 = NULL;
90         rdataset->privateuint4 = 0;
91         rdataset->private5 = NULL;
92
93         return (ISC_R_SUCCESS);
94 }
95
96 isc_result_t
97 dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
98                            dns_rdatalist_t **rdatalist)
99 {
100         REQUIRE(rdatalist != NULL && rdataset != NULL);
101         *rdatalist = rdataset->private1;
102
103         return (ISC_R_SUCCESS);
104 }
105
106 void
107 isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
108         UNUSED(rdataset);
109 }
110
111 isc_result_t
112 isc__rdatalist_first(dns_rdataset_t *rdataset) {
113         dns_rdatalist_t *rdatalist;
114
115         rdatalist = rdataset->private1;
116         rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata);
117
118         if (rdataset->private2 == NULL)
119                 return (ISC_R_NOMORE);
120
121         return (ISC_R_SUCCESS);
122 }
123
124 isc_result_t
125 isc__rdatalist_next(dns_rdataset_t *rdataset) {
126         dns_rdata_t *rdata;
127
128         rdata = rdataset->private2;
129         if (rdata == NULL)
130                 return (ISC_R_NOMORE);
131
132         rdataset->private2 = ISC_LIST_NEXT(rdata, link);
133
134         if (rdataset->private2 == NULL)
135                 return (ISC_R_NOMORE);
136
137         return (ISC_R_SUCCESS);
138 }
139
140 void
141 isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
142         dns_rdata_t *list_rdata;
143
144         list_rdata = rdataset->private2;
145         INSIST(list_rdata != NULL);
146
147         dns_rdata_clone(list_rdata, rdata);
148 }
149
150 void
151 isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
152         *target = *source;
153
154         /*
155          * Reset iterator state.
156          */
157         target->private2 = NULL;
158 }
159
160 unsigned int
161 isc__rdatalist_count(dns_rdataset_t *rdataset) {
162         dns_rdatalist_t *rdatalist;
163         dns_rdata_t *rdata;
164         unsigned int count;
165
166         rdatalist = rdataset->private1;
167
168         count = 0;
169         for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
170              rdata != NULL;
171              rdata = ISC_LIST_NEXT(rdata, link))
172                 count++;
173
174         return (count);
175 }
176
177 isc_result_t
178 isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
179         dns_rdataset_t *neg = NULL;
180         dns_rdataset_t *negsig = NULL;
181         dns_rdataset_t *rdset;
182         dns_ttl_t ttl;
183
184         for (rdset = ISC_LIST_HEAD(name->list);
185              rdset != NULL;
186              rdset = ISC_LIST_NEXT(rdset, link))
187         {
188                 if (rdset->rdclass != rdataset->rdclass)
189                         continue;
190                 if (rdset->type == dns_rdatatype_nsec ||
191                     rdset->type == dns_rdatatype_nsec3)
192                         neg = rdset;
193         }
194         if (neg == NULL)
195                 return (ISC_R_NOTFOUND);
196
197         for (rdset = ISC_LIST_HEAD(name->list);
198              rdset != NULL;
199              rdset = ISC_LIST_NEXT(rdset, link))
200         {
201                 if (rdset->type == dns_rdatatype_rrsig &&
202                     rdset->covers == neg->type)
203                         negsig = rdset;
204         }
205
206         if (negsig == NULL)
207                 return (ISC_R_NOTFOUND);
208         /*
209          * Minimise ttl.
210          */
211         ttl = rdataset->ttl;
212         if (neg->ttl < ttl)
213                 ttl = neg->ttl;
214         if (negsig->ttl < ttl)
215                 ttl = negsig->ttl;
216         rdataset->ttl = neg->ttl = negsig->ttl = ttl;
217         rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
218         rdataset->private6 = name;
219         return (ISC_R_SUCCESS);
220 }
221
222 isc_result_t
223 isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
224                           dns_rdataset_t *neg, dns_rdataset_t *negsig)
225 {
226         dns_rdataclass_t rdclass = rdataset->rdclass;
227         dns_rdataset_t *tneg = NULL;
228         dns_rdataset_t *tnegsig = NULL;
229         dns_name_t *noqname = rdataset->private6;
230
231         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
232         (void)dns_name_dynamic(noqname);        /* Sanity Check. */
233
234         for (rdataset = ISC_LIST_HEAD(noqname->list);
235              rdataset != NULL;
236              rdataset = ISC_LIST_NEXT(rdataset, link))
237         {
238                 if (rdataset->rdclass != rdclass)
239                         continue;
240                 if (rdataset->type == dns_rdatatype_nsec ||
241                     rdataset->type == dns_rdatatype_nsec3)
242                         tneg = rdataset;
243         }
244         if (tneg == NULL)
245                 return (ISC_R_NOTFOUND);
246
247         for (rdataset = ISC_LIST_HEAD(noqname->list);
248              rdataset != NULL;
249              rdataset = ISC_LIST_NEXT(rdataset, link))
250         {
251                 if (rdataset->type == dns_rdatatype_rrsig &&
252                     rdataset->covers == tneg->type)
253                         tnegsig = rdataset;
254         }
255         if (tnegsig == NULL)
256                 return (ISC_R_NOTFOUND);
257
258         dns_name_clone(noqname, name);
259         dns_rdataset_clone(tneg, neg);
260         dns_rdataset_clone(tnegsig, negsig);
261         return (ISC_R_SUCCESS);
262 }
263
264 isc_result_t
265 isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
266         dns_rdataset_t *neg = NULL;
267         dns_rdataset_t *negsig = NULL;
268         dns_rdataset_t *rdset;
269         dns_ttl_t ttl;
270
271         for (rdset = ISC_LIST_HEAD(name->list);
272              rdset != NULL;
273              rdset = ISC_LIST_NEXT(rdset, link))
274         {
275                 if (rdset->rdclass != rdataset->rdclass)
276                         continue;
277                 if (rdset->type == dns_rdatatype_nsec ||
278                     rdset->type == dns_rdatatype_nsec3)
279                         neg = rdset;
280         }
281         if (neg == NULL)
282                 return (ISC_R_NOTFOUND);
283
284         for (rdset = ISC_LIST_HEAD(name->list);
285              rdset != NULL;
286              rdset = ISC_LIST_NEXT(rdset, link))
287         {
288                 if (rdset->type == dns_rdatatype_rrsig &&
289                     rdset->covers == neg->type)
290                         negsig = rdset;
291         }
292
293         if (negsig == NULL)
294                 return (ISC_R_NOTFOUND);
295         /*
296          * Minimise ttl.
297          */
298         ttl = rdataset->ttl;
299         if (neg->ttl < ttl)
300                 ttl = neg->ttl;
301         if (negsig->ttl < ttl)
302                 ttl = negsig->ttl;
303         rdataset->ttl = neg->ttl = negsig->ttl = ttl;
304         rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
305         rdataset->private7 = name;
306         return (ISC_R_SUCCESS);
307 }
308
309 isc_result_t
310 isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
311                           dns_rdataset_t *neg, dns_rdataset_t *negsig)
312 {
313         dns_rdataclass_t rdclass = rdataset->rdclass;
314         dns_rdataset_t *tneg = NULL;
315         dns_rdataset_t *tnegsig = NULL;
316         dns_name_t *closest = rdataset->private7;
317
318         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
319         (void)dns_name_dynamic(closest);        /* Sanity Check. */
320
321         for (rdataset = ISC_LIST_HEAD(closest->list);
322              rdataset != NULL;
323              rdataset = ISC_LIST_NEXT(rdataset, link))
324         {
325                 if (rdataset->rdclass != rdclass)
326                         continue;
327                 if (rdataset->type == dns_rdatatype_nsec ||
328                     rdataset->type == dns_rdatatype_nsec3)
329                         tneg = rdataset;
330         }
331         if (tneg == NULL)
332                 return (ISC_R_NOTFOUND);
333
334         for (rdataset = ISC_LIST_HEAD(closest->list);
335              rdataset != NULL;
336              rdataset = ISC_LIST_NEXT(rdataset, link))
337         {
338                 if (rdataset->type == dns_rdatatype_rrsig &&
339                     rdataset->covers == tneg->type)
340                         tnegsig = rdataset;
341         }
342         if (tnegsig == NULL)
343                 return (ISC_R_NOTFOUND);
344
345         dns_name_clone(closest, name);
346         dns_rdataset_clone(tneg, neg);
347         dns_rdataset_clone(tnegsig, negsig);
348         return (ISC_R_SUCCESS);
349 }