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, ®ion); 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, ®ion); 82 return inet_totext(AF_INET6, tctx->flags, ®ion, 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, ®ion); 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