2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 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.46.2.3 2004/03/09 06:11:35 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;
40 REQUIRE(rdclass == 1);
49 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
51 if (token.value.as_ulong > 128U)
54 prefixlen = (unsigned char)token.value.as_ulong;
55 RETERR(mem_tobuffer(target, &prefixlen, 1));
60 if (prefixlen != 128) {
68 RETERR(isc_lex_getmastertoken(lexer, &token,
71 if (inet_pton(AF_INET6, token.value.as_pointer, addr) != 1)
72 RETTOK(DNS_R_BADAAAA);
73 mask = 0xff >> (prefixlen % 8);
75 RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
79 return (ISC_R_SUCCESS);
81 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
83 dns_name_init(&name, NULL);
84 buffer_fromregion(&buffer, &token.value.as_region);
85 origin = (origin != NULL) ? origin : dns_rootname;
86 RETTOK(dns_name_fromtext(&name, &buffer, origin, downcase, target));
87 return (ISC_R_SUCCESS);
90 static inline isc_result_t
91 totext_in_a6(ARGS_TOTEXT) {
93 unsigned char addr[16];
94 unsigned char prefixlen;
97 char buf[sizeof "128"];
102 REQUIRE(rdata->type == 38);
103 REQUIRE(rdata->rdclass == 1);
104 REQUIRE(rdata->length != 0);
106 dns_rdata_toregion(rdata, &sr);
107 prefixlen = sr.base[0];
108 INSIST(prefixlen <= 128);
109 isc_region_consume(&sr, 1);
110 sprintf(buf, "%u", prefixlen);
111 RETERR(str_totext(buf, target));
112 RETERR(str_totext(" ", target));
114 if (prefixlen != 128) {
115 octets = prefixlen/8;
116 memset(addr, 0, sizeof addr);
117 memcpy(&addr[octets], sr.base, 16 - octets);
118 mask = 0xff >> (prefixlen % 8);
119 addr[octets] &= mask;
121 ar.length = sizeof(addr);
122 RETERR(inet_totext(AF_INET6, &ar, target));
123 isc_region_consume(&sr, 16 - octets);
127 return (ISC_R_SUCCESS);
129 RETERR(str_totext(" ", target));
130 dns_name_init(&name, NULL);
131 dns_name_init(&prefix, NULL);
132 dns_name_fromregion(&name, &sr);
133 sub = name_prefix(&name, tctx->origin, &prefix);
134 return (dns_name_totext(&prefix, sub, target));
137 static inline isc_result_t
138 fromwire_in_a6(ARGS_FROMWIRE) {
140 unsigned char prefixlen;
141 unsigned char octets;
146 REQUIRE(rdclass == 1);
151 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
153 isc_buffer_activeregion(source, &sr);
158 return (ISC_R_UNEXPECTEDEND);
159 prefixlen = sr.base[0];
161 return (ISC_R_RANGE);
162 isc_region_consume(&sr, 1);
163 RETERR(mem_tobuffer(target, &prefixlen, 1));
164 isc_buffer_forward(source, 1);
169 if (prefixlen != 128) {
170 octets = 16 - prefixlen / 8;
171 if (sr.length < octets)
172 return (ISC_R_UNEXPECTEDEND);
173 mask = 0xff >> (prefixlen % 8);
174 sr.base[0] &= mask; /* Ensure pad bits are zero. */
175 RETERR(mem_tobuffer(target, sr.base, octets));
176 isc_buffer_forward(source, octets);
180 return (ISC_R_SUCCESS);
182 dns_name_init(&name, NULL);
183 return (dns_name_fromwire(&name, source, dctx, downcase, target));
186 static inline isc_result_t
187 towire_in_a6(ARGS_TOWIRE) {
190 dns_offsets_t offsets;
191 unsigned char prefixlen;
192 unsigned char octets;
194 REQUIRE(rdata->type == 38);
195 REQUIRE(rdata->rdclass == 1);
196 REQUIRE(rdata->length != 0);
198 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
199 dns_rdata_toregion(rdata, &sr);
200 prefixlen = sr.base[0];
201 INSIST(prefixlen <= 128);
203 octets = 1 + 16 - prefixlen / 8;
204 RETERR(mem_tobuffer(target, sr.base, octets));
205 isc_region_consume(&sr, octets);
208 return (ISC_R_SUCCESS);
210 dns_name_init(&name, offsets);
211 dns_name_fromregion(&name, &sr);
212 return (dns_name_towire(&name, cctx, target));
216 compare_in_a6(ARGS_COMPARE) {
218 unsigned char prefixlen1, prefixlen2;
219 unsigned char octets;
222 isc_region_t region1;
223 isc_region_t region2;
225 REQUIRE(rdata1->type == rdata2->type);
226 REQUIRE(rdata1->rdclass == rdata2->rdclass);
227 REQUIRE(rdata1->type == 38);
228 REQUIRE(rdata1->rdclass == 1);
229 REQUIRE(rdata1->length != 0);
230 REQUIRE(rdata2->length != 0);
232 dns_rdata_toregion(rdata1, ®ion1);
233 dns_rdata_toregion(rdata2, ®ion2);
234 prefixlen1 = region1.base[0];
235 prefixlen2 = region2.base[0];
236 isc_region_consume(®ion1, 1);
237 isc_region_consume(®ion2, 1);
238 if (prefixlen1 < prefixlen2)
240 else if (prefixlen1 > prefixlen2)
243 * Prefix lengths are equal.
245 octets = 16 - prefixlen1 / 8;
248 order = memcmp(region1.base, region2.base, octets);
254 * Address suffixes are equal.
258 isc_region_consume(®ion1, octets);
259 isc_region_consume(®ion2, octets);
262 dns_name_init(&name1, NULL);
263 dns_name_init(&name2, NULL);
264 dns_name_fromregion(&name1, ®ion1);
265 dns_name_fromregion(&name2, ®ion2);
266 return (dns_name_rdatacompare(&name1, &name2));
269 static inline isc_result_t
270 fromstruct_in_a6(ARGS_FROMSTRUCT) {
271 dns_rdata_in_a6_t *a6 = source;
279 REQUIRE(rdclass == 1);
280 REQUIRE(source != NULL);
281 REQUIRE(a6->common.rdtype == type);
282 REQUIRE(a6->common.rdclass == rdclass);
287 if (a6->prefixlen > 128)
288 return (ISC_R_RANGE);
290 RETERR(uint8_tobuffer(a6->prefixlen, target));
293 if (a6->prefixlen != 128) {
294 octets = 16 - a6->prefixlen / 8;
295 bits = a6->prefixlen % 8;
297 mask = 0xffU >> bits;
298 first = a6->in6_addr.s6_addr[16 - octets] & mask;
299 RETERR(uint8_tobuffer(first, target));
303 RETERR(mem_tobuffer(target,
304 a6->in6_addr.s6_addr + 16 - octets,
308 if (a6->prefixlen == 0)
309 return (ISC_R_SUCCESS);
310 dns_name_toregion(&a6->prefix, ®ion);
311 return (isc_buffer_copyregion(target, ®ion));
314 static inline isc_result_t
315 tostruct_in_a6(ARGS_TOSTRUCT) {
316 dns_rdata_in_a6_t *a6 = target;
317 unsigned char octets;
321 REQUIRE(rdata->type == 38);
322 REQUIRE(rdata->rdclass == 1);
323 REQUIRE(target != NULL);
324 REQUIRE(rdata->length != 0);
326 a6->common.rdclass = rdata->rdclass;
327 a6->common.rdtype = rdata->type;
328 ISC_LINK_INIT(&a6->common, link);
330 dns_rdata_toregion(rdata, &r);
332 a6->prefixlen = uint8_fromregion(&r);
333 isc_region_consume(&r, 1);
334 memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
339 if (a6->prefixlen != 128) {
340 octets = 16 - a6->prefixlen / 8;
341 INSIST(r.length >= octets);
342 memcpy(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
343 isc_region_consume(&r, octets);
349 dns_name_init(&a6->prefix, NULL);
350 if (a6->prefixlen != 0) {
351 dns_name_init(&name, NULL);
352 dns_name_fromregion(&name, &r);
353 RETERR(name_duporclone(&name, mctx, &a6->prefix));
356 return (ISC_R_SUCCESS);
360 freestruct_in_a6(ARGS_FREESTRUCT) {
361 dns_rdata_in_a6_t *a6 = source;
363 REQUIRE(source != NULL);
364 REQUIRE(a6->common.rdclass == 1);
365 REQUIRE(a6->common.rdtype == 38);
367 if (a6->mctx == NULL)
370 if (dns_name_dynamic(&a6->prefix))
371 dns_name_free(&a6->prefix, a6->mctx);
375 static inline isc_result_t
376 additionaldata_in_a6(ARGS_ADDLDATA) {
377 REQUIRE(rdata->type == 38);
378 REQUIRE(rdata->rdclass == 1);
384 return (ISC_R_SUCCESS);
387 static inline isc_result_t
388 digest_in_a6(ARGS_DIGEST) {
390 unsigned char prefixlen, octets;
394 REQUIRE(rdata->type == 38);
395 REQUIRE(rdata->rdclass == 1);
397 dns_rdata_toregion(rdata, &r1);
399 prefixlen = r1.base[0];
400 octets = 1 + 16 - prefixlen / 8;
403 result = (digest)(arg, &r1);
404 if (result != ISC_R_SUCCESS)
407 return (ISC_R_SUCCESS);
409 isc_region_consume(&r2, octets);
410 dns_name_init(&name, NULL);
411 dns_name_fromregion(&name, &r2);
412 return (dns_name_digest(&name, digest, arg));
415 #endif /* RDATA_IN_1_A6_38_C */