1 /* $NetBSD: nsec_47.c,v 1.4 2014/12/10 04:37:59 christos Exp $ */
4 * Copyright (C) 2004, 2007-2009, 2011 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.15 2011/01/13 04:59:26 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
) {
93 unsigned int window
, len
;
95 REQUIRE(rdata
->type
== 47);
96 REQUIRE(rdata
->length
!= 0);
100 dns_name_init(&name
, NULL
);
101 dns_rdata_toregion(rdata
, &sr
);
102 dns_name_fromregion(&name
, &sr
);
103 isc_region_consume(&sr
, name_length(&name
));
104 RETERR(dns_name_totext(&name
, ISC_FALSE
, 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);
367 casecompare_nsec(ARGS_COMPARE
) {
368 isc_region_t region1
;
369 isc_region_t region2
;
374 REQUIRE(rdata1
->type
== rdata2
->type
);
375 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
376 REQUIRE(rdata1
->type
== 47);
377 REQUIRE(rdata1
->length
!= 0);
378 REQUIRE(rdata2
->length
!= 0);
380 dns_name_init(&name1
, NULL
);
381 dns_name_init(&name2
, NULL
);
383 dns_rdata_toregion(rdata1
, ®ion1
);
384 dns_rdata_toregion(rdata2
, ®ion2
);
386 dns_name_fromregion(&name1
, ®ion1
);
387 dns_name_fromregion(&name2
, ®ion2
);
389 order
= dns_name_rdatacompare(&name1
, &name2
);
393 isc_region_consume(®ion1
, name_length(&name1
));
394 isc_region_consume(®ion2
, name_length(&name2
));
396 return (isc_region_compare(®ion1
, ®ion2
));
398 #endif /* RDATA_GENERIC_NSEC_47_C */