2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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: a6_38.c,v 1.52 2004/03/05 05:10:23 marka Exp $ */
22 #ifndef RDATA_IN_1_A6_28_C
23 #define RDATA_IN_1_A6_28_C
27 #define RRTYPE_A6_ATTRIBUTES (0)
29 static inline isc_result_t
30 fromtext_in_a6(ARGS_FROMTEXT) {
32 unsigned char addr[16];
33 unsigned char prefixlen;
41 REQUIRE(rdclass == 1);
50 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
52 if (token.value.as_ulong > 128U)
55 prefixlen = (unsigned char)token.value.as_ulong;
56 RETERR(mem_tobuffer(target, &prefixlen, 1));
61 if (prefixlen != 128) {
69 RETERR(isc_lex_getmastertoken(lexer, &token,
72 if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1)
73 RETTOK(DNS_R_BADAAAA);
74 mask = 0xff >> (prefixlen % 8);
76 RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
80 return (ISC_R_SUCCESS);
82 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
84 dns_name_init(&name, NULL);
85 buffer_fromregion(&buffer, &token.value.as_region);
86 origin = (origin != NULL) ? origin : dns_rootname;
87 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
89 if ((options & DNS_RDATA_CHECKNAMES) != 0)
90 ok = dns_name_ishostname(&name, ISC_FALSE);
91 if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
92 RETTOK(DNS_R_BADNAME);
93 if (!ok && callbacks != NULL)
94 warn_badname(&name, lexer, callbacks);
95 return (ISC_R_SUCCESS);
98 static inline isc_result_t
99 totext_in_a6(ARGS_TOTEXT) {
101 unsigned char addr[16];
102 unsigned char prefixlen;
103 unsigned char octets;
105 char buf[sizeof("128")];
110 REQUIRE(rdata->type == 38);
111 REQUIRE(rdata->rdclass == 1);
112 REQUIRE(rdata->length != 0);
114 dns_rdata_toregion(rdata, &sr);
115 prefixlen = sr.base[0];
116 INSIST(prefixlen <= 128);
117 isc_region_consume(&sr, 1);
118 sprintf(buf, "%u", prefixlen);
119 RETERR(str_totext(buf, target));
120 RETERR(str_totext(" ", target));
122 if (prefixlen != 128) {
123 octets = prefixlen/8;
124 memset(addr, 0, sizeof(addr));
125 memcpy(&addr[octets], sr.base, 16 - octets);
126 mask = 0xff >> (prefixlen % 8);
127 addr[octets] &= mask;
129 ar.length = sizeof(addr);
130 RETERR(inet_totext(AF_INET6, &ar, target));
131 isc_region_consume(&sr, 16 - octets);
135 return (ISC_R_SUCCESS);
137 RETERR(str_totext(" ", target));
138 dns_name_init(&name, NULL);
139 dns_name_init(&prefix, NULL);
140 dns_name_fromregion(&name, &sr);
141 sub = name_prefix(&name, tctx->origin, &prefix);
142 return (dns_name_totext(&prefix, sub, target));
145 static inline isc_result_t
146 fromwire_in_a6(ARGS_FROMWIRE) {
148 unsigned char prefixlen;
149 unsigned char octets;
154 REQUIRE(rdclass == 1);
159 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
161 isc_buffer_activeregion(source, &sr);
166 return (ISC_R_UNEXPECTEDEND);
167 prefixlen = sr.base[0];
169 return (ISC_R_RANGE);
170 isc_region_consume(&sr, 1);
171 RETERR(mem_tobuffer(target, &prefixlen, 1));
172 isc_buffer_forward(source, 1);
177 if (prefixlen != 128) {
178 octets = 16 - prefixlen / 8;
179 if (sr.length < octets)
180 return (ISC_R_UNEXPECTEDEND);
181 mask = 0xff >> (prefixlen % 8);
182 sr.base[0] &= mask; /* Ensure pad bits are zero. */
183 RETERR(mem_tobuffer(target, sr.base, octets));
184 isc_buffer_forward(source, octets);
188 return (ISC_R_SUCCESS);
190 dns_name_init(&name, NULL);
191 return (dns_name_fromwire(&name, source, dctx, options, target));
194 static inline isc_result_t
195 towire_in_a6(ARGS_TOWIRE) {
198 dns_offsets_t offsets;
199 unsigned char prefixlen;
200 unsigned char octets;
202 REQUIRE(rdata->type == 38);
203 REQUIRE(rdata->rdclass == 1);
204 REQUIRE(rdata->length != 0);
206 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
207 dns_rdata_toregion(rdata, &sr);
208 prefixlen = sr.base[0];
209 INSIST(prefixlen <= 128);
211 octets = 1 + 16 - prefixlen / 8;
212 RETERR(mem_tobuffer(target, sr.base, octets));
213 isc_region_consume(&sr, octets);
216 return (ISC_R_SUCCESS);
218 dns_name_init(&name, offsets);
219 dns_name_fromregion(&name, &sr);
220 return (dns_name_towire(&name, cctx, target));
224 compare_in_a6(ARGS_COMPARE) {
226 unsigned char prefixlen1, prefixlen2;
227 unsigned char octets;
230 isc_region_t region1;
231 isc_region_t region2;
233 REQUIRE(rdata1->type == rdata2->type);
234 REQUIRE(rdata1->rdclass == rdata2->rdclass);
235 REQUIRE(rdata1->type == 38);
236 REQUIRE(rdata1->rdclass == 1);
237 REQUIRE(rdata1->length != 0);
238 REQUIRE(rdata2->length != 0);
240 dns_rdata_toregion(rdata1, ®ion1);
241 dns_rdata_toregion(rdata2, ®ion2);
242 prefixlen1 = region1.base[0];
243 prefixlen2 = region2.base[0];
244 isc_region_consume(®ion1, 1);
245 isc_region_consume(®ion2, 1);
246 if (prefixlen1 < prefixlen2)
248 else if (prefixlen1 > prefixlen2)
251 * Prefix lengths are equal.
253 octets = 16 - prefixlen1 / 8;
256 order = memcmp(region1.base, region2.base, octets);
262 * Address suffixes are equal.
266 isc_region_consume(®ion1, octets);
267 isc_region_consume(®ion2, octets);
270 dns_name_init(&name1, NULL);
271 dns_name_init(&name2, NULL);
272 dns_name_fromregion(&name1, ®ion1);
273 dns_name_fromregion(&name2, ®ion2);
274 return (dns_name_rdatacompare(&name1, &name2));
277 static inline isc_result_t
278 fromstruct_in_a6(ARGS_FROMSTRUCT) {
279 dns_rdata_in_a6_t *a6 = source;
287 REQUIRE(rdclass == 1);
288 REQUIRE(source != NULL);
289 REQUIRE(a6->common.rdtype == type);
290 REQUIRE(a6->common.rdclass == rdclass);
295 if (a6->prefixlen > 128)
296 return (ISC_R_RANGE);
298 RETERR(uint8_tobuffer(a6->prefixlen, target));
301 if (a6->prefixlen != 128) {
302 octets = 16 - a6->prefixlen / 8;
303 bits = a6->prefixlen % 8;
305 mask = 0xffU >> bits;
306 first = a6->in6_addr.s6_addr[16 - octets] & mask;
307 RETERR(uint8_tobuffer(first, target));
311 RETERR(mem_tobuffer(target,
312 a6->in6_addr.s6_addr + 16 - octets,
316 if (a6->prefixlen == 0)
317 return (ISC_R_SUCCESS);
318 dns_name_toregion(&a6->prefix, ®ion);
319 return (isc_buffer_copyregion(target, ®ion));
322 static inline isc_result_t
323 tostruct_in_a6(ARGS_TOSTRUCT) {
324 dns_rdata_in_a6_t *a6 = target;
325 unsigned char octets;
329 REQUIRE(rdata->type == 38);
330 REQUIRE(rdata->rdclass == 1);
331 REQUIRE(target != NULL);
332 REQUIRE(rdata->length != 0);
334 a6->common.rdclass = rdata->rdclass;
335 a6->common.rdtype = rdata->type;
336 ISC_LINK_INIT(&a6->common, link);
338 dns_rdata_toregion(rdata, &r);
340 a6->prefixlen = uint8_fromregion(&r);
341 isc_region_consume(&r, 1);
342 memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
347 if (a6->prefixlen != 128) {
348 octets = 16 - a6->prefixlen / 8;
349 INSIST(r.length >= octets);
350 memcpy(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
351 isc_region_consume(&r, octets);
357 dns_name_init(&a6->prefix, NULL);
358 if (a6->prefixlen != 0) {
359 dns_name_init(&name, NULL);
360 dns_name_fromregion(&name, &r);
361 RETERR(name_duporclone(&name, mctx, &a6->prefix));
364 return (ISC_R_SUCCESS);
368 freestruct_in_a6(ARGS_FREESTRUCT) {
369 dns_rdata_in_a6_t *a6 = source;
371 REQUIRE(source != NULL);
372 REQUIRE(a6->common.rdclass == 1);
373 REQUIRE(a6->common.rdtype == 38);
375 if (a6->mctx == NULL)
378 if (dns_name_dynamic(&a6->prefix))
379 dns_name_free(&a6->prefix, a6->mctx);
383 static inline isc_result_t
384 additionaldata_in_a6(ARGS_ADDLDATA) {
385 REQUIRE(rdata->type == 38);
386 REQUIRE(rdata->rdclass == 1);
392 return (ISC_R_SUCCESS);
395 static inline isc_result_t
396 digest_in_a6(ARGS_DIGEST) {
398 unsigned char prefixlen, octets;
402 REQUIRE(rdata->type == 38);
403 REQUIRE(rdata->rdclass == 1);
405 dns_rdata_toregion(rdata, &r1);
407 prefixlen = r1.base[0];
408 octets = 1 + 16 - prefixlen / 8;
411 result = (digest)(arg, &r1);
412 if (result != ISC_R_SUCCESS)
415 return (ISC_R_SUCCESS);
417 isc_region_consume(&r2, octets);
418 dns_name_init(&name, NULL);
419 dns_name_fromregion(&name, &r2);
420 return (dns_name_digest(&name, digest, arg));
423 static inline isc_boolean_t
424 checkowner_in_a6(ARGS_CHECKOWNER) {
427 REQUIRE(rdclass == 1);
432 return (dns_name_ishostname(name, wildcard));
435 static inline isc_boolean_t
436 checknames_in_a6(ARGS_CHECKNAMES) {
439 unsigned int prefixlen;
441 REQUIRE(rdata->type == 38);
442 REQUIRE(rdata->rdclass == 1);
446 dns_rdata_toregion(rdata, ®ion);
447 prefixlen = uint8_fromregion(®ion);
450 isc_region_consume(®ion, 1 + 16 - prefixlen / 8);
451 dns_name_init(&name, NULL);
452 dns_name_fromregion(&name, ®ion);
453 if (!dns_name_ishostname(&name, ISC_FALSE)) {
455 dns_name_clone(&name, bad);
461 #endif /* RDATA_IN_1_A6_38_C */