Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / nsec.c
blob29f0755cdbfb045866f3644f9ecaa155937eb345
1 /* $NetBSD$ */
3 /*
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 */
22 /*! \file */
24 #include <config.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
29 #include <dns/db.h>
30 #include <dns/nsec.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>
38 #include <dst/dst.h>
40 #define RETERR(x) do { \
41 result = (x); \
42 if (result != ISC_R_SUCCESS) \
43 goto failure; \
44 } while (0)
46 static void
47 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
48 unsigned int shift, mask;
50 shift = 7 - (index % 8);
51 mask = 1 << shift;
53 if (bit != 0)
54 array[index / 8] |= mask;
55 else
56 array[index / 8] &= (~mask & 0xFF);
59 static unsigned int
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);
65 mask = 1 << shift;
67 return ((byte & mask) != 0);
70 isc_result_t
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)
75 isc_result_t result;
76 dns_rdataset_t rdataset;
77 isc_region_t r;
78 unsigned int i, window;
79 int octet;
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);
88 r.base = buffer;
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);
99 rdsiter = NULL;
100 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
101 if (result != ISC_R_SUCCESS)
102 return (result);
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))
126 set_bit(bm, i, 0);
130 dns_rdatasetiter_destroy(&rdsiter);
131 if (result != ISC_R_NOMORE)
132 return (result);
134 for (window = 0; window < 256; window++) {
135 if (window * 256 > max_type)
136 break;
137 for (octet = 31; octet >= 0; octet--)
138 if (bm[window * 32 + octet] != 0)
139 break;
140 if (octet < 0)
141 continue;
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,
153 dns_db_class(db),
154 dns_rdatatype_nsec,
155 &r);
157 return (ISC_R_SUCCESS);
161 isc_result_t
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)
165 isc_result_t result;
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;
179 rdatalist.ttl = ttl;
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,
184 0, NULL);
185 if (result == DNS_R_UNCHANGED)
186 result = ISC_R_SUCCESS;
187 RETERR(result);
188 failure:
189 if (dns_rdataset_isassociated(&rdataset))
190 dns_rdataset_disassociate(&rdataset);
191 return (result);
194 isc_boolean_t
195 dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) {
196 dns_rdata_nsec_t nsecstruct;
197 isc_result_t result;
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);
208 present = ISC_FALSE;
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);
214 i += 2;
215 INSIST(i + len <= nsecstruct.len);
216 if (window * 256 > type)
217 break;
218 if ((window + 1) * 256 <= type)
219 continue;
220 if (type < (window * 256) + len * 8)
221 present = ISC_TF(bit_isset(&nsecstruct.typebits[i],
222 type % 256));
223 break;
225 dns_rdata_freestruct(&nsecstruct);
226 return (present);
229 isc_result_t
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;
236 isc_result_t result;
238 REQUIRE(answer != NULL);
240 dns_rdataset_init(&rdataset);
242 result = dns_db_getoriginnode(db, &node);
243 if (result != ISC_R_SUCCESS)
244 return (result);
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) {
251 *answer = ISC_FALSE;
252 return (ISC_R_SUCCESS);
254 if (result != ISC_R_SUCCESS)
255 return (result);
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)
269 break;
271 dns_rdataset_disassociate(&rdataset);
272 if (result == ISC_R_SUCCESS)
273 *answer = ISC_TRUE;
274 if (result == ISC_R_NOMORE) {
275 *answer = ISC_FALSE;
276 result = ISC_R_SUCCESS;
278 return (result);