4 * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
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.
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.
20 /* Id: nsec.c,v 1.13 2009/01/06 23:47:57 tbox Exp */
26 #include <isc/string.h>
31 #include <dns/rdata.h>
32 #include <dns/rdatalist.h>
33 #include <dns/rdataset.h>
34 #include <dns/rdatasetiter.h>
35 #include <dns/rdatastruct.h>
36 #include <dns/result.h>
40 #define RETERR(x) do { \
42 if (result != ISC_R_SUCCESS) \
47 set_bit(unsigned char *array
, unsigned int index
, unsigned int bit
) {
48 unsigned int shift
, mask
;
50 shift
= 7 - (index
% 8);
54 array
[index
/ 8] |= mask
;
56 array
[index
/ 8] &= (~mask
& 0xFF);
60 bit_isset(unsigned char *array
, unsigned int index
) {
61 unsigned int byte
, shift
, mask
;
63 byte
= array
[index
/ 8];
64 shift
= 7 - (index
% 8);
67 return ((byte
& mask
) != 0);
71 dns_nsec_buildrdata(dns_db_t
*db
, dns_dbversion_t
*version
,
72 dns_dbnode_t
*node
, dns_name_t
*target
,
73 unsigned char *buffer
, dns_rdata_t
*rdata
)
76 dns_rdataset_t rdataset
;
78 unsigned int i
, window
;
81 unsigned char *nsec_bits
, *bm
;
82 unsigned int max_type
;
83 dns_rdatasetiter_t
*rdsiter
;
85 memset(buffer
, 0, DNS_NSEC_BUFFERSIZE
);
86 dns_name_toregion(target
, &r
);
87 memcpy(buffer
, r
.base
, r
.length
);
90 * Use the end of the space for a raw bitmap leaving enough
91 * space for the window identifiers and length octets.
93 bm
= r
.base
+ r
.length
+ 512;
94 nsec_bits
= r
.base
+ r
.length
;
95 set_bit(bm
, dns_rdatatype_rrsig
, 1);
96 set_bit(bm
, dns_rdatatype_nsec
, 1);
97 max_type
= dns_rdatatype_nsec
;
98 dns_rdataset_init(&rdataset
);
100 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
101 if (result
!= ISC_R_SUCCESS
)
103 for (result
= dns_rdatasetiter_first(rdsiter
);
104 result
== ISC_R_SUCCESS
;
105 result
= dns_rdatasetiter_next(rdsiter
))
107 dns_rdatasetiter_current(rdsiter
, &rdataset
);
108 if (rdataset
.type
!= dns_rdatatype_nsec
&&
109 rdataset
.type
!= dns_rdatatype_nsec3
&&
110 rdataset
.type
!= dns_rdatatype_rrsig
) {
111 if (rdataset
.type
> max_type
)
112 max_type
= rdataset
.type
;
113 set_bit(bm
, rdataset
.type
, 1);
115 dns_rdataset_disassociate(&rdataset
);
119 * At zone cuts, deny the existence of glue in the parent zone.
121 if (bit_isset(bm
, dns_rdatatype_ns
) &&
122 ! bit_isset(bm
, dns_rdatatype_soa
)) {
123 for (i
= 0; i
<= max_type
; i
++) {
124 if (bit_isset(bm
, i
) &&
125 ! dns_rdatatype_iszonecutauth((dns_rdatatype_t
)i
))
130 dns_rdatasetiter_destroy(&rdsiter
);
131 if (result
!= ISC_R_NOMORE
)
134 for (window
= 0; window
< 256; window
++) {
135 if (window
* 256 > max_type
)
137 for (octet
= 31; octet
>= 0; octet
--)
138 if (bm
[window
* 32 + octet
] != 0)
142 nsec_bits
[0] = window
;
143 nsec_bits
[1] = octet
+ 1;
145 * Note: potential overlapping move.
147 memmove(&nsec_bits
[2], &bm
[window
* 32], octet
+ 1);
148 nsec_bits
+= 3 + octet
;
150 r
.length
= nsec_bits
- r
.base
;
151 INSIST(r
.length
<= DNS_NSEC_BUFFERSIZE
);
152 dns_rdata_fromregion(rdata
,
157 return (ISC_R_SUCCESS
);
162 dns_nsec_build(dns_db_t
*db
, dns_dbversion_t
*version
, dns_dbnode_t
*node
,
163 dns_name_t
*target
, dns_ttl_t ttl
)
166 dns_rdata_t rdata
= DNS_RDATA_INIT
;
167 unsigned char data
[DNS_NSEC_BUFFERSIZE
];
168 dns_rdatalist_t rdatalist
;
169 dns_rdataset_t rdataset
;
171 dns_rdataset_init(&rdataset
);
172 dns_rdata_init(&rdata
);
174 RETERR(dns_nsec_buildrdata(db
, version
, node
, target
, data
, &rdata
));
176 rdatalist
.rdclass
= dns_db_class(db
);
177 rdatalist
.type
= dns_rdatatype_nsec
;
178 rdatalist
.covers
= 0;
180 ISC_LIST_INIT(rdatalist
.rdata
);
181 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
182 RETERR(dns_rdatalist_tordataset(&rdatalist
, &rdataset
));
183 result
= dns_db_addrdataset(db
, node
, version
, 0, &rdataset
,
185 if (result
== DNS_R_UNCHANGED
)
186 result
= ISC_R_SUCCESS
;
189 if (dns_rdataset_isassociated(&rdataset
))
190 dns_rdataset_disassociate(&rdataset
);
195 dns_nsec_typepresent(dns_rdata_t
*nsec
, dns_rdatatype_t type
) {
196 dns_rdata_nsec_t nsecstruct
;
198 isc_boolean_t present
;
199 unsigned int i
, len
, window
;
201 REQUIRE(nsec
!= NULL
);
202 REQUIRE(nsec
->type
== dns_rdatatype_nsec
);
204 /* This should never fail */
205 result
= dns_rdata_tostruct(nsec
, &nsecstruct
, NULL
);
206 INSIST(result
== ISC_R_SUCCESS
);
209 for (i
= 0; i
< nsecstruct
.len
; i
+= len
) {
210 INSIST(i
+ 2 <= nsecstruct
.len
);
211 window
= nsecstruct
.typebits
[i
];
212 len
= nsecstruct
.typebits
[i
+ 1];
213 INSIST(len
> 0 && len
<= 32);
215 INSIST(i
+ len
<= nsecstruct
.len
);
216 if (window
* 256 > type
)
218 if ((window
+ 1) * 256 <= type
)
220 if (type
< (window
* 256) + len
* 8)
221 present
= ISC_TF(bit_isset(&nsecstruct
.typebits
[i
],
225 dns_rdata_freestruct(&nsecstruct
);
230 dns_nsec_nseconly(dns_db_t
*db
, dns_dbversion_t
*version
,
231 isc_boolean_t
*answer
)
233 dns_dbnode_t
*node
= NULL
;
234 dns_rdataset_t rdataset
;
235 dns_rdata_dnskey_t dnskey
;
238 REQUIRE(answer
!= NULL
);
240 dns_rdataset_init(&rdataset
);
242 result
= dns_db_getoriginnode(db
, &node
);
243 if (result
!= ISC_R_SUCCESS
)
246 result
= dns_db_findrdataset(db
, node
, version
, dns_rdatatype_dnskey
,
247 0, 0, &rdataset
, NULL
);
248 dns_db_detachnode(db
, &node
);
250 if (result
== ISC_R_NOTFOUND
) {
252 return (ISC_R_SUCCESS
);
254 if (result
!= ISC_R_SUCCESS
)
256 for (result
= dns_rdataset_first(&rdataset
);
257 result
== ISC_R_SUCCESS
;
258 result
= dns_rdataset_next(&rdataset
)) {
259 dns_rdata_t rdata
= DNS_RDATA_INIT
;
261 dns_rdataset_current(&rdataset
, &rdata
);
262 result
= dns_rdata_tostruct(&rdata
, &dnskey
, NULL
);
263 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
265 if (dnskey
.algorithm
== DST_ALG_RSAMD5
||
266 dnskey
.algorithm
== DST_ALG_RSASHA1
||
267 dnskey
.algorithm
== DST_ALG_DSA
||
268 dnskey
.algorithm
== DST_ALG_ECC
)
271 dns_rdataset_disassociate(&rdataset
);
272 if (result
== ISC_R_SUCCESS
)
274 if (result
== ISC_R_NOMORE
) {
276 result
= ISC_R_SUCCESS
;