2 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
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.
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.
18 /* $Id: nsec.c,v 1.9.128.2 2009/01/06 23:46:47 tbox Exp $ */
24 #include <isc/string.h>
29 #include <dns/rdata.h>
30 #include <dns/rdatalist.h>
31 #include <dns/rdataset.h>
32 #include <dns/rdatasetiter.h>
33 #include <dns/rdatastruct.h>
34 #include <dns/result.h>
36 #define RETERR(x) do { \
38 if (result != ISC_R_SUCCESS) \
43 set_bit(unsigned char *array
, unsigned int index
, unsigned int bit
) {
44 unsigned int shift
, mask
;
46 shift
= 7 - (index
% 8);
50 array
[index
/ 8] |= mask
;
52 array
[index
/ 8] &= (~mask
& 0xFF);
56 bit_isset(unsigned char *array
, unsigned int index
) {
57 unsigned int byte
, shift
, mask
;
59 byte
= array
[index
/ 8];
60 shift
= 7 - (index
% 8);
63 return ((byte
& mask
) != 0);
67 dns_nsec_buildrdata(dns_db_t
*db
, dns_dbversion_t
*version
,
68 dns_dbnode_t
*node
, dns_name_t
*target
,
69 unsigned char *buffer
, dns_rdata_t
*rdata
)
72 dns_rdataset_t rdataset
;
74 unsigned int i
, window
;
77 unsigned char *nsec_bits
, *bm
;
78 unsigned int max_type
;
79 dns_rdatasetiter_t
*rdsiter
;
81 memset(buffer
, 0, DNS_NSEC_BUFFERSIZE
);
82 dns_name_toregion(target
, &r
);
83 memcpy(buffer
, r
.base
, r
.length
);
86 * Use the end of the space for a raw bitmap leaving enough
87 * space for the window identifiers and length octets.
89 bm
= r
.base
+ r
.length
+ 512;
90 nsec_bits
= r
.base
+ r
.length
;
91 set_bit(bm
, dns_rdatatype_nsec
, 1);
92 max_type
= dns_rdatatype_nsec
;
93 dns_rdataset_init(&rdataset
);
95 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
96 if (result
!= ISC_R_SUCCESS
)
98 for (result
= dns_rdatasetiter_first(rdsiter
);
99 result
== ISC_R_SUCCESS
;
100 result
= dns_rdatasetiter_next(rdsiter
))
102 dns_rdatasetiter_current(rdsiter
, &rdataset
);
103 if (rdataset
.type
!= dns_rdatatype_nsec
) {
104 if (rdataset
.type
> max_type
)
105 max_type
= rdataset
.type
;
106 set_bit(bm
, rdataset
.type
, 1);
108 dns_rdataset_disassociate(&rdataset
);
112 * At zone cuts, deny the existence of glue in the parent zone.
114 if (bit_isset(bm
, dns_rdatatype_ns
) &&
115 ! bit_isset(bm
, dns_rdatatype_soa
)) {
116 for (i
= 0; i
<= max_type
; i
++) {
117 if (bit_isset(bm
, i
) &&
118 ! dns_rdatatype_iszonecutauth((dns_rdatatype_t
)i
))
123 dns_rdatasetiter_destroy(&rdsiter
);
124 if (result
!= ISC_R_NOMORE
)
127 for (window
= 0; window
< 256; window
++) {
128 if (window
* 256 > max_type
)
130 for (octet
= 31; octet
>= 0; octet
--)
131 if (bm
[window
* 32 + octet
] != 0)
135 nsec_bits
[0] = window
;
136 nsec_bits
[1] = octet
+ 1;
138 * Note: potential overlapping move.
140 memmove(&nsec_bits
[2], &bm
[window
* 32], octet
+ 1);
141 nsec_bits
+= 3 + octet
;
143 r
.length
= nsec_bits
- r
.base
;
144 INSIST(r
.length
<= DNS_NSEC_BUFFERSIZE
);
145 dns_rdata_fromregion(rdata
,
150 return (ISC_R_SUCCESS
);
155 dns_nsec_build(dns_db_t
*db
, dns_dbversion_t
*version
, dns_dbnode_t
*node
,
156 dns_name_t
*target
, dns_ttl_t ttl
)
159 dns_rdata_t rdata
= DNS_RDATA_INIT
;
160 unsigned char data
[DNS_NSEC_BUFFERSIZE
];
161 dns_rdatalist_t rdatalist
;
162 dns_rdataset_t rdataset
;
164 dns_rdataset_init(&rdataset
);
165 dns_rdata_init(&rdata
);
167 RETERR(dns_nsec_buildrdata(db
, version
, node
, target
, data
, &rdata
));
169 rdatalist
.rdclass
= dns_db_class(db
);
170 rdatalist
.type
= dns_rdatatype_nsec
;
171 rdatalist
.covers
= 0;
173 ISC_LIST_INIT(rdatalist
.rdata
);
174 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
175 RETERR(dns_rdatalist_tordataset(&rdatalist
, &rdataset
));
176 result
= dns_db_addrdataset(db
, node
, version
, 0, &rdataset
,
178 if (result
== DNS_R_UNCHANGED
)
179 result
= ISC_R_SUCCESS
;
182 if (dns_rdataset_isassociated(&rdataset
))
183 dns_rdataset_disassociate(&rdataset
);
188 dns_nsec_typepresent(dns_rdata_t
*nsec
, dns_rdatatype_t type
) {
189 dns_rdata_nsec_t nsecstruct
;
191 isc_boolean_t present
;
192 unsigned int i
, len
, window
;
194 REQUIRE(nsec
!= NULL
);
195 REQUIRE(nsec
->type
== dns_rdatatype_nsec
);
197 /* This should never fail */
198 result
= dns_rdata_tostruct(nsec
, &nsecstruct
, NULL
);
199 INSIST(result
== ISC_R_SUCCESS
);
202 for (i
= 0; i
< nsecstruct
.len
; i
+= len
) {
203 INSIST(i
+ 2 <= nsecstruct
.len
);
204 window
= nsecstruct
.typebits
[i
];
205 len
= nsecstruct
.typebits
[i
+ 1];
206 INSIST(len
> 0 && len
<= 32);
208 INSIST(i
+ len
<= nsecstruct
.len
);
209 if (window
* 256 > type
)
211 if ((window
+ 1) * 256 <= type
)
213 if (type
< (window
* 256) + len
* 8)
214 present
= ISC_TF(bit_isset(&nsecstruct
.typebits
[i
],
218 dns_rdata_freestruct(&nsecstruct
);