Home | History | Annotate | Line # | Download | only in in_1
      1 /*	$NetBSD: aaaa_28.c,v 1.12 2026/01/29 18:37:54 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /* RFC1886 */
     17 
     18 #ifndef RDATA_IN_1_AAAA_28_C
     19 #define RDATA_IN_1_AAAA_28_C
     20 
     21 #include <isc/net.h>
     22 
     23 #define RRTYPE_AAAA_ATTRIBUTES (0)
     24 
     25 static isc_result_t
     26 fromtext_in_aaaa(ARGS_FROMTEXT) {
     27 	isc_token_t token;
     28 	unsigned char addr[16];
     29 	isc_region_t region;
     30 
     31 	REQUIRE(type == dns_rdatatype_aaaa);
     32 	REQUIRE(rdclass == dns_rdataclass_in);
     33 
     34 	UNUSED(type);
     35 	UNUSED(origin);
     36 	UNUSED(options);
     37 	UNUSED(rdclass);
     38 	UNUSED(callbacks);
     39 
     40 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     41 				      false));
     42 
     43 	if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1) {
     44 		RETTOK(DNS_R_BADAAAA);
     45 	}
     46 	isc_buffer_availableregion(target, &region);
     47 	if (region.length < 16) {
     48 		return ISC_R_NOSPACE;
     49 	}
     50 	memmove(region.base, addr, 16);
     51 	isc_buffer_add(target, 16);
     52 	return ISC_R_SUCCESS;
     53 }
     54 
     55 static isc_result_t
     56 totext_in_aaaa(ARGS_TOTEXT) {
     57 	isc_region_t region;
     58 
     59 	REQUIRE(rdata->type == dns_rdatatype_aaaa);
     60 	REQUIRE(rdata->rdclass == dns_rdataclass_in);
     61 	REQUIRE(rdata->length == 16);
     62 
     63 	if ((tctx->flags & DNS_STYLEFLAG_EXPANDAAAA) != 0) {
     64 		char buf[5 * 8];
     65 		const char *sep = "";
     66 		int i, n;
     67 		unsigned int len = 0;
     68 
     69 		for (i = 0; i < 16; i += 2) {
     70 			INSIST(len < sizeof(buf));
     71 			n = snprintf(buf + len, sizeof(buf) - len, "%s%02x%02x",
     72 				     sep, rdata->data[i], rdata->data[i + 1]);
     73 			if (n < 0) {
     74 				return ISC_R_FAILURE;
     75 			}
     76 			len += n;
     77 			sep = ":";
     78 		}
     79 		return str_totext(buf, target);
     80 	}
     81 	dns_rdata_toregion(rdata, &region);
     82 	return inet_totext(AF_INET6, tctx->flags, &region, target);
     83 }
     84 
     85 static isc_result_t
     86 fromwire_in_aaaa(ARGS_FROMWIRE) {
     87 	isc_region_t sregion;
     88 	isc_region_t tregion;
     89 
     90 	REQUIRE(type == dns_rdatatype_aaaa);
     91 	REQUIRE(rdclass == dns_rdataclass_in);
     92 
     93 	UNUSED(type);
     94 	UNUSED(dctx);
     95 	UNUSED(rdclass);
     96 
     97 	isc_buffer_activeregion(source, &sregion);
     98 	isc_buffer_availableregion(target, &tregion);
     99 	if (sregion.length < 16) {
    100 		return ISC_R_UNEXPECTEDEND;
    101 	}
    102 	if (tregion.length < 16) {
    103 		return ISC_R_NOSPACE;
    104 	}
    105 
    106 	memmove(tregion.base, sregion.base, 16);
    107 	isc_buffer_forward(source, 16);
    108 	isc_buffer_add(target, 16);
    109 	return ISC_R_SUCCESS;
    110 }
    111 
    112 static isc_result_t
    113 towire_in_aaaa(ARGS_TOWIRE) {
    114 	isc_region_t region;
    115 
    116 	UNUSED(cctx);
    117 
    118 	REQUIRE(rdata->type == dns_rdatatype_aaaa);
    119 	REQUIRE(rdata->rdclass == dns_rdataclass_in);
    120 	REQUIRE(rdata->length == 16);
    121 
    122 	isc_buffer_availableregion(target, &region);
    123 	if (region.length < rdata->length) {
    124 		return ISC_R_NOSPACE;
    125 	}
    126 	memmove(region.base, rdata->data, rdata->length);
    127 	isc_buffer_add(target, 16);
    128 	return ISC_R_SUCCESS;
    129 }
    130 
    131 static int
    132 compare_in_aaaa(ARGS_COMPARE) {
    133 	isc_region_t r1;
    134 	isc_region_t r2;
    135 
    136 	REQUIRE(rdata1->type == rdata2->type);
    137 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
    138 	REQUIRE(rdata1->type == dns_rdatatype_aaaa);
    139 	REQUIRE(rdata1->rdclass == dns_rdataclass_in);
    140 	REQUIRE(rdata1->length == 16);
    141 	REQUIRE(rdata2->length == 16);
    142 
    143 	dns_rdata_toregion(rdata1, &r1);
    144 	dns_rdata_toregion(rdata2, &r2);
    145 	return isc_region_compare(&r1, &r2);
    146 }
    147 
    148 static isc_result_t
    149 fromstruct_in_aaaa(ARGS_FROMSTRUCT) {
    150 	dns_rdata_in_aaaa_t *aaaa = source;
    151 
    152 	REQUIRE(type == dns_rdatatype_aaaa);
    153 	REQUIRE(rdclass == dns_rdataclass_in);
    154 	REQUIRE(aaaa != NULL);
    155 	REQUIRE(aaaa->common.rdtype == type);
    156 	REQUIRE(aaaa->common.rdclass == rdclass);
    157 
    158 	UNUSED(type);
    159 	UNUSED(rdclass);
    160 
    161 	return mem_tobuffer(target, aaaa->in6_addr.s6_addr, 16);
    162 }
    163 
    164 static isc_result_t
    165 tostruct_in_aaaa(ARGS_TOSTRUCT) {
    166 	dns_rdata_in_aaaa_t *aaaa = target;
    167 	isc_region_t r;
    168 
    169 	REQUIRE(rdata->type == dns_rdatatype_aaaa);
    170 	REQUIRE(rdata->rdclass == dns_rdataclass_in);
    171 	REQUIRE(aaaa != NULL);
    172 	REQUIRE(rdata->length == 16);
    173 
    174 	UNUSED(mctx);
    175 
    176 	DNS_RDATACOMMON_INIT(aaaa, rdata->type, rdata->rdclass);
    177 
    178 	dns_rdata_toregion(rdata, &r);
    179 	INSIST(r.length == 16);
    180 	memmove(aaaa->in6_addr.s6_addr, r.base, 16);
    181 
    182 	return ISC_R_SUCCESS;
    183 }
    184 
    185 static void
    186 freestruct_in_aaaa(ARGS_FREESTRUCT) {
    187 	dns_rdata_in_aaaa_t *aaaa = source;
    188 
    189 	REQUIRE(aaaa != NULL);
    190 	REQUIRE(aaaa->common.rdclass == dns_rdataclass_in);
    191 	REQUIRE(aaaa->common.rdtype == dns_rdatatype_aaaa);
    192 
    193 	UNUSED(aaaa);
    194 }
    195 
    196 static isc_result_t
    197 additionaldata_in_aaaa(ARGS_ADDLDATA) {
    198 	REQUIRE(rdata->type == dns_rdatatype_aaaa);
    199 	REQUIRE(rdata->rdclass == dns_rdataclass_in);
    200 
    201 	UNUSED(rdata);
    202 	UNUSED(owner);
    203 	UNUSED(add);
    204 	UNUSED(arg);
    205 
    206 	return ISC_R_SUCCESS;
    207 }
    208 
    209 static isc_result_t
    210 digest_in_aaaa(ARGS_DIGEST) {
    211 	isc_region_t r;
    212 
    213 	REQUIRE(rdata->type == dns_rdatatype_aaaa);
    214 	REQUIRE(rdata->rdclass == dns_rdataclass_in);
    215 
    216 	dns_rdata_toregion(rdata, &r);
    217 
    218 	return (digest)(arg, &r);
    219 }
    220 
    221 static bool
    222 checkowner_in_aaaa(ARGS_CHECKOWNER) {
    223 	dns_name_t prefix, suffix;
    224 
    225 	REQUIRE(type == dns_rdatatype_aaaa);
    226 	REQUIRE(rdclass == dns_rdataclass_in);
    227 
    228 	UNUSED(type);
    229 	UNUSED(rdclass);
    230 
    231 	/*
    232 	 * Handle Active Directory gc._msdcs.<forest> name.
    233 	 */
    234 	if (dns_name_countlabels(name) > 2U) {
    235 		dns_name_init(&prefix, NULL);
    236 		dns_name_init(&suffix, NULL);
    237 		dns_name_split(name, dns_name_countlabels(name) - 2, &prefix,
    238 			       &suffix);
    239 		if (dns_name_equal(&gc_msdcs, &prefix) &&
    240 		    dns_name_ishostname(&suffix, false))
    241 		{
    242 			return true;
    243 		}
    244 	}
    245 
    246 	return dns_name_ishostname(name, wildcard);
    247 }
    248 
    249 static bool
    250 checknames_in_aaaa(ARGS_CHECKNAMES) {
    251 	REQUIRE(rdata->type == dns_rdatatype_aaaa);
    252 	REQUIRE(rdata->rdclass == dns_rdataclass_in);
    253 
    254 	UNUSED(rdata);
    255 	UNUSED(owner);
    256 	UNUSED(bad);
    257 
    258 	return true;
    259 }
    260 
    261 static int
    262 casecompare_in_aaaa(ARGS_COMPARE) {
    263 	return compare_in_aaaa(rdata1, rdata2);
    264 }
    265 #endif /* RDATA_IN_1_AAAA_28_C */
    266