4 * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 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_47.c,v 1.13 2009/12/04 22:06:37 tbox Exp */
22 /* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
26 #ifndef RDATA_GENERIC_NSEC_47_C
27 #define RDATA_GENERIC_NSEC_47_C
30 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
31 * because we must be able to handle a parent/child NSEC pair.
33 #define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
35 static inline isc_result_t
36 fromtext_nsec(ARGS_FROMTEXT
) {
40 unsigned char bm
[8*1024]; /* 64k bits */
41 dns_rdatatype_t covered
;
54 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
56 dns_name_init(&name
, NULL
);
57 buffer_fromregion(&buffer
, &token
.value
.as_region
);
58 origin
= (origin
!= NULL
) ? origin
: dns_rootname
;
59 RETTOK(dns_name_fromtext(&name
, &buffer
, origin
, options
, target
));
61 memset(bm
, 0, sizeof(bm
));
63 RETERR(isc_lex_getmastertoken(lexer
, &token
,
64 isc_tokentype_string
, ISC_TRUE
));
65 if (token
.type
!= isc_tokentype_string
)
67 RETTOK(dns_rdatatype_fromtext(&covered
,
68 &token
.value
.as_textregion
));
69 bm
[covered
/8] |= (0x80>>(covered
%8));
71 isc_lex_ungettoken(lexer
, &token
);
72 for (window
= 0; window
< 256 ; window
++) {
74 * Find if we have a type in this window.
76 for (octet
= 31; octet
>= 0; octet
--)
77 if (bm
[window
* 32 + octet
] != 0)
81 RETERR(uint8_tobuffer(window
, target
));
82 RETERR(uint8_tobuffer(octet
+ 1, target
));
83 RETERR(mem_tobuffer(target
, &bm
[window
* 32], octet
+ 1));
85 return (ISC_R_SUCCESS
);
88 static inline isc_result_t
89 totext_nsec(ARGS_TOTEXT
) {
95 unsigned int window
, len
;
97 REQUIRE(rdata
->type
== 47);
98 REQUIRE(rdata
->length
!= 0);
100 dns_name_init(&name
, NULL
);
101 dns_name_init(&prefix
, NULL
);
102 dns_rdata_toregion(rdata
, &sr
);
103 dns_name_fromregion(&name
, &sr
);
104 isc_region_consume(&sr
, name_length(&name
));
105 sub
= name_prefix(&name
, tctx
->origin
, &prefix
);
106 RETERR(dns_name_totext(&prefix
, sub
, target
));
109 for (i
= 0; i
< sr
.length
; i
+= len
) {
110 INSIST(i
+ 2 <= sr
.length
);
112 len
= sr
.base
[i
+ 1];
113 INSIST(len
> 0 && len
<= 32);
115 INSIST(i
+ len
<= sr
.length
);
116 for (j
= 0; j
< len
; j
++) {
118 if (sr
.base
[i
+ j
] == 0)
120 for (k
= 0; k
< 8; k
++) {
121 if ((sr
.base
[i
+ j
] & (0x80 >> k
)) == 0)
123 t
= window
* 256 + j
* 8 + k
;
124 RETERR(str_totext(" ", target
));
125 if (dns_rdatatype_isknown(t
)) {
126 RETERR(dns_rdatatype_totext(t
, target
));
128 char buf
[sizeof("TYPE65535")];
129 sprintf(buf
, "TYPE%u", t
);
130 RETERR(str_totext(buf
, target
));
135 return (ISC_R_SUCCESS
);
138 static /* inline */ isc_result_t
139 fromwire_nsec(ARGS_FROMWIRE
) {
142 unsigned int window
, lastwindow
= 0;
144 isc_boolean_t first
= ISC_TRUE
;
152 dns_decompress_setmethods(dctx
, DNS_COMPRESS_NONE
);
154 dns_name_init(&name
, NULL
);
155 RETERR(dns_name_fromwire(&name
, source
, dctx
, options
, target
));
157 isc_buffer_activeregion(source
, &sr
);
158 for (i
= 0; i
< sr
.length
; i
+= len
) {
160 * Check for overflow.
162 if (i
+ 2 > sr
.length
)
163 RETERR(DNS_R_FORMERR
);
165 len
= sr
.base
[i
+ 1];
168 * Check that bitmap windows are in the correct order.
170 if (!first
&& window
<= lastwindow
)
171 RETERR(DNS_R_FORMERR
);
173 * Check for legal lengths.
175 if (len
< 1 || len
> 32)
176 RETERR(DNS_R_FORMERR
);
178 * Check for overflow.
180 if (i
+ len
> sr
.length
)
181 RETERR(DNS_R_FORMERR
);
183 * The last octet of the bitmap must be non zero.
185 if (sr
.base
[i
+ len
- 1] == 0)
186 RETERR(DNS_R_FORMERR
);
191 return (DNS_R_EXTRADATA
);
193 RETERR(DNS_R_FORMERR
);
194 RETERR(mem_tobuffer(target
, sr
.base
, sr
.length
));
195 isc_buffer_forward(source
, sr
.length
);
196 return (ISC_R_SUCCESS
);
199 static inline isc_result_t
200 towire_nsec(ARGS_TOWIRE
) {
203 dns_offsets_t offsets
;
205 REQUIRE(rdata
->type
== 47);
206 REQUIRE(rdata
->length
!= 0);
208 dns_compress_setmethods(cctx
, DNS_COMPRESS_NONE
);
209 dns_name_init(&name
, offsets
);
210 dns_rdata_toregion(rdata
, &sr
);
211 dns_name_fromregion(&name
, &sr
);
212 isc_region_consume(&sr
, name_length(&name
));
213 RETERR(dns_name_towire(&name
, cctx
, target
));
215 return (mem_tobuffer(target
, sr
.base
, sr
.length
));
219 compare_nsec(ARGS_COMPARE
) {
223 REQUIRE(rdata1
->type
== rdata2
->type
);
224 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
225 REQUIRE(rdata1
->type
== 47);
226 REQUIRE(rdata1
->length
!= 0);
227 REQUIRE(rdata2
->length
!= 0);
229 dns_rdata_toregion(rdata1
, &r1
);
230 dns_rdata_toregion(rdata2
, &r2
);
231 return (isc_region_compare(&r1
, &r2
));
234 static inline isc_result_t
235 fromstruct_nsec(ARGS_FROMSTRUCT
) {
236 dns_rdata_nsec_t
*nsec
= source
;
238 unsigned int i
, len
, window
, lastwindow
= 0;
239 isc_boolean_t first
= ISC_TRUE
;
242 REQUIRE(source
!= NULL
);
243 REQUIRE(nsec
->common
.rdtype
== type
);
244 REQUIRE(nsec
->common
.rdclass
== rdclass
);
245 REQUIRE(nsec
->typebits
!= NULL
|| nsec
->len
== 0);
250 dns_name_toregion(&nsec
->next
, ®ion
);
251 RETERR(isc_buffer_copyregion(target
, ®ion
));
253 * Perform sanity check.
255 for (i
= 0; i
< nsec
->len
; i
+= len
) {
256 INSIST(i
+ 2 <= nsec
->len
);
257 window
= nsec
->typebits
[i
];
258 len
= nsec
->typebits
[i
+1];
260 INSIST(first
|| window
> lastwindow
);
261 INSIST(len
> 0 && len
<= 32);
262 INSIST(i
+ len
<= nsec
->len
);
263 INSIST(nsec
->typebits
[i
+ len
- 1] != 0);
268 return (mem_tobuffer(target
, nsec
->typebits
, nsec
->len
));
271 static inline isc_result_t
272 tostruct_nsec(ARGS_TOSTRUCT
) {
274 dns_rdata_nsec_t
*nsec
= target
;
277 REQUIRE(rdata
->type
== 47);
278 REQUIRE(target
!= NULL
);
279 REQUIRE(rdata
->length
!= 0);
281 nsec
->common
.rdclass
= rdata
->rdclass
;
282 nsec
->common
.rdtype
= rdata
->type
;
283 ISC_LINK_INIT(&nsec
->common
, link
);
285 dns_name_init(&name
, NULL
);
286 dns_rdata_toregion(rdata
, ®ion
);
287 dns_name_fromregion(&name
, ®ion
);
288 isc_region_consume(®ion
, name_length(&name
));
289 dns_name_init(&nsec
->next
, NULL
);
290 RETERR(name_duporclone(&name
, mctx
, &nsec
->next
));
292 nsec
->len
= region
.length
;
293 nsec
->typebits
= mem_maybedup(mctx
, region
.base
, region
.length
);
294 if (nsec
->typebits
== NULL
)
298 return (ISC_R_SUCCESS
);
302 dns_name_free(&nsec
->next
, mctx
);
303 return (ISC_R_NOMEMORY
);
307 freestruct_nsec(ARGS_FREESTRUCT
) {
308 dns_rdata_nsec_t
*nsec
= source
;
310 REQUIRE(source
!= NULL
);
311 REQUIRE(nsec
->common
.rdtype
== 47);
313 if (nsec
->mctx
== NULL
)
316 dns_name_free(&nsec
->next
, nsec
->mctx
);
317 if (nsec
->typebits
!= NULL
)
318 isc_mem_free(nsec
->mctx
, nsec
->typebits
);
322 static inline isc_result_t
323 additionaldata_nsec(ARGS_ADDLDATA
) {
324 REQUIRE(rdata
->type
== 47);
330 return (ISC_R_SUCCESS
);
333 static inline isc_result_t
334 digest_nsec(ARGS_DIGEST
) {
337 REQUIRE(rdata
->type
== 47);
339 dns_rdata_toregion(rdata
, &r
);
340 return ((digest
)(arg
, &r
));
343 static inline isc_boolean_t
344 checkowner_nsec(ARGS_CHECKOWNER
) {
356 static inline isc_boolean_t
357 checknames_nsec(ARGS_CHECKNAMES
) {
359 REQUIRE(rdata
->type
== 47);
369 casecompare_nsec(ARGS_COMPARE
) {
370 isc_region_t region1
;
371 isc_region_t region2
;
376 REQUIRE(rdata1
->type
== rdata2
->type
);
377 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
378 REQUIRE(rdata1
->type
== 47);
379 REQUIRE(rdata1
->length
!= 0);
380 REQUIRE(rdata2
->length
!= 0);
382 dns_name_init(&name1
, NULL
);
383 dns_name_init(&name2
, NULL
);
385 dns_rdata_toregion(rdata1
, ®ion1
);
386 dns_rdata_toregion(rdata2
, ®ion2
);
388 dns_name_fromregion(&name1
, ®ion1
);
389 dns_name_fromregion(&name2
, ®ion2
);
391 order
= dns_name_rdatacompare(&name1
, &name2
);
395 isc_region_consume(®ion1
, name_length(&name1
));
396 isc_region_consume(®ion2
, name_length(&name2
));
398 return (isc_region_compare(®ion1
, ®ion2
));
400 #endif /* RDATA_GENERIC_NSEC_47_C */