15185a700Sflorian /*
25185a700Sflorian * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian *
45185a700Sflorian * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian * copyright notice and this permission notice appear in all copies.
75185a700Sflorian *
85185a700Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian */
165185a700Sflorian
17*1fb015a8Sflorian /* $Id: a6_38.c,v 1.14 2020/09/14 08:40:44 florian Exp $ */
185185a700Sflorian
195185a700Sflorian /* RFC2874 */
205185a700Sflorian
215185a700Sflorian #ifndef RDATA_IN_1_A6_28_C
225185a700Sflorian #define RDATA_IN_1_A6_28_C
235185a700Sflorian
245185a700Sflorian static inline isc_result_t
totext_in_a6(ARGS_TOTEXT)255185a700Sflorian totext_in_a6(ARGS_TOTEXT) {
265185a700Sflorian isc_region_t sr, ar;
275185a700Sflorian unsigned char addr[16];
285185a700Sflorian unsigned char prefixlen;
295185a700Sflorian unsigned char octets;
305185a700Sflorian unsigned char mask;
315185a700Sflorian char buf[sizeof("128")];
325185a700Sflorian dns_name_t name;
335185a700Sflorian dns_name_t prefix;
34*1fb015a8Sflorian int sub;
355185a700Sflorian
365185a700Sflorian REQUIRE(rdata->type == dns_rdatatype_a6);
375185a700Sflorian REQUIRE(rdata->rdclass == dns_rdataclass_in);
385185a700Sflorian REQUIRE(rdata->length != 0);
395185a700Sflorian
405185a700Sflorian dns_rdata_toregion(rdata, &sr);
415185a700Sflorian prefixlen = sr.base[0];
425185a700Sflorian INSIST(prefixlen <= 128);
435185a700Sflorian isc_region_consume(&sr, 1);
445185a700Sflorian snprintf(buf, sizeof(buf), "%u", prefixlen);
45873f12b9Sflorian RETERR(isc_str_tobuffer(buf, target));
46873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
475185a700Sflorian
485185a700Sflorian if (prefixlen != 128) {
495185a700Sflorian octets = prefixlen/8;
505185a700Sflorian memset(addr, 0, sizeof(addr));
515185a700Sflorian memmove(&addr[octets], sr.base, 16 - octets);
525185a700Sflorian mask = 0xff >> (prefixlen % 8);
535185a700Sflorian addr[octets] &= mask;
545185a700Sflorian ar.base = addr;
555185a700Sflorian ar.length = sizeof(addr);
565185a700Sflorian RETERR(inet_totext(AF_INET6, &ar, target));
575185a700Sflorian isc_region_consume(&sr, 16 - octets);
585185a700Sflorian }
595185a700Sflorian
605185a700Sflorian if (prefixlen == 0)
615185a700Sflorian return (ISC_R_SUCCESS);
625185a700Sflorian
63873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
645185a700Sflorian dns_name_init(&name, NULL);
655185a700Sflorian dns_name_init(&prefix, NULL);
665185a700Sflorian dns_name_fromregion(&name, &sr);
675185a700Sflorian sub = name_prefix(&name, tctx->origin, &prefix);
685185a700Sflorian return (dns_name_totext(&prefix, sub, target));
695185a700Sflorian }
705185a700Sflorian
715185a700Sflorian static inline isc_result_t
fromwire_in_a6(ARGS_FROMWIRE)725185a700Sflorian fromwire_in_a6(ARGS_FROMWIRE) {
735185a700Sflorian isc_region_t sr;
745185a700Sflorian unsigned char prefixlen;
755185a700Sflorian unsigned char octets;
765185a700Sflorian unsigned char mask;
775185a700Sflorian dns_name_t name;
785185a700Sflorian
795185a700Sflorian REQUIRE(type == dns_rdatatype_a6);
805185a700Sflorian REQUIRE(rdclass == dns_rdataclass_in);
815185a700Sflorian
825185a700Sflorian UNUSED(type);
835185a700Sflorian UNUSED(rdclass);
845185a700Sflorian
855185a700Sflorian dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
865185a700Sflorian
875185a700Sflorian isc_buffer_activeregion(source, &sr);
885185a700Sflorian /*
895185a700Sflorian * Prefix length.
905185a700Sflorian */
915185a700Sflorian if (sr.length < 1)
925185a700Sflorian return (ISC_R_UNEXPECTEDEND);
935185a700Sflorian prefixlen = sr.base[0];
945185a700Sflorian if (prefixlen > 128)
955185a700Sflorian return (ISC_R_RANGE);
965185a700Sflorian isc_region_consume(&sr, 1);
97637d8eb6Sflorian RETERR(isc_mem_tobuffer(target, &prefixlen, 1));
985185a700Sflorian isc_buffer_forward(source, 1);
995185a700Sflorian
1005185a700Sflorian /*
1015185a700Sflorian * Suffix.
1025185a700Sflorian */
1035185a700Sflorian if (prefixlen != 128) {
1045185a700Sflorian octets = 16 - prefixlen / 8;
1055185a700Sflorian if (sr.length < octets)
1065185a700Sflorian return (ISC_R_UNEXPECTEDEND);
1075185a700Sflorian mask = 0xff >> (prefixlen % 8);
1085185a700Sflorian sr.base[0] &= mask; /* Ensure pad bits are zero. */
109637d8eb6Sflorian RETERR(isc_mem_tobuffer(target, sr.base, octets));
1105185a700Sflorian isc_buffer_forward(source, octets);
1115185a700Sflorian }
1125185a700Sflorian
1135185a700Sflorian if (prefixlen == 0)
1145185a700Sflorian return (ISC_R_SUCCESS);
1155185a700Sflorian
1165185a700Sflorian dns_name_init(&name, NULL);
1175185a700Sflorian return (dns_name_fromwire(&name, source, dctx, options, target));
1185185a700Sflorian }
1195185a700Sflorian
1205185a700Sflorian static inline isc_result_t
towire_in_a6(ARGS_TOWIRE)1215185a700Sflorian towire_in_a6(ARGS_TOWIRE) {
1225185a700Sflorian isc_region_t sr;
1235185a700Sflorian dns_name_t name;
1245185a700Sflorian dns_offsets_t offsets;
1255185a700Sflorian unsigned char prefixlen;
1265185a700Sflorian unsigned char octets;
1275185a700Sflorian
1285185a700Sflorian REQUIRE(rdata->type == dns_rdatatype_a6);
1295185a700Sflorian REQUIRE(rdata->rdclass == dns_rdataclass_in);
1305185a700Sflorian REQUIRE(rdata->length != 0);
1315185a700Sflorian
1325185a700Sflorian dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
1335185a700Sflorian dns_rdata_toregion(rdata, &sr);
1345185a700Sflorian prefixlen = sr.base[0];
1355185a700Sflorian INSIST(prefixlen <= 128);
1365185a700Sflorian
1375185a700Sflorian octets = 1 + 16 - prefixlen / 8;
138637d8eb6Sflorian RETERR(isc_mem_tobuffer(target, sr.base, octets));
1395185a700Sflorian isc_region_consume(&sr, octets);
1405185a700Sflorian
1415185a700Sflorian if (prefixlen == 0)
1425185a700Sflorian return (ISC_R_SUCCESS);
1435185a700Sflorian
1445185a700Sflorian dns_name_init(&name, offsets);
1455185a700Sflorian dns_name_fromregion(&name, &sr);
1465185a700Sflorian return (dns_name_towire(&name, cctx, target));
1475185a700Sflorian }
1485185a700Sflorian
1495185a700Sflorian #endif /* RDATA_IN_1_A6_38_C */
150