Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / rdata / in_1 / a6_38.c
blobbf9cab30df018eb4c32fccb3f350ddb820ef6d6f
1 /*
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 $ */
20 /* RFC2874 */
22 #ifndef RDATA_IN_1_A6_28_C
23 #define RDATA_IN_1_A6_28_C
25 #include <isc/net.h>
27 #define RRTYPE_A6_ATTRIBUTES (0)
29 static inline isc_result_t
30 fromtext_in_a6(ARGS_FROMTEXT) {
31 isc_token_t token;
32 unsigned char addr[16];
33 unsigned char prefixlen;
34 unsigned char octets;
35 unsigned char mask;
36 dns_name_t name;
37 isc_buffer_t buffer;
39 REQUIRE(type == 38);
40 REQUIRE(rdclass == 1);
42 UNUSED(type);
43 UNUSED(rdclass);
44 UNUSED(callbacks);
47 * Prefix length.
49 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
50 ISC_FALSE));
51 if (token.value.as_ulong > 128U)
52 RETTOK(ISC_R_RANGE);
54 prefixlen = (unsigned char)token.value.as_ulong;
55 RETERR(mem_tobuffer(target, &prefixlen, 1));
58 * Suffix.
60 if (prefixlen != 128) {
62 * Prefix 0..127.
64 octets = prefixlen/8;
66 * Octets 0..15.
68 RETERR(isc_lex_getmastertoken(lexer, &token,
69 isc_tokentype_string,
70 ISC_FALSE));
71 if (inet_pton(AF_INET6, token.value.as_pointer, addr) != 1)
72 RETTOK(DNS_R_BADAAAA);
73 mask = 0xff >> (prefixlen % 8);
74 addr[octets] &= mask;
75 RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
78 if (prefixlen == 0)
79 return (ISC_R_SUCCESS);
81 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
82 ISC_FALSE));
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) {
92 isc_region_t sr, ar;
93 unsigned char addr[16];
94 unsigned char prefixlen;
95 unsigned char octets;
96 unsigned char mask;
97 char buf[sizeof "128"];
98 dns_name_t name;
99 dns_name_t prefix;
100 isc_boolean_t sub;
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;
120 ar.base = addr;
121 ar.length = sizeof(addr);
122 RETERR(inet_totext(AF_INET6, &ar, target));
123 isc_region_consume(&sr, 16 - octets);
126 if (prefixlen == 0)
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) {
139 isc_region_t sr;
140 unsigned char prefixlen;
141 unsigned char octets;
142 unsigned char mask;
143 dns_name_t name;
145 REQUIRE(type == 38);
146 REQUIRE(rdclass == 1);
148 UNUSED(type);
149 UNUSED(rdclass);
151 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
153 isc_buffer_activeregion(source, &sr);
155 * Prefix length.
157 if (sr.length < 1)
158 return (ISC_R_UNEXPECTEDEND);
159 prefixlen = sr.base[0];
160 if (prefixlen > 128)
161 return (ISC_R_RANGE);
162 isc_region_consume(&sr, 1);
163 RETERR(mem_tobuffer(target, &prefixlen, 1));
164 isc_buffer_forward(source, 1);
167 * Suffix.
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);
179 if (prefixlen == 0)
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) {
188 isc_region_t sr;
189 dns_name_t name;
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);
207 if (prefixlen == 0)
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));
215 static inline int
216 compare_in_a6(ARGS_COMPARE) {
217 int order;
218 unsigned char prefixlen1, prefixlen2;
219 unsigned char octets;
220 dns_name_t name1;
221 dns_name_t name2;
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, &region1);
233 dns_rdata_toregion(rdata2, &region2);
234 prefixlen1 = region1.base[0];
235 prefixlen2 = region2.base[0];
236 isc_region_consume(&region1, 1);
237 isc_region_consume(&region2, 1);
238 if (prefixlen1 < prefixlen2)
239 return (-1);
240 else if (prefixlen1 > prefixlen2)
241 return (1);
243 * Prefix lengths are equal.
245 octets = 16 - prefixlen1 / 8;
247 if (octets > 0) {
248 order = memcmp(region1.base, region2.base, octets);
249 if (order < 0)
250 return (-1);
251 else if (order > 0)
252 return (1);
254 * Address suffixes are equal.
256 if (prefixlen1 == 0)
257 return (order);
258 isc_region_consume(&region1, octets);
259 isc_region_consume(&region2, octets);
262 dns_name_init(&name1, NULL);
263 dns_name_init(&name2, NULL);
264 dns_name_fromregion(&name1, &region1);
265 dns_name_fromregion(&name2, &region2);
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;
272 isc_region_t region;
273 int octets;
274 isc_uint8_t bits;
275 isc_uint8_t first;
276 isc_uint8_t mask;
278 REQUIRE(type == 38);
279 REQUIRE(rdclass == 1);
280 REQUIRE(source != NULL);
281 REQUIRE(a6->common.rdtype == type);
282 REQUIRE(a6->common.rdclass == rdclass);
284 UNUSED(type);
285 UNUSED(rdclass);
287 if (a6->prefixlen > 128)
288 return (ISC_R_RANGE);
290 RETERR(uint8_tobuffer(a6->prefixlen, target));
292 /* Suffix */
293 if (a6->prefixlen != 128) {
294 octets = 16 - a6->prefixlen / 8;
295 bits = a6->prefixlen % 8;
296 if (bits != 0) {
297 mask = 0xffU >> bits;
298 first = a6->in6_addr.s6_addr[16 - octets] & mask;
299 RETERR(uint8_tobuffer(first, target));
300 octets--;
302 if (octets > 0)
303 RETERR(mem_tobuffer(target,
304 a6->in6_addr.s6_addr + 16 - octets,
305 octets));
308 if (a6->prefixlen == 0)
309 return (ISC_R_SUCCESS);
310 dns_name_toregion(&a6->prefix, &region);
311 return (isc_buffer_copyregion(target, &region));
314 static inline isc_result_t
315 tostruct_in_a6(ARGS_TOSTRUCT) {
316 dns_rdata_in_a6_t *a6 = target;
317 unsigned char octets;
318 dns_name_t name;
319 isc_region_t r;
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));
337 * Suffix.
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);
347 * Prefix.
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));
355 a6->mctx = mctx;
356 return (ISC_R_SUCCESS);
359 static inline void
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)
368 return;
370 if (dns_name_dynamic(&a6->prefix))
371 dns_name_free(&a6->prefix, a6->mctx);
372 a6->mctx = NULL;
375 static inline isc_result_t
376 additionaldata_in_a6(ARGS_ADDLDATA) {
377 REQUIRE(rdata->type == 38);
378 REQUIRE(rdata->rdclass == 1);
380 UNUSED(rdata);
381 UNUSED(add);
382 UNUSED(arg);
384 return (ISC_R_SUCCESS);
387 static inline isc_result_t
388 digest_in_a6(ARGS_DIGEST) {
389 isc_region_t r1, r2;
390 unsigned char prefixlen, octets;
391 isc_result_t result;
392 dns_name_t name;
394 REQUIRE(rdata->type == 38);
395 REQUIRE(rdata->rdclass == 1);
397 dns_rdata_toregion(rdata, &r1);
398 r2 = r1;
399 prefixlen = r1.base[0];
400 octets = 1 + 16 - prefixlen / 8;
402 r1.length = octets;
403 result = (digest)(arg, &r1);
404 if (result != ISC_R_SUCCESS)
405 return (result);
406 if (prefixlen == 0)
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 */