1/* $NetBSD: aaaa_28.c,v 1.1 2024/02/18 20:57:46 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 25static isc_result_t 26fromtext_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 55static isc_result_t 56totext_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 85static isc_result_t 86fromwire_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(options); 96 UNUSED(rdclass); 97 98 isc_buffer_activeregion(source, &sregion); 99 isc_buffer_availableregion(target, &tregion); 100 if (sregion.length < 16) { 101 return (ISC_R_UNEXPECTEDEND); 102 } 103 if (tregion.length < 16) { 104 return (ISC_R_NOSPACE); 105 } 106 107 memmove(tregion.base, sregion.base, 16); 108 isc_buffer_forward(source, 16); 109 isc_buffer_add(target, 16); 110 return (ISC_R_SUCCESS); 111} 112 113static isc_result_t 114towire_in_aaaa(ARGS_TOWIRE) { 115 isc_region_t region; 116 117 UNUSED(cctx); 118 119 REQUIRE(rdata->type == dns_rdatatype_aaaa); 120 REQUIRE(rdata->rdclass == dns_rdataclass_in); 121 REQUIRE(rdata->length == 16); 122 123 isc_buffer_availableregion(target, ®ion); 124 if (region.length < rdata->length) { 125 return (ISC_R_NOSPACE); 126 } 127 memmove(region.base, rdata->data, rdata->length); 128 isc_buffer_add(target, 16); 129 return (ISC_R_SUCCESS); 130} 131 132static int 133compare_in_aaaa(ARGS_COMPARE) { 134 isc_region_t r1; 135 isc_region_t r2; 136 137 REQUIRE(rdata1->type == rdata2->type); 138 REQUIRE(rdata1->rdclass == rdata2->rdclass); 139 REQUIRE(rdata1->type == dns_rdatatype_aaaa); 140 REQUIRE(rdata1->rdclass == dns_rdataclass_in); 141 REQUIRE(rdata1->length == 16); 142 REQUIRE(rdata2->length == 16); 143 144 dns_rdata_toregion(rdata1, &r1); 145 dns_rdata_toregion(rdata2, &r2); 146 return (isc_region_compare(&r1, &r2)); 147} 148 149static isc_result_t 150fromstruct_in_aaaa(ARGS_FROMSTRUCT) { 151 dns_rdata_in_aaaa_t *aaaa = source; 152 153 REQUIRE(type == dns_rdatatype_aaaa); 154 REQUIRE(rdclass == dns_rdataclass_in); 155 REQUIRE(aaaa != NULL); 156 REQUIRE(aaaa->common.rdtype == type); 157 REQUIRE(aaaa->common.rdclass == rdclass); 158 159 UNUSED(type); 160 UNUSED(rdclass); 161 162 return (mem_tobuffer(target, aaaa->in6_addr.s6_addr, 16)); 163} 164 165static isc_result_t 166tostruct_in_aaaa(ARGS_TOSTRUCT) { 167 dns_rdata_in_aaaa_t *aaaa = target; 168 isc_region_t r; 169 170 REQUIRE(rdata->type == dns_rdatatype_aaaa); 171 REQUIRE(rdata->rdclass == dns_rdataclass_in); 172 REQUIRE(aaaa != NULL); 173 REQUIRE(rdata->length == 16); 174 175 UNUSED(mctx); 176 177 aaaa->common.rdclass = rdata->rdclass; 178 aaaa->common.rdtype = rdata->type; 179 ISC_LINK_INIT(&aaaa->common, link); 180 181 dns_rdata_toregion(rdata, &r); 182 INSIST(r.length == 16); 183 memmove(aaaa->in6_addr.s6_addr, r.base, 16); 184 185 return (ISC_R_SUCCESS); 186} 187 188static void 189freestruct_in_aaaa(ARGS_FREESTRUCT) { 190 dns_rdata_in_aaaa_t *aaaa = source; 191 192 REQUIRE(aaaa != NULL); 193 REQUIRE(aaaa->common.rdclass == dns_rdataclass_in); 194 REQUIRE(aaaa->common.rdtype == dns_rdatatype_aaaa); 195 196 UNUSED(aaaa); 197} 198 199static isc_result_t 200additionaldata_in_aaaa(ARGS_ADDLDATA) { 201 REQUIRE(rdata->type == dns_rdatatype_aaaa); 202 REQUIRE(rdata->rdclass == dns_rdataclass_in); 203 204 UNUSED(rdata); 205 UNUSED(add); 206 UNUSED(arg); 207 208 return (ISC_R_SUCCESS); 209} 210 211static isc_result_t 212digest_in_aaaa(ARGS_DIGEST) { 213 isc_region_t r; 214 215 REQUIRE(rdata->type == dns_rdatatype_aaaa); 216 REQUIRE(rdata->rdclass == dns_rdataclass_in); 217 218 dns_rdata_toregion(rdata, &r); 219 220 return ((digest)(arg, &r)); 221} 222 223static bool 224checkowner_in_aaaa(ARGS_CHECKOWNER) { 225 dns_name_t prefix, suffix; 226 227 REQUIRE(type == dns_rdatatype_aaaa); 228 REQUIRE(rdclass == dns_rdataclass_in); 229 230 UNUSED(type); 231 UNUSED(rdclass); 232 233 /* 234 * Handle Active Directory gc._msdcs.<forest> name. 235 */ 236 if (dns_name_countlabels(name) > 2U) { 237 dns_name_init(&prefix, NULL); 238 dns_name_init(&suffix, NULL); 239 dns_name_split(name, dns_name_countlabels(name) - 2, &prefix, 240 &suffix); 241 if (dns_name_equal(&gc_msdcs, &prefix) && 242 dns_name_ishostname(&suffix, false)) 243 { 244 return (true); 245 } 246 } 247 248 return (dns_name_ishostname(name, wildcard)); 249} 250 251static bool 252checknames_in_aaaa(ARGS_CHECKNAMES) { 253 REQUIRE(rdata->type == dns_rdatatype_aaaa); 254 REQUIRE(rdata->rdclass == dns_rdataclass_in); 255 256 UNUSED(rdata); 257 UNUSED(owner); 258 UNUSED(bad); 259 260 return (true); 261} 262 263static int 264casecompare_in_aaaa(ARGS_COMPARE) { 265 return (compare_in_aaaa(rdata1, rdata2)); 266} 267#endif /* RDATA_IN_1_AAAA_28_C */ 268