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