]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/rdata/in_1/a6_38.c
MFV r306384:
[FreeBSD/stable/9.git] / contrib / bind9 / lib / dns / rdata / in_1 / a6_38.c
1 /*
2  * Copyright (C) 2004, 2007, 2009, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or 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.56 2009/12/04 22:06:37 tbox 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 == dns_rdatatype_a6);
41         REQUIRE(rdclass == dns_rdataclass_in);
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         if (origin == NULL)
87                 origin = dns_rootname;
88         RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
89         ok = ISC_TRUE;
90         if ((options & DNS_RDATA_CHECKNAMES) != 0)
91                 ok = dns_name_ishostname(&name, ISC_FALSE);
92         if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
93                 RETTOK(DNS_R_BADNAME);
94         if (!ok && callbacks != NULL)
95                 warn_badname(&name, lexer, callbacks);
96         return (ISC_R_SUCCESS);
97 }
98
99 static inline isc_result_t
100 totext_in_a6(ARGS_TOTEXT) {
101         isc_region_t sr, ar;
102         unsigned char addr[16];
103         unsigned char prefixlen;
104         unsigned char octets;
105         unsigned char mask;
106         char buf[sizeof("128")];
107         dns_name_t name;
108         dns_name_t prefix;
109         isc_boolean_t sub;
110
111         REQUIRE(rdata->type == dns_rdatatype_a6);
112         REQUIRE(rdata->rdclass == dns_rdataclass_in);
113         REQUIRE(rdata->length != 0);
114
115         dns_rdata_toregion(rdata, &sr);
116         prefixlen = sr.base[0];
117         INSIST(prefixlen <= 128);
118         isc_region_consume(&sr, 1);
119         sprintf(buf, "%u", prefixlen);
120         RETERR(str_totext(buf, target));
121         RETERR(str_totext(" ", target));
122
123         if (prefixlen != 128) {
124                 octets = prefixlen/8;
125                 memset(addr, 0, sizeof(addr));
126                 memmove(&addr[octets], sr.base, 16 - octets);
127                 mask = 0xff >> (prefixlen % 8);
128                 addr[octets] &= mask;
129                 ar.base = addr;
130                 ar.length = sizeof(addr);
131                 RETERR(inet_totext(AF_INET6, &ar, target));
132                 isc_region_consume(&sr, 16 - octets);
133         }
134
135         if (prefixlen == 0)
136                 return (ISC_R_SUCCESS);
137
138         RETERR(str_totext(" ", target));
139         dns_name_init(&name, NULL);
140         dns_name_init(&prefix, NULL);
141         dns_name_fromregion(&name, &sr);
142         sub = name_prefix(&name, tctx->origin, &prefix);
143         return (dns_name_totext(&prefix, sub, target));
144 }
145
146 static inline isc_result_t
147 fromwire_in_a6(ARGS_FROMWIRE) {
148         isc_region_t sr;
149         unsigned char prefixlen;
150         unsigned char octets;
151         unsigned char mask;
152         dns_name_t name;
153
154         REQUIRE(type == dns_rdatatype_a6);
155         REQUIRE(rdclass == dns_rdataclass_in);
156
157         UNUSED(type);
158         UNUSED(rdclass);
159
160         dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
161
162         isc_buffer_activeregion(source, &sr);
163         /*
164          * Prefix length.
165          */
166         if (sr.length < 1)
167                 return (ISC_R_UNEXPECTEDEND);
168         prefixlen = sr.base[0];
169         if (prefixlen > 128)
170                 return (ISC_R_RANGE);
171         isc_region_consume(&sr, 1);
172         RETERR(mem_tobuffer(target, &prefixlen, 1));
173         isc_buffer_forward(source, 1);
174
175         /*
176          * Suffix.
177          */
178         if (prefixlen != 128) {
179                 octets = 16 - prefixlen / 8;
180                 if (sr.length < octets)
181                         return (ISC_R_UNEXPECTEDEND);
182                 mask = 0xff >> (prefixlen % 8);
183                 sr.base[0] &= mask;     /* Ensure pad bits are zero. */
184                 RETERR(mem_tobuffer(target, sr.base, octets));
185                 isc_buffer_forward(source, octets);
186         }
187
188         if (prefixlen == 0)
189                 return (ISC_R_SUCCESS);
190
191         dns_name_init(&name, NULL);
192         return (dns_name_fromwire(&name, source, dctx, options, target));
193 }
194
195 static inline isc_result_t
196 towire_in_a6(ARGS_TOWIRE) {
197         isc_region_t sr;
198         dns_name_t name;
199         dns_offsets_t offsets;
200         unsigned char prefixlen;
201         unsigned char octets;
202
203         REQUIRE(rdata->type == dns_rdatatype_a6);
204         REQUIRE(rdata->rdclass == dns_rdataclass_in);
205         REQUIRE(rdata->length != 0);
206
207         dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
208         dns_rdata_toregion(rdata, &sr);
209         prefixlen = sr.base[0];
210         INSIST(prefixlen <= 128);
211
212         octets = 1 + 16 - prefixlen / 8;
213         RETERR(mem_tobuffer(target, sr.base, octets));
214         isc_region_consume(&sr, octets);
215
216         if (prefixlen == 0)
217                 return (ISC_R_SUCCESS);
218
219         dns_name_init(&name, offsets);
220         dns_name_fromregion(&name, &sr);
221         return (dns_name_towire(&name, cctx, target));
222 }
223
224 static inline int
225 compare_in_a6(ARGS_COMPARE) {
226         int order;
227         unsigned char prefixlen1, prefixlen2;
228         unsigned char octets;
229         dns_name_t name1;
230         dns_name_t name2;
231         isc_region_t region1;
232         isc_region_t region2;
233
234         REQUIRE(rdata1->type == rdata2->type);
235         REQUIRE(rdata1->rdclass == rdata2->rdclass);
236         REQUIRE(rdata1->type == dns_rdatatype_a6);
237         REQUIRE(rdata1->rdclass == dns_rdataclass_in);
238         REQUIRE(rdata1->length != 0);
239         REQUIRE(rdata2->length != 0);
240
241         dns_rdata_toregion(rdata1, &region1);
242         dns_rdata_toregion(rdata2, &region2);
243         prefixlen1 = region1.base[0];
244         prefixlen2 = region2.base[0];
245         isc_region_consume(&region1, 1);
246         isc_region_consume(&region2, 1);
247         if (prefixlen1 < prefixlen2)
248                 return (-1);
249         else if (prefixlen1 > prefixlen2)
250                 return (1);
251         /*
252          * Prefix lengths are equal.
253          */
254         octets = 16 - prefixlen1 / 8;
255
256         if (octets > 0) {
257                 order = memcmp(region1.base, region2.base, octets);
258                 if (order < 0)
259                         return (-1);
260                 else if (order > 0)
261                         return (1);
262                 /*
263                  * Address suffixes are equal.
264                  */
265                 if (prefixlen1 == 0)
266                         return (order);
267                 isc_region_consume(&region1, octets);
268                 isc_region_consume(&region2, octets);
269         }
270
271         dns_name_init(&name1, NULL);
272         dns_name_init(&name2, NULL);
273         dns_name_fromregion(&name1, &region1);
274         dns_name_fromregion(&name2, &region2);
275         return (dns_name_rdatacompare(&name1, &name2));
276 }
277
278 static inline isc_result_t
279 fromstruct_in_a6(ARGS_FROMSTRUCT) {
280         dns_rdata_in_a6_t *a6 = source;
281         isc_region_t region;
282         int octets;
283         isc_uint8_t bits;
284         isc_uint8_t first;
285         isc_uint8_t mask;
286
287         REQUIRE(type == dns_rdatatype_a6);
288         REQUIRE(rdclass == dns_rdataclass_in);
289         REQUIRE(source != NULL);
290         REQUIRE(a6->common.rdtype == type);
291         REQUIRE(a6->common.rdclass == rdclass);
292
293         UNUSED(type);
294         UNUSED(rdclass);
295
296         if (a6->prefixlen > 128)
297                 return (ISC_R_RANGE);
298
299         RETERR(uint8_tobuffer(a6->prefixlen, target));
300
301         /* Suffix */
302         if (a6->prefixlen != 128) {
303                 octets = 16 - a6->prefixlen / 8;
304                 bits = a6->prefixlen % 8;
305                 if (bits != 0) {
306                         mask = 0xffU >> bits;
307                         first = a6->in6_addr.s6_addr[16 - octets] & mask;
308                         RETERR(uint8_tobuffer(first, target));
309                         octets--;
310                 }
311                 if (octets > 0)
312                         RETERR(mem_tobuffer(target,
313                                             a6->in6_addr.s6_addr + 16 - octets,
314                                             octets));
315         }
316
317         if (a6->prefixlen == 0)
318                 return (ISC_R_SUCCESS);
319         dns_name_toregion(&a6->prefix, &region);
320         return (isc_buffer_copyregion(target, &region));
321 }
322
323 static inline isc_result_t
324 tostruct_in_a6(ARGS_TOSTRUCT) {
325         dns_rdata_in_a6_t *a6 = target;
326         unsigned char octets;
327         dns_name_t name;
328         isc_region_t r;
329
330         REQUIRE(rdata->type == dns_rdatatype_a6);
331         REQUIRE(rdata->rdclass == dns_rdataclass_in);
332         REQUIRE(target != NULL);
333         REQUIRE(rdata->length != 0);
334
335         a6->common.rdclass = rdata->rdclass;
336         a6->common.rdtype = rdata->type;
337         ISC_LINK_INIT(&a6->common, link);
338
339         dns_rdata_toregion(rdata, &r);
340
341         a6->prefixlen = uint8_fromregion(&r);
342         isc_region_consume(&r, 1);
343         memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
344
345         /*
346          * Suffix.
347          */
348         if (a6->prefixlen != 128) {
349                 octets = 16 - a6->prefixlen / 8;
350                 INSIST(r.length >= octets);
351                 memmove(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
352                 isc_region_consume(&r, octets);
353         }
354
355         /*
356          * Prefix.
357          */
358         dns_name_init(&a6->prefix, NULL);
359         if (a6->prefixlen != 0) {
360                 dns_name_init(&name, NULL);
361                 dns_name_fromregion(&name, &r);
362                 RETERR(name_duporclone(&name, mctx, &a6->prefix));
363         }
364         a6->mctx = mctx;
365         return (ISC_R_SUCCESS);
366 }
367
368 static inline void
369 freestruct_in_a6(ARGS_FREESTRUCT) {
370         dns_rdata_in_a6_t *a6 = source;
371
372         REQUIRE(source != NULL);
373         REQUIRE(a6->common.rdclass == dns_rdataclass_in);
374         REQUIRE(a6->common.rdtype == dns_rdatatype_a6);
375
376         if (a6->mctx == NULL)
377                 return;
378
379         if (dns_name_dynamic(&a6->prefix))
380                 dns_name_free(&a6->prefix, a6->mctx);
381         a6->mctx = NULL;
382 }
383
384 static inline isc_result_t
385 additionaldata_in_a6(ARGS_ADDLDATA) {
386         REQUIRE(rdata->type == dns_rdatatype_a6);
387         REQUIRE(rdata->rdclass == dns_rdataclass_in);
388
389         UNUSED(rdata);
390         UNUSED(add);
391         UNUSED(arg);
392
393         return (ISC_R_SUCCESS);
394 }
395
396 static inline isc_result_t
397 digest_in_a6(ARGS_DIGEST) {
398         isc_region_t r1, r2;
399         unsigned char prefixlen, octets;
400         isc_result_t result;
401         dns_name_t name;
402
403         REQUIRE(rdata->type == dns_rdatatype_a6);
404         REQUIRE(rdata->rdclass == dns_rdataclass_in);
405
406         dns_rdata_toregion(rdata, &r1);
407         r2 = r1;
408         prefixlen = r1.base[0];
409         octets = 1 + 16 - prefixlen / 8;
410
411         r1.length = octets;
412         result = (digest)(arg, &r1);
413         if (result != ISC_R_SUCCESS)
414                 return (result);
415         if (prefixlen == 0)
416                 return (ISC_R_SUCCESS);
417
418         isc_region_consume(&r2, octets);
419         dns_name_init(&name, NULL);
420         dns_name_fromregion(&name, &r2);
421         return (dns_name_digest(&name, digest, arg));
422 }
423
424 static inline isc_boolean_t
425 checkowner_in_a6(ARGS_CHECKOWNER) {
426
427         REQUIRE(type == dns_rdatatype_a6);
428         REQUIRE(rdclass == dns_rdataclass_in);
429
430         UNUSED(type);
431         UNUSED(rdclass);
432
433         return (dns_name_ishostname(name, wildcard));
434 }
435
436 static inline isc_boolean_t
437 checknames_in_a6(ARGS_CHECKNAMES) {
438         isc_region_t region;
439         dns_name_t name;
440         unsigned int prefixlen;
441
442         REQUIRE(rdata->type == dns_rdatatype_a6);
443         REQUIRE(rdata->rdclass == dns_rdataclass_in);
444
445         UNUSED(owner);
446
447         dns_rdata_toregion(rdata, &region);
448         prefixlen = uint8_fromregion(&region);
449         if (prefixlen == 0)
450                 return (ISC_TRUE);
451         isc_region_consume(&region, 1 + 16 - prefixlen / 8);
452         dns_name_init(&name, NULL);
453         dns_name_fromregion(&name, &region);
454         if (!dns_name_ishostname(&name, ISC_FALSE)) {
455                 if (bad != NULL)
456                         dns_name_clone(&name, bad);
457                 return (ISC_FALSE);
458         }
459         return (ISC_TRUE);
460 }
461
462 static inline int
463 casecompare_in_a6(ARGS_COMPARE) {
464         return (compare_in_a6(rdata1, rdata2));
465 }
466
467 #endif  /* RDATA_IN_1_A6_38_C */