Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / bind-9.3 / lib / dns / rdata / in_1 / a6_38.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 /* $Id: a6_38.c,v 1.46.2.1.2.5 2004/03/08 09:04:43 marka Exp $ */
19
20 /* RFC2874 */
21
22 #ifndef RDATA_IN_1_A6_28_C
23 #define RDATA_IN_1_A6_28_C
24
25 #include <isc/net.h>
26
27 #define RRTYPE_A6_ATTRIBUTES (0)
28
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;
38         isc_boolean_t ok;
39
40         REQUIRE(type == 38);
41         REQUIRE(rdclass == 1);
42
43         UNUSED(type);
44         UNUSED(rdclass);
45         UNUSED(callbacks);
46
47         /*
48          * Prefix length.
49          */
50         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
51                                       ISC_FALSE));
52         if (token.value.as_ulong > 128U)
53                 RETTOK(ISC_R_RANGE);
54
55         prefixlen = (unsigned char)token.value.as_ulong;
56         RETERR(mem_tobuffer(target, &prefixlen, 1));
57
58         /*
59          * Suffix.
60          */
61         if (prefixlen != 128) {
62                 /*
63                  * Prefix 0..127.
64                  */
65                 octets = prefixlen/8;
66                 /*
67                  * Octets 0..15.
68                  */
69                 RETERR(isc_lex_getmastertoken(lexer, &token,
70                                               isc_tokentype_string,
71                                               ISC_FALSE));
72                 if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1)
73                         RETTOK(DNS_R_BADAAAA);
74                 mask = 0xff >> (prefixlen % 8);
75                 addr[octets] &= mask;
76                 RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
77         }
78
79         if (prefixlen == 0)
80                 return (ISC_R_SUCCESS);
81
82         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
83                                       ISC_FALSE));
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));
88         ok = ISC_TRUE;
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);
96 }
97
98 static inline isc_result_t
99 totext_in_a6(ARGS_TOTEXT) {
100         isc_region_t sr, ar;
101         unsigned char addr[16];
102         unsigned char prefixlen;
103         unsigned char octets;
104         unsigned char mask;
105         char buf[sizeof("128")];
106         dns_name_t name;
107         dns_name_t prefix;
108         isc_boolean_t sub;
109
110         REQUIRE(rdata->type == 38);
111         REQUIRE(rdata->rdclass == 1);
112         REQUIRE(rdata->length != 0);
113
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));
121
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;
128                 ar.base = addr;
129                 ar.length = sizeof(addr);
130                 RETERR(inet_totext(AF_INET6, &ar, target));
131                 isc_region_consume(&sr, 16 - octets);
132         }
133
134         if (prefixlen == 0)
135                 return (ISC_R_SUCCESS);
136
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));
143 }
144
145 static inline isc_result_t
146 fromwire_in_a6(ARGS_FROMWIRE) {
147         isc_region_t sr;
148         unsigned char prefixlen;
149         unsigned char octets;
150         unsigned char mask;
151         dns_name_t name;
152
153         REQUIRE(type == 38);
154         REQUIRE(rdclass == 1);
155
156         UNUSED(type);
157         UNUSED(rdclass);
158
159         dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
160
161         isc_buffer_activeregion(source, &sr);
162         /*
163          * Prefix length.
164          */
165         if (sr.length < 1)
166                 return (ISC_R_UNEXPECTEDEND);
167         prefixlen = sr.base[0];
168         if (prefixlen > 128)
169                 return (ISC_R_RANGE);
170         isc_region_consume(&sr, 1);
171         RETERR(mem_tobuffer(target, &prefixlen, 1));
172         isc_buffer_forward(source, 1);
173
174         /*
175          * Suffix.
176          */
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);
185         }
186
187         if (prefixlen == 0)
188                 return (ISC_R_SUCCESS);
189
190         dns_name_init(&name, NULL);
191         return (dns_name_fromwire(&name, source, dctx, options, target));
192 }
193
194 static inline isc_result_t
195 towire_in_a6(ARGS_TOWIRE) {
196         isc_region_t sr;
197         dns_name_t name;
198         dns_offsets_t offsets;
199         unsigned char prefixlen;
200         unsigned char octets;
201
202         REQUIRE(rdata->type == 38);
203         REQUIRE(rdata->rdclass == 1);
204         REQUIRE(rdata->length != 0);
205
206         dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
207         dns_rdata_toregion(rdata, &sr);
208         prefixlen = sr.base[0];
209         INSIST(prefixlen <= 128);
210
211         octets = 1 + 16 - prefixlen / 8;
212         RETERR(mem_tobuffer(target, sr.base, octets));
213         isc_region_consume(&sr, octets);
214
215         if (prefixlen == 0)
216                 return (ISC_R_SUCCESS);
217
218         dns_name_init(&name, offsets);
219         dns_name_fromregion(&name, &sr);
220         return (dns_name_towire(&name, cctx, target));
221 }
222
223 static inline int
224 compare_in_a6(ARGS_COMPARE) {
225         int order;
226         unsigned char prefixlen1, prefixlen2;
227         unsigned char octets;
228         dns_name_t name1;
229         dns_name_t name2;
230         isc_region_t region1;
231         isc_region_t region2;
232
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);
239
240         dns_rdata_toregion(rdata1, &region1);
241         dns_rdata_toregion(rdata2, &region2);
242         prefixlen1 = region1.base[0];
243         prefixlen2 = region2.base[0];
244         isc_region_consume(&region1, 1);
245         isc_region_consume(&region2, 1);
246         if (prefixlen1 < prefixlen2)
247                 return (-1);
248         else if (prefixlen1 > prefixlen2)
249                 return (1);
250         /*
251          * Prefix lengths are equal.
252          */
253         octets = 16 - prefixlen1 / 8;
254
255         if (octets > 0) {
256                 order = memcmp(region1.base, region2.base, octets);
257                 if (order < 0)
258                         return (-1);
259                 else if (order > 0)
260                         return (1);
261                 /*
262                  * Address suffixes are equal.
263                  */
264                 if (prefixlen1 == 0)
265                         return (order);
266                 isc_region_consume(&region1, octets);
267                 isc_region_consume(&region2, octets);
268         }
269
270         dns_name_init(&name1, NULL);
271         dns_name_init(&name2, NULL);
272         dns_name_fromregion(&name1, &region1);
273         dns_name_fromregion(&name2, &region2);
274         return (dns_name_rdatacompare(&name1, &name2));
275 }
276
277 static inline isc_result_t
278 fromstruct_in_a6(ARGS_FROMSTRUCT) {
279         dns_rdata_in_a6_t *a6 = source;
280         isc_region_t region;
281         int octets;
282         isc_uint8_t bits;
283         isc_uint8_t first;
284         isc_uint8_t mask;
285
286         REQUIRE(type == 38);
287         REQUIRE(rdclass == 1);
288         REQUIRE(source != NULL);
289         REQUIRE(a6->common.rdtype == type);
290         REQUIRE(a6->common.rdclass == rdclass);
291
292         UNUSED(type);
293         UNUSED(rdclass);
294
295         if (a6->prefixlen > 128)
296                 return (ISC_R_RANGE);
297
298         RETERR(uint8_tobuffer(a6->prefixlen, target));
299
300         /* Suffix */
301         if (a6->prefixlen != 128) {
302                 octets = 16 - a6->prefixlen / 8;
303                 bits = a6->prefixlen % 8;
304                 if (bits != 0) {
305                         mask = 0xffU >> bits;
306                         first = a6->in6_addr.s6_addr[16 - octets] & mask;
307                         RETERR(uint8_tobuffer(first, target));
308                         octets--;
309                 }
310                 if (octets > 0)
311                         RETERR(mem_tobuffer(target,
312                                             a6->in6_addr.s6_addr + 16 - octets,
313                                             octets));
314         }
315
316         if (a6->prefixlen == 0)
317                 return (ISC_R_SUCCESS);
318         dns_name_toregion(&a6->prefix, &region);
319         return (isc_buffer_copyregion(target, &region));
320 }
321
322 static inline isc_result_t
323 tostruct_in_a6(ARGS_TOSTRUCT) {
324         dns_rdata_in_a6_t *a6 = target;
325         unsigned char octets;
326         dns_name_t name;
327         isc_region_t r;
328
329         REQUIRE(rdata->type == 38);
330         REQUIRE(rdata->rdclass == 1);
331         REQUIRE(target != NULL);
332         REQUIRE(rdata->length != 0);
333
334         a6->common.rdclass = rdata->rdclass;
335         a6->common.rdtype = rdata->type;
336         ISC_LINK_INIT(&a6->common, link);
337
338         dns_rdata_toregion(rdata, &r);
339
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));
343
344         /*
345          * Suffix.
346          */
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);
352         }
353
354         /*
355          * Prefix.
356          */
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));
362         }
363         a6->mctx = mctx;
364         return (ISC_R_SUCCESS);
365 }
366
367 static inline void
368 freestruct_in_a6(ARGS_FREESTRUCT) {
369         dns_rdata_in_a6_t *a6 = source;
370
371         REQUIRE(source != NULL);
372         REQUIRE(a6->common.rdclass == 1);
373         REQUIRE(a6->common.rdtype == 38);
374
375         if (a6->mctx == NULL)
376                 return;
377
378         if (dns_name_dynamic(&a6->prefix))
379                 dns_name_free(&a6->prefix, a6->mctx);
380         a6->mctx = NULL;
381 }
382
383 static inline isc_result_t
384 additionaldata_in_a6(ARGS_ADDLDATA) {
385         REQUIRE(rdata->type == 38);
386         REQUIRE(rdata->rdclass == 1);
387
388         UNUSED(rdata);
389         UNUSED(add);
390         UNUSED(arg);
391
392         return (ISC_R_SUCCESS);
393 }
394
395 static inline isc_result_t
396 digest_in_a6(ARGS_DIGEST) {
397         isc_region_t r1, r2;
398         unsigned char prefixlen, octets;
399         isc_result_t result;
400         dns_name_t name;
401
402         REQUIRE(rdata->type == 38);
403         REQUIRE(rdata->rdclass == 1);
404
405         dns_rdata_toregion(rdata, &r1);
406         r2 = r1;
407         prefixlen = r1.base[0];
408         octets = 1 + 16 - prefixlen / 8;
409
410         r1.length = octets;
411         result = (digest)(arg, &r1);
412         if (result != ISC_R_SUCCESS)
413                 return (result);
414         if (prefixlen == 0)
415                 return (ISC_R_SUCCESS);
416
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));
421 }
422
423 static inline isc_boolean_t
424 checkowner_in_a6(ARGS_CHECKOWNER) {
425
426         REQUIRE(type == 38);
427         REQUIRE(rdclass == 1);
428
429         UNUSED(type);
430         UNUSED(rdclass);
431
432         return (dns_name_ishostname(name, wildcard));
433 }
434
435 static inline isc_boolean_t
436 checknames_in_a6(ARGS_CHECKNAMES) {
437         isc_region_t region;
438         dns_name_t name;
439         unsigned int prefixlen;
440
441         REQUIRE(rdata->type == 38);
442         REQUIRE(rdata->rdclass == 1);
443
444         UNUSED(owner);
445
446         dns_rdata_toregion(rdata, &region);
447         prefixlen = uint8_fromregion(&region);
448         if (prefixlen == 0)
449                 return (ISC_TRUE);
450         isc_region_consume(&region, 1 + 16 - prefixlen / 8);
451         dns_name_init(&name, NULL);
452         dns_name_fromregion(&name, &region);
453         if (!dns_name_ishostname(&name, ISC_FALSE)) {
454                 if (bad != NULL)
455                         dns_name_clone(&name, bad);
456                 return (ISC_FALSE);
457         }
458         return (ISC_TRUE);
459 }
460
461 #endif  /* RDATA_IN_1_A6_38_C */