2 * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 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_47.c,v 1.9.128.2 2008/07/15 23:46:46 tbox Exp $ */
20 /* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
24 #ifndef RDATA_GENERIC_NSEC_47_C
25 #define RDATA_GENERIC_NSEC_47_C
28 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
29 * because we must be able to handle a parent/child NSEC pair.
31 #define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
33 static inline isc_result_t
34 fromtext_nsec(ARGS_FROMTEXT
) {
38 unsigned char bm
[8*1024]; /* 64k bits */
39 dns_rdatatype_t covered
;
52 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
54 dns_name_init(&name
, NULL
);
55 buffer_fromregion(&buffer
, &token
.value
.as_region
);
56 origin
= (origin
!= NULL
) ? origin
: dns_rootname
;
57 RETTOK(dns_name_fromtext(&name
, &buffer
, origin
, options
, target
));
59 memset(bm
, 0, sizeof(bm
));
61 RETERR(isc_lex_getmastertoken(lexer
, &token
,
62 isc_tokentype_string
, ISC_TRUE
));
63 if (token
.type
!= isc_tokentype_string
)
65 RETTOK(dns_rdatatype_fromtext(&covered
,
66 &token
.value
.as_textregion
));
67 bm
[covered
/8] |= (0x80>>(covered
%8));
69 isc_lex_ungettoken(lexer
, &token
);
70 for (window
= 0; window
< 256 ; window
++) {
72 * Find if we have a type in this window.
74 for (octet
= 31; octet
>= 0; octet
--)
75 if (bm
[window
* 32 + octet
] != 0)
79 RETERR(uint8_tobuffer(window
, target
));
80 RETERR(uint8_tobuffer(octet
+ 1, target
));
81 RETERR(mem_tobuffer(target
, &bm
[window
* 32], octet
+ 1));
83 return (ISC_R_SUCCESS
);
86 static inline isc_result_t
87 totext_nsec(ARGS_TOTEXT
) {
93 unsigned int window
, len
;
95 REQUIRE(rdata
->type
== 47);
96 REQUIRE(rdata
->length
!= 0);
98 dns_name_init(&name
, NULL
);
99 dns_name_init(&prefix
, NULL
);
100 dns_rdata_toregion(rdata
, &sr
);
101 dns_name_fromregion(&name
, &sr
);
102 isc_region_consume(&sr
, name_length(&name
));
103 sub
= name_prefix(&name
, tctx
->origin
, &prefix
);
104 RETERR(dns_name_totext(&prefix
, sub
, target
));
107 for (i
= 0; i
< sr
.length
; i
+= len
) {
108 INSIST(i
+ 2 <= sr
.length
);
110 len
= sr
.base
[i
+ 1];
111 INSIST(len
> 0 && len
<= 32);
113 INSIST(i
+ len
<= sr
.length
);
114 for (j
= 0; j
< len
; j
++) {
116 if (sr
.base
[i
+ j
] == 0)
118 for (k
= 0; k
< 8; k
++) {
119 if ((sr
.base
[i
+ j
] & (0x80 >> k
)) == 0)
121 t
= window
* 256 + j
* 8 + k
;
122 RETERR(str_totext(" ", target
));
123 if (dns_rdatatype_isknown(t
)) {
124 RETERR(dns_rdatatype_totext(t
, target
));
126 char buf
[sizeof("TYPE65535")];
127 sprintf(buf
, "TYPE%u", t
);
128 RETERR(str_totext(buf
, target
));
133 return (ISC_R_SUCCESS
);
136 static /* inline */ isc_result_t
137 fromwire_nsec(ARGS_FROMWIRE
) {
140 unsigned int window
, lastwindow
= 0;
142 isc_boolean_t first
= ISC_TRUE
;
150 dns_decompress_setmethods(dctx
, DNS_COMPRESS_NONE
);
152 dns_name_init(&name
, NULL
);
153 RETERR(dns_name_fromwire(&name
, source
, dctx
, options
, target
));
155 isc_buffer_activeregion(source
, &sr
);
156 for (i
= 0; i
< sr
.length
; i
+= len
) {
158 * Check for overflow.
160 if (i
+ 2 > sr
.length
)
161 RETERR(DNS_R_FORMERR
);
163 len
= sr
.base
[i
+ 1];
166 * Check that bitmap windows are in the correct order.
168 if (!first
&& window
<= lastwindow
)
169 RETERR(DNS_R_FORMERR
);
171 * Check for legal lengths.
173 if (len
< 1 || len
> 32)
174 RETERR(DNS_R_FORMERR
);
176 * Check for overflow.
178 if (i
+ len
> sr
.length
)
179 RETERR(DNS_R_FORMERR
);
181 * The last octet of the bitmap must be non zero.
183 if (sr
.base
[i
+ len
- 1] == 0)
184 RETERR(DNS_R_FORMERR
);
189 return (DNS_R_EXTRADATA
);
191 RETERR(DNS_R_FORMERR
);
192 RETERR(mem_tobuffer(target
, sr
.base
, sr
.length
));
193 isc_buffer_forward(source
, sr
.length
);
194 return (ISC_R_SUCCESS
);
197 static inline isc_result_t
198 towire_nsec(ARGS_TOWIRE
) {
201 dns_offsets_t offsets
;
203 REQUIRE(rdata
->type
== 47);
204 REQUIRE(rdata
->length
!= 0);
206 dns_compress_setmethods(cctx
, DNS_COMPRESS_NONE
);
207 dns_name_init(&name
, offsets
);
208 dns_rdata_toregion(rdata
, &sr
);
209 dns_name_fromregion(&name
, &sr
);
210 isc_region_consume(&sr
, name_length(&name
));
211 RETERR(dns_name_towire(&name
, cctx
, target
));
213 return (mem_tobuffer(target
, sr
.base
, sr
.length
));
217 compare_nsec(ARGS_COMPARE
) {
221 REQUIRE(rdata1
->type
== rdata2
->type
);
222 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
223 REQUIRE(rdata1
->type
== 47);
224 REQUIRE(rdata1
->length
!= 0);
225 REQUIRE(rdata2
->length
!= 0);
227 dns_rdata_toregion(rdata1
, &r1
);
228 dns_rdata_toregion(rdata2
, &r2
);
229 return (isc_region_compare(&r1
, &r2
));
232 static inline isc_result_t
233 fromstruct_nsec(ARGS_FROMSTRUCT
) {
234 dns_rdata_nsec_t
*nsec
= source
;
236 unsigned int i
, len
, window
, lastwindow
= 0;
237 isc_boolean_t first
= ISC_TRUE
;
240 REQUIRE(source
!= NULL
);
241 REQUIRE(nsec
->common
.rdtype
== type
);
242 REQUIRE(nsec
->common
.rdclass
== rdclass
);
243 REQUIRE(nsec
->typebits
!= NULL
|| nsec
->len
== 0);
248 dns_name_toregion(&nsec
->next
, ®ion
);
249 RETERR(isc_buffer_copyregion(target
, ®ion
));
251 * Perform sanity check.
253 for (i
= 0; i
< nsec
->len
; i
+= len
) {
254 INSIST(i
+ 2 <= nsec
->len
);
255 window
= nsec
->typebits
[i
];
256 len
= nsec
->typebits
[i
+1];
258 INSIST(first
|| window
> lastwindow
);
259 INSIST(len
> 0 && len
<= 32);
260 INSIST(i
+ len
<= nsec
->len
);
261 INSIST(nsec
->typebits
[i
+ len
- 1] != 0);
266 return (mem_tobuffer(target
, nsec
->typebits
, nsec
->len
));
269 static inline isc_result_t
270 tostruct_nsec(ARGS_TOSTRUCT
) {
272 dns_rdata_nsec_t
*nsec
= target
;
275 REQUIRE(rdata
->type
== 47);
276 REQUIRE(target
!= NULL
);
277 REQUIRE(rdata
->length
!= 0);
279 nsec
->common
.rdclass
= rdata
->rdclass
;
280 nsec
->common
.rdtype
= rdata
->type
;
281 ISC_LINK_INIT(&nsec
->common
, link
);
283 dns_name_init(&name
, NULL
);
284 dns_rdata_toregion(rdata
, ®ion
);
285 dns_name_fromregion(&name
, ®ion
);
286 isc_region_consume(®ion
, name_length(&name
));
287 dns_name_init(&nsec
->next
, NULL
);
288 RETERR(name_duporclone(&name
, mctx
, &nsec
->next
));
290 nsec
->len
= region
.length
;
291 nsec
->typebits
= mem_maybedup(mctx
, region
.base
, region
.length
);
292 if (nsec
->typebits
== NULL
)
296 return (ISC_R_SUCCESS
);
300 dns_name_free(&nsec
->next
, mctx
);
301 return (ISC_R_NOMEMORY
);
305 freestruct_nsec(ARGS_FREESTRUCT
) {
306 dns_rdata_nsec_t
*nsec
= source
;
308 REQUIRE(source
!= NULL
);
309 REQUIRE(nsec
->common
.rdtype
== 47);
311 if (nsec
->mctx
== NULL
)
314 dns_name_free(&nsec
->next
, nsec
->mctx
);
315 if (nsec
->typebits
!= NULL
)
316 isc_mem_free(nsec
->mctx
, nsec
->typebits
);
320 static inline isc_result_t
321 additionaldata_nsec(ARGS_ADDLDATA
) {
322 REQUIRE(rdata
->type
== 47);
328 return (ISC_R_SUCCESS
);
331 static inline isc_result_t
332 digest_nsec(ARGS_DIGEST
) {
335 REQUIRE(rdata
->type
== 47);
337 dns_rdata_toregion(rdata
, &r
);
338 return ((digest
)(arg
, &r
));
341 static inline isc_boolean_t
342 checkowner_nsec(ARGS_CHECKOWNER
) {
354 static inline isc_boolean_t
355 checknames_nsec(ARGS_CHECKNAMES
) {
357 REQUIRE(rdata
->type
== 47);
366 #endif /* RDATA_GENERIC_NSEC_47_C */