1 /* $NetBSD: a6_38.c,v 1.5 2014/12/10 04:37:59 christos Exp $ */
4 * Copyright (C) 2004, 2007, 2009, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-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: a6_38.c,v 1.56 2009/12/04 22:06:37 tbox Exp */
24 #ifndef RDATA_IN_1_A6_28_C
25 #define RDATA_IN_1_A6_28_C
29 #define RRTYPE_A6_ATTRIBUTES (0)
31 static inline isc_result_t
32 fromtext_in_a6(ARGS_FROMTEXT
) {
34 unsigned char addr
[16];
35 unsigned char prefixlen
;
43 REQUIRE(rdclass
== 1);
52 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
54 if (token
.value
.as_ulong
> 128U)
57 prefixlen
= (unsigned char)token
.value
.as_ulong
;
58 RETERR(mem_tobuffer(target
, &prefixlen
, 1));
63 if (prefixlen
!= 128) {
71 RETERR(isc_lex_getmastertoken(lexer
, &token
,
74 if (inet_pton(AF_INET6
, DNS_AS_STR(token
), addr
) != 1)
75 RETTOK(DNS_R_BADAAAA
);
76 mask
= 0xff >> (prefixlen
% 8);
78 RETERR(mem_tobuffer(target
, &addr
[octets
], 16 - octets
));
82 return (ISC_R_SUCCESS
);
84 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
86 dns_name_init(&name
, NULL
);
87 buffer_fromregion(&buffer
, &token
.value
.as_region
);
88 origin
= (origin
!= NULL
) ? origin
: dns_rootname
;
89 RETTOK(dns_name_fromtext(&name
, &buffer
, origin
, options
, target
));
91 if ((options
& DNS_RDATA_CHECKNAMES
) != 0)
92 ok
= dns_name_ishostname(&name
, ISC_FALSE
);
93 if (!ok
&& (options
& DNS_RDATA_CHECKNAMESFAIL
) != 0)
94 RETTOK(DNS_R_BADNAME
);
95 if (!ok
&& callbacks
!= NULL
)
96 warn_badname(&name
, lexer
, callbacks
);
97 return (ISC_R_SUCCESS
);
100 static inline isc_result_t
101 totext_in_a6(ARGS_TOTEXT
) {
103 unsigned char addr
[16];
104 unsigned char prefixlen
;
105 unsigned char octets
;
107 char buf
[sizeof("128")];
112 REQUIRE(rdata
->type
== 38);
113 REQUIRE(rdata
->rdclass
== 1);
114 REQUIRE(rdata
->length
!= 0);
116 dns_rdata_toregion(rdata
, &sr
);
117 prefixlen
= sr
.base
[0];
118 INSIST(prefixlen
<= 128);
119 isc_region_consume(&sr
, 1);
120 sprintf(buf
, "%u", prefixlen
);
121 RETERR(str_totext(buf
, target
));
122 RETERR(str_totext(" ", target
));
124 if (prefixlen
!= 128) {
125 octets
= prefixlen
/8;
126 memset(addr
, 0, sizeof(addr
));
127 memmove(&addr
[octets
], sr
.base
, 16 - octets
);
128 mask
= 0xff >> (prefixlen
% 8);
129 addr
[octets
] &= mask
;
131 ar
.length
= sizeof(addr
);
132 RETERR(inet_totext(AF_INET6
, &ar
, target
));
133 isc_region_consume(&sr
, 16 - octets
);
137 return (ISC_R_SUCCESS
);
139 RETERR(str_totext(" ", target
));
140 dns_name_init(&name
, NULL
);
141 dns_name_init(&prefix
, NULL
);
142 dns_name_fromregion(&name
, &sr
);
143 sub
= name_prefix(&name
, tctx
->origin
, &prefix
);
144 return (dns_name_totext(&prefix
, sub
, target
));
147 static inline isc_result_t
148 fromwire_in_a6(ARGS_FROMWIRE
) {
150 unsigned char prefixlen
;
151 unsigned char octets
;
156 REQUIRE(rdclass
== 1);
161 dns_decompress_setmethods(dctx
, DNS_COMPRESS_NONE
);
163 isc_buffer_activeregion(source
, &sr
);
168 return (ISC_R_UNEXPECTEDEND
);
169 prefixlen
= sr
.base
[0];
171 return (ISC_R_RANGE
);
172 isc_region_consume(&sr
, 1);
173 RETERR(mem_tobuffer(target
, &prefixlen
, 1));
174 isc_buffer_forward(source
, 1);
179 if (prefixlen
!= 128) {
180 octets
= 16 - prefixlen
/ 8;
181 if (sr
.length
< octets
)
182 return (ISC_R_UNEXPECTEDEND
);
183 mask
= 0xff >> (prefixlen
% 8);
184 sr
.base
[0] &= mask
; /* Ensure pad bits are zero. */
185 RETERR(mem_tobuffer(target
, sr
.base
, octets
));
186 isc_buffer_forward(source
, octets
);
190 return (ISC_R_SUCCESS
);
192 dns_name_init(&name
, NULL
);
193 return (dns_name_fromwire(&name
, source
, dctx
, options
, target
));
196 static inline isc_result_t
197 towire_in_a6(ARGS_TOWIRE
) {
200 dns_offsets_t offsets
;
201 unsigned char prefixlen
;
202 unsigned char octets
;
204 REQUIRE(rdata
->type
== 38);
205 REQUIRE(rdata
->rdclass
== 1);
206 REQUIRE(rdata
->length
!= 0);
208 dns_compress_setmethods(cctx
, DNS_COMPRESS_NONE
);
209 dns_rdata_toregion(rdata
, &sr
);
210 prefixlen
= sr
.base
[0];
211 INSIST(prefixlen
<= 128);
213 octets
= 1 + 16 - prefixlen
/ 8;
214 RETERR(mem_tobuffer(target
, sr
.base
, octets
));
215 isc_region_consume(&sr
, octets
);
218 return (ISC_R_SUCCESS
);
220 dns_name_init(&name
, offsets
);
221 dns_name_fromregion(&name
, &sr
);
222 return (dns_name_towire(&name
, cctx
, target
));
226 compare_in_a6(ARGS_COMPARE
) {
228 unsigned char prefixlen1
, prefixlen2
;
229 unsigned char octets
;
232 isc_region_t region1
;
233 isc_region_t region2
;
235 REQUIRE(rdata1
->type
== rdata2
->type
);
236 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
237 REQUIRE(rdata1
->type
== 38);
238 REQUIRE(rdata1
->rdclass
== 1);
239 REQUIRE(rdata1
->length
!= 0);
240 REQUIRE(rdata2
->length
!= 0);
242 dns_rdata_toregion(rdata1
, ®ion1
);
243 dns_rdata_toregion(rdata2
, ®ion2
);
244 prefixlen1
= region1
.base
[0];
245 prefixlen2
= region2
.base
[0];
246 isc_region_consume(®ion1
, 1);
247 isc_region_consume(®ion2
, 1);
248 if (prefixlen1
< prefixlen2
)
250 else if (prefixlen1
> prefixlen2
)
253 * Prefix lengths are equal.
255 octets
= 16 - prefixlen1
/ 8;
258 order
= memcmp(region1
.base
, region2
.base
, octets
);
264 * Address suffixes are equal.
268 isc_region_consume(®ion1
, octets
);
269 isc_region_consume(®ion2
, octets
);
272 dns_name_init(&name1
, NULL
);
273 dns_name_init(&name2
, NULL
);
274 dns_name_fromregion(&name1
, ®ion1
);
275 dns_name_fromregion(&name2
, ®ion2
);
276 return (dns_name_rdatacompare(&name1
, &name2
));
279 static inline isc_result_t
280 fromstruct_in_a6(ARGS_FROMSTRUCT
) {
281 dns_rdata_in_a6_t
*a6
= source
;
289 REQUIRE(rdclass
== 1);
290 REQUIRE(source
!= NULL
);
291 REQUIRE(a6
->common
.rdtype
== type
);
292 REQUIRE(a6
->common
.rdclass
== rdclass
);
297 if (a6
->prefixlen
> 128)
298 return (ISC_R_RANGE
);
300 RETERR(uint8_tobuffer(a6
->prefixlen
, target
));
303 if (a6
->prefixlen
!= 128) {
304 octets
= 16 - a6
->prefixlen
/ 8;
305 bits
= a6
->prefixlen
% 8;
307 mask
= 0xffU
>> bits
;
308 first
= a6
->in6_addr
.s6_addr
[16 - octets
] & mask
;
309 RETERR(uint8_tobuffer(first
, target
));
313 RETERR(mem_tobuffer(target
,
314 a6
->in6_addr
.s6_addr
+ 16 - octets
,
318 if (a6
->prefixlen
== 0)
319 return (ISC_R_SUCCESS
);
320 dns_name_toregion(&a6
->prefix
, ®ion
);
321 return (isc_buffer_copyregion(target
, ®ion
));
324 static inline isc_result_t
325 tostruct_in_a6(ARGS_TOSTRUCT
) {
326 dns_rdata_in_a6_t
*a6
= target
;
327 unsigned char octets
;
331 REQUIRE(rdata
->type
== 38);
332 REQUIRE(rdata
->rdclass
== 1);
333 REQUIRE(target
!= NULL
);
334 REQUIRE(rdata
->length
!= 0);
336 a6
->common
.rdclass
= rdata
->rdclass
;
337 a6
->common
.rdtype
= rdata
->type
;
338 ISC_LINK_INIT(&a6
->common
, link
);
340 dns_rdata_toregion(rdata
, &r
);
342 a6
->prefixlen
= uint8_fromregion(&r
);
343 isc_region_consume(&r
, 1);
344 memset(a6
->in6_addr
.s6_addr
, 0, sizeof(a6
->in6_addr
.s6_addr
));
349 if (a6
->prefixlen
!= 128) {
350 octets
= 16 - a6
->prefixlen
/ 8;
351 INSIST(r
.length
>= octets
);
352 memmove(a6
->in6_addr
.s6_addr
+ 16 - octets
, r
.base
, octets
);
353 isc_region_consume(&r
, octets
);
359 dns_name_init(&a6
->prefix
, NULL
);
360 if (a6
->prefixlen
!= 0) {
361 dns_name_init(&name
, NULL
);
362 dns_name_fromregion(&name
, &r
);
363 RETERR(name_duporclone(&name
, mctx
, &a6
->prefix
));
366 return (ISC_R_SUCCESS
);
370 freestruct_in_a6(ARGS_FREESTRUCT
) {
371 dns_rdata_in_a6_t
*a6
= source
;
373 REQUIRE(source
!= NULL
);
374 REQUIRE(a6
->common
.rdclass
== 1);
375 REQUIRE(a6
->common
.rdtype
== 38);
377 if (a6
->mctx
== NULL
)
380 if (dns_name_dynamic(&a6
->prefix
))
381 dns_name_free(&a6
->prefix
, a6
->mctx
);
385 static inline isc_result_t
386 additionaldata_in_a6(ARGS_ADDLDATA
) {
387 REQUIRE(rdata
->type
== 38);
388 REQUIRE(rdata
->rdclass
== 1);
394 return (ISC_R_SUCCESS
);
397 static inline isc_result_t
398 digest_in_a6(ARGS_DIGEST
) {
400 unsigned char prefixlen
, octets
;
404 REQUIRE(rdata
->type
== 38);
405 REQUIRE(rdata
->rdclass
== 1);
407 dns_rdata_toregion(rdata
, &r1
);
409 prefixlen
= r1
.base
[0];
410 octets
= 1 + 16 - prefixlen
/ 8;
413 result
= (digest
)(arg
, &r1
);
414 if (result
!= ISC_R_SUCCESS
)
417 return (ISC_R_SUCCESS
);
419 isc_region_consume(&r2
, octets
);
420 dns_name_init(&name
, NULL
);
421 dns_name_fromregion(&name
, &r2
);
422 return (dns_name_digest(&name
, digest
, arg
));
425 static inline isc_boolean_t
426 checkowner_in_a6(ARGS_CHECKOWNER
) {
429 REQUIRE(rdclass
== 1);
434 return (dns_name_ishostname(name
, wildcard
));
437 static inline isc_boolean_t
438 checknames_in_a6(ARGS_CHECKNAMES
) {
441 unsigned int prefixlen
;
443 REQUIRE(rdata
->type
== 38);
444 REQUIRE(rdata
->rdclass
== 1);
448 dns_rdata_toregion(rdata
, ®ion
);
449 prefixlen
= uint8_fromregion(®ion
);
452 isc_region_consume(®ion
, 1 + 16 - prefixlen
/ 8);
453 dns_name_init(&name
, NULL
);
454 dns_name_fromregion(&name
, ®ion
);
455 if (!dns_name_ishostname(&name
, ISC_FALSE
)) {
457 dns_name_clone(&name
, bad
);
464 casecompare_in_a6(ARGS_COMPARE
) {
465 return (compare_in_a6(rdata1
, rdata2
));
468 #endif /* RDATA_IN_1_A6_38_C */