1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file */
13
14 #include <stddef.h>
15 #include <string.h>
16
17 #include <isc/util.h>
18
19 #include <dns/name.h>
20 #include <dns/nsec3.h>
21 #include <dns/rdata.h>
22 #include <dns/rdatalist.h>
23 #include <dns/rdataset.h>
24
25 #include "rdatalist_p.h"
26
27 static dns_rdatasetmethods_t methods = {
28 isc__rdatalist_disassociate,
29 isc__rdatalist_first,
30 isc__rdatalist_next,
31 isc__rdatalist_current,
32 isc__rdatalist_clone,
33 isc__rdatalist_count,
34 isc__rdatalist_addnoqname,
35 isc__rdatalist_getnoqname,
36 isc__rdatalist_addclosest,
37 isc__rdatalist_getclosest,
38 NULL, /* settrust */
39 NULL, /* expire */
40 NULL, /* clearprefetch */
41 isc__rdatalist_setownercase,
42 isc__rdatalist_getownercase,
43 NULL /* addglue */
44 };
45
46 void
dns_rdatalist_init(dns_rdatalist_t * rdatalist)47 dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
48 REQUIRE(rdatalist != NULL);
49
50 /*
51 * Initialize rdatalist.
52 */
53
54 rdatalist->rdclass = 0;
55 rdatalist->type = 0;
56 rdatalist->covers = 0;
57 rdatalist->ttl = 0;
58 ISC_LIST_INIT(rdatalist->rdata);
59 ISC_LINK_INIT(rdatalist, link);
60 memset(rdatalist->upper, 0xeb, sizeof(rdatalist->upper));
61 /*
62 * Clear upper set bit.
63 */
64 rdatalist->upper[0] &= ~0x01;
65 }
66
67 isc_result_t
dns_rdatalist_tordataset(dns_rdatalist_t * rdatalist,dns_rdataset_t * rdataset)68 dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist, dns_rdataset_t *rdataset) {
69 /*
70 * Make 'rdataset' refer to the rdata in 'rdatalist'.
71 */
72
73 REQUIRE(rdatalist != NULL);
74 REQUIRE(DNS_RDATASET_VALID(rdataset));
75 REQUIRE(!dns_rdataset_isassociated(rdataset));
76
77 /* Check if dns_rdatalist_init has was called. */
78 REQUIRE(rdatalist->upper[0] == 0xea);
79
80 rdataset->methods = &methods;
81 rdataset->rdclass = rdatalist->rdclass;
82 rdataset->type = rdatalist->type;
83 rdataset->covers = rdatalist->covers;
84 rdataset->ttl = rdatalist->ttl;
85 rdataset->trust = 0;
86 rdataset->private1 = rdatalist;
87 rdataset->private2 = NULL;
88 rdataset->private3 = NULL;
89 rdataset->privateuint4 = 0;
90 rdataset->private5 = NULL;
91
92 return (ISC_R_SUCCESS);
93 }
94
95 isc_result_t
dns_rdatalist_fromrdataset(dns_rdataset_t * rdataset,dns_rdatalist_t ** rdatalist)96 dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
97 dns_rdatalist_t **rdatalist) {
98 REQUIRE(rdatalist != NULL && rdataset != NULL);
99 *rdatalist = rdataset->private1;
100
101 return (ISC_R_SUCCESS);
102 }
103
104 void
isc__rdatalist_disassociate(dns_rdataset_t * rdataset)105 isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
106 UNUSED(rdataset);
107 }
108
109 isc_result_t
isc__rdatalist_first(dns_rdataset_t * rdataset)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
120 return (ISC_R_SUCCESS);
121 }
122
123 isc_result_t
isc__rdatalist_next(dns_rdataset_t * rdataset)124 isc__rdatalist_next(dns_rdataset_t *rdataset) {
125 dns_rdata_t *rdata;
126
127 REQUIRE(rdataset != NULL);
128
129 rdata = rdataset->private2;
130 if (rdata == NULL) {
131 return (ISC_R_NOMORE);
132 }
133
134 rdataset->private2 = ISC_LIST_NEXT(rdata, link);
135
136 if (rdataset->private2 == NULL) {
137 return (ISC_R_NOMORE);
138 }
139
140 return (ISC_R_SUCCESS);
141 }
142
143 void
isc__rdatalist_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)144 isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
145 dns_rdata_t *list_rdata;
146
147 REQUIRE(rdataset != NULL);
148
149 list_rdata = rdataset->private2;
150 INSIST(list_rdata != NULL);
151
152 dns_rdata_clone(list_rdata, rdata);
153 }
154
155 void
isc__rdatalist_clone(dns_rdataset_t * source,dns_rdataset_t * target)156 isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
157 REQUIRE(source != NULL);
158 REQUIRE(target != NULL);
159
160 *target = *source;
161
162 /*
163 * Reset iterator state.
164 */
165 target->private2 = NULL;
166 }
167
168 unsigned int
isc__rdatalist_count(dns_rdataset_t * rdataset)169 isc__rdatalist_count(dns_rdataset_t *rdataset) {
170 dns_rdatalist_t *rdatalist;
171 dns_rdata_t *rdata;
172 unsigned int count;
173
174 REQUIRE(rdataset != NULL);
175
176 rdatalist = rdataset->private1;
177
178 count = 0;
179 for (rdata = ISC_LIST_HEAD(rdatalist->rdata); rdata != NULL;
180 rdata = ISC_LIST_NEXT(rdata, link))
181 {
182 count++;
183 }
184
185 return (count);
186 }
187
188 isc_result_t
isc__rdatalist_addnoqname(dns_rdataset_t * rdataset,const dns_name_t * name)189 isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, const dns_name_t *name) {
190 dns_rdataset_t *neg = NULL;
191 dns_rdataset_t *negsig = NULL;
192 dns_rdataset_t *rdset;
193 dns_ttl_t ttl;
194
195 REQUIRE(rdataset != NULL);
196
197 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL;
198 rdset = ISC_LIST_NEXT(rdset, link))
199 {
200 if (rdset->rdclass != rdataset->rdclass) {
201 continue;
202 }
203 if (rdset->type == dns_rdatatype_nsec ||
204 rdset->type == dns_rdatatype_nsec3) {
205 neg = rdset;
206 }
207 }
208 if (neg == NULL) {
209 return (ISC_R_NOTFOUND);
210 }
211
212 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL;
213 rdset = ISC_LIST_NEXT(rdset, link))
214 {
215 if (rdset->type == dns_rdatatype_rrsig &&
216 rdset->covers == neg->type) {
217 negsig = rdset;
218 }
219 }
220
221 if (negsig == NULL) {
222 return (ISC_R_NOTFOUND);
223 }
224 /*
225 * Minimise ttl.
226 */
227 ttl = rdataset->ttl;
228 if (neg->ttl < ttl) {
229 ttl = neg->ttl;
230 }
231 if (negsig->ttl < ttl) {
232 ttl = negsig->ttl;
233 }
234 rdataset->ttl = neg->ttl = negsig->ttl = ttl;
235 rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
236 rdataset->private6 = name;
237 return (ISC_R_SUCCESS);
238 }
239
240 isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)241 isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
242 dns_rdataset_t *neg, dns_rdataset_t *negsig) {
243 dns_rdataclass_t rdclass;
244 dns_rdataset_t *tneg = NULL;
245 dns_rdataset_t *tnegsig = NULL;
246 const dns_name_t *noqname;
247
248 REQUIRE(rdataset != NULL);
249 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
250
251 rdclass = rdataset->rdclass;
252 noqname = rdataset->private6;
253
254 (void)dns_name_dynamic(noqname); /* Sanity Check. */
255
256 for (rdataset = ISC_LIST_HEAD(noqname->list); rdataset != NULL;
257 rdataset = ISC_LIST_NEXT(rdataset, link))
258 {
259 if (rdataset->rdclass != rdclass) {
260 continue;
261 }
262 if (rdataset->type == dns_rdatatype_nsec ||
263 rdataset->type == dns_rdatatype_nsec3)
264 {
265 tneg = rdataset;
266 }
267 }
268 if (tneg == NULL) {
269 return (ISC_R_NOTFOUND);
270 }
271
272 for (rdataset = ISC_LIST_HEAD(noqname->list); rdataset != NULL;
273 rdataset = ISC_LIST_NEXT(rdataset, link))
274 {
275 if (rdataset->type == dns_rdatatype_rrsig &&
276 rdataset->covers == tneg->type) {
277 tnegsig = rdataset;
278 }
279 }
280 if (tnegsig == NULL) {
281 return (ISC_R_NOTFOUND);
282 }
283
284 dns_name_clone(noqname, name);
285 dns_rdataset_clone(tneg, neg);
286 dns_rdataset_clone(tnegsig, negsig);
287 return (ISC_R_SUCCESS);
288 }
289
290 isc_result_t
isc__rdatalist_addclosest(dns_rdataset_t * rdataset,const dns_name_t * name)291 isc__rdatalist_addclosest(dns_rdataset_t *rdataset, const dns_name_t *name) {
292 dns_rdataset_t *neg = NULL;
293 dns_rdataset_t *negsig = NULL;
294 dns_rdataset_t *rdset;
295 dns_ttl_t ttl;
296
297 REQUIRE(rdataset != NULL);
298
299 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL;
300 rdset = ISC_LIST_NEXT(rdset, link))
301 {
302 if (rdset->rdclass != rdataset->rdclass) {
303 continue;
304 }
305 if (rdset->type == dns_rdatatype_nsec ||
306 rdset->type == dns_rdatatype_nsec3) {
307 neg = rdset;
308 }
309 }
310 if (neg == NULL) {
311 return (ISC_R_NOTFOUND);
312 }
313
314 for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL;
315 rdset = ISC_LIST_NEXT(rdset, link))
316 {
317 if (rdset->type == dns_rdatatype_rrsig &&
318 rdset->covers == neg->type) {
319 negsig = rdset;
320 }
321 }
322
323 if (negsig == NULL) {
324 return (ISC_R_NOTFOUND);
325 }
326 /*
327 * Minimise ttl.
328 */
329 ttl = rdataset->ttl;
330 if (neg->ttl < ttl) {
331 ttl = neg->ttl;
332 }
333 if (negsig->ttl < ttl) {
334 ttl = negsig->ttl;
335 }
336 rdataset->ttl = neg->ttl = negsig->ttl = ttl;
337 rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
338 rdataset->private7 = name;
339 return (ISC_R_SUCCESS);
340 }
341
342 isc_result_t
isc__rdatalist_getclosest(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)343 isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
344 dns_rdataset_t *neg, dns_rdataset_t *negsig) {
345 dns_rdataclass_t rdclass;
346 dns_rdataset_t *tneg = NULL;
347 dns_rdataset_t *tnegsig = NULL;
348 const dns_name_t *closest;
349
350 REQUIRE(rdataset != NULL);
351 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
352
353 rdclass = rdataset->rdclass;
354 closest = rdataset->private7;
355
356 (void)dns_name_dynamic(closest); /* Sanity Check. */
357
358 for (rdataset = ISC_LIST_HEAD(closest->list); rdataset != NULL;
359 rdataset = ISC_LIST_NEXT(rdataset, link))
360 {
361 if (rdataset->rdclass != rdclass) {
362 continue;
363 }
364 if (rdataset->type == dns_rdatatype_nsec ||
365 rdataset->type == dns_rdatatype_nsec3)
366 {
367 tneg = rdataset;
368 }
369 }
370 if (tneg == NULL) {
371 return (ISC_R_NOTFOUND);
372 }
373
374 for (rdataset = ISC_LIST_HEAD(closest->list); rdataset != NULL;
375 rdataset = ISC_LIST_NEXT(rdataset, link))
376 {
377 if (rdataset->type == dns_rdatatype_rrsig &&
378 rdataset->covers == tneg->type) {
379 tnegsig = rdataset;
380 }
381 }
382 if (tnegsig == NULL) {
383 return (ISC_R_NOTFOUND);
384 }
385
386 dns_name_clone(closest, name);
387 dns_rdataset_clone(tneg, neg);
388 dns_rdataset_clone(tnegsig, negsig);
389 return (ISC_R_SUCCESS);
390 }
391
392 void
isc__rdatalist_setownercase(dns_rdataset_t * rdataset,const dns_name_t * name)393 isc__rdatalist_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
394 dns_rdatalist_t *rdatalist;
395 unsigned int i;
396
397 /*
398 * We do not need to worry about label lengths as they are all
399 * less than or equal to 63.
400 */
401 rdatalist = rdataset->private1;
402 memset(rdatalist->upper, 0, sizeof(rdatalist->upper));
403 for (i = 1; i < name->length; i++) {
404 if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) {
405 rdatalist->upper[i / 8] |= 1 << (i % 8);
406 /*
407 * Record that upper has been set.
408 */
409 }
410 }
411 /*
412 * Record that upper has been set.
413 */
414 rdatalist->upper[0] |= 0x01;
415 }
416
417 void
isc__rdatalist_getownercase(const dns_rdataset_t * rdataset,dns_name_t * name)418 isc__rdatalist_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
419 dns_rdatalist_t *rdatalist;
420 unsigned int i;
421
422 rdatalist = rdataset->private1;
423 if ((rdatalist->upper[0] & 0x01) == 0) {
424 return;
425 }
426 for (i = 0; i < name->length; i++) {
427 /*
428 * Set the case bit if it does not match the recorded bit.
429 */
430 if (name->ndata[i] >= 0x61 && name->ndata[i] <= 0x7a &&
431 (rdatalist->upper[i / 8] & (1 << (i % 8))) != 0)
432 {
433 name->ndata[i] &= ~0x20; /* clear the lower case bit */
434 } else if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a &&
435 (rdatalist->upper[i / 8] & (1 << (i % 8))) == 0)
436 {
437 name->ndata[i] |= 0x20; /* set the lower case bit */
438 }
439 }
440 }
441