1/* $NetBSD: a_1.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#ifndef RDATA_IN_1_A_1_C 17#define RDATA_IN_1_A_1_C 18 19#include <string.h> 20 21#include <isc/net.h> 22 23#define RRTYPE_A_ATTRIBUTES (0) 24 25static isc_result_t 26fromtext_in_a(ARGS_FROMTEXT) { 27 isc_token_t token; 28 struct in_addr addr; 29 isc_region_t region; 30 31 REQUIRE(type == dns_rdatatype_a); 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_INET, DNS_AS_STR(token), &addr) != 1) { 44 RETTOK(DNS_R_BADDOTTEDQUAD); 45 } 46 isc_buffer_availableregion(target, ®ion); 47 if (region.length < 4) { 48 return (ISC_R_NOSPACE); 49 } 50 memmove(region.base, &addr, 4); 51 isc_buffer_add(target, 4); 52 return (ISC_R_SUCCESS); 53} 54 55static isc_result_t 56totext_in_a(ARGS_TOTEXT) { 57 isc_region_t region; 58 59 REQUIRE(rdata->type == dns_rdatatype_a); 60 REQUIRE(rdata->rdclass == dns_rdataclass_in); 61 REQUIRE(rdata->length == 4); 62 63 UNUSED(tctx); 64 65 dns_rdata_toregion(rdata, ®ion); 66 return (inet_totext(AF_INET, tctx->flags, ®ion, target)); 67} 68 69static isc_result_t 70fromwire_in_a(ARGS_FROMWIRE) { 71 isc_region_t sregion; 72 isc_region_t tregion; 73 74 REQUIRE(type == dns_rdatatype_a); 75 REQUIRE(rdclass == dns_rdataclass_in); 76 77 UNUSED(type); 78 UNUSED(dctx); 79 UNUSED(options); 80 UNUSED(rdclass); 81 82 isc_buffer_activeregion(source, &sregion); 83 isc_buffer_availableregion(target, &tregion); 84 if (sregion.length < 4) { 85 return (ISC_R_UNEXPECTEDEND); 86 } 87 if (tregion.length < 4) { 88 return (ISC_R_NOSPACE); 89 } 90 91 memmove(tregion.base, sregion.base, 4); 92 isc_buffer_forward(source, 4); 93 isc_buffer_add(target, 4); 94 return (ISC_R_SUCCESS); 95} 96 97static isc_result_t 98towire_in_a(ARGS_TOWIRE) { 99 isc_region_t region; 100 101 REQUIRE(rdata->type == dns_rdatatype_a); 102 REQUIRE(rdata->rdclass == dns_rdataclass_in); 103 REQUIRE(rdata->length == 4); 104 105 UNUSED(cctx); 106 107 isc_buffer_availableregion(target, ®ion); 108 if (region.length < rdata->length) { 109 return (ISC_R_NOSPACE); 110 } 111 memmove(region.base, rdata->data, rdata->length); 112 isc_buffer_add(target, 4); 113 return (ISC_R_SUCCESS); 114} 115 116static int 117compare_in_a(ARGS_COMPARE) { 118 isc_region_t r1; 119 isc_region_t r2; 120 121 REQUIRE(rdata1->type == rdata2->type); 122 REQUIRE(rdata1->rdclass == rdata2->rdclass); 123 REQUIRE(rdata1->type == dns_rdatatype_a); 124 REQUIRE(rdata1->rdclass == dns_rdataclass_in); 125 REQUIRE(rdata1->length == 4); 126 REQUIRE(rdata2->length == 4); 127 128 dns_rdata_toregion(rdata1, &r1); 129 dns_rdata_toregion(rdata2, &r2); 130 return (isc_region_compare(&r1, &r2)); 131} 132 133static isc_result_t 134fromstruct_in_a(ARGS_FROMSTRUCT) { 135 dns_rdata_in_a_t *a = source; 136 uint32_t n; 137 138 REQUIRE(type == dns_rdatatype_a); 139 REQUIRE(rdclass == dns_rdataclass_in); 140 REQUIRE(a != NULL); 141 REQUIRE(a->common.rdtype == type); 142 REQUIRE(a->common.rdclass == rdclass); 143 144 UNUSED(type); 145 UNUSED(rdclass); 146 147 n = ntohl(a->in_addr.s_addr); 148 149 return (uint32_tobuffer(n, target)); 150} 151 152static isc_result_t 153tostruct_in_a(ARGS_TOSTRUCT) { 154 dns_rdata_in_a_t *a = target; 155 uint32_t n; 156 isc_region_t region; 157 158 REQUIRE(a != NULL); 159 REQUIRE(rdata->type == dns_rdatatype_a); 160 REQUIRE(rdata->rdclass == dns_rdataclass_in); 161 REQUIRE(rdata->length == 4); 162 163 UNUSED(mctx); 164 165 a->common.rdclass = rdata->rdclass; 166 a->common.rdtype = rdata->type; 167 ISC_LINK_INIT(&a->common, link); 168 169 dns_rdata_toregion(rdata, ®ion); 170 n = uint32_fromregion(®ion); 171 a->in_addr.s_addr = htonl(n); 172 173 return (ISC_R_SUCCESS); 174} 175 176static void 177freestruct_in_a(ARGS_FREESTRUCT) { 178 dns_rdata_in_a_t *a = source; 179 180 REQUIRE(a != NULL); 181 REQUIRE(a->common.rdtype == dns_rdatatype_a); 182 REQUIRE(a->common.rdclass == dns_rdataclass_in); 183 184 UNUSED(a); 185} 186 187static isc_result_t 188additionaldata_in_a(ARGS_ADDLDATA) { 189 REQUIRE(rdata->type == dns_rdatatype_a); 190 REQUIRE(rdata->rdclass == dns_rdataclass_in); 191 192 UNUSED(rdata); 193 UNUSED(add); 194 UNUSED(arg); 195 196 return (ISC_R_SUCCESS); 197} 198 199static isc_result_t 200digest_in_a(ARGS_DIGEST) { 201 isc_region_t r; 202 203 REQUIRE(rdata->type == dns_rdatatype_a); 204 REQUIRE(rdata->rdclass == dns_rdataclass_in); 205 206 dns_rdata_toregion(rdata, &r); 207 208 return ((digest)(arg, &r)); 209} 210 211static bool 212checkowner_in_a(ARGS_CHECKOWNER) { 213 dns_name_t prefix, suffix; 214 unsigned int labels, i; 215 216 REQUIRE(type == dns_rdatatype_a); 217 REQUIRE(rdclass == dns_rdataclass_in); 218 219 UNUSED(type); 220 UNUSED(rdclass); 221 222 labels = dns_name_countlabels(name); 223 if (labels > 2U) { 224 /* 225 * Handle Active Directory gc._msdcs.<forest> name. 226 */ 227 dns_name_init(&prefix, NULL); 228 dns_name_init(&suffix, NULL); 229 dns_name_split(name, labels - 2, &prefix, &suffix); 230 if (dns_name_equal(&gc_msdcs, &prefix) && 231 dns_name_ishostname(&suffix, false)) 232 { 233 return (true); 234 } 235 236 /* 237 * Handle SPF exists targets when the seperating label is: 238 * - "_spf" RFC7208, section 5.7 239 * - "_spf_verify" RFC7208, Appendix D1 240 * - "_spf_rate" RFC7208, Appendix D1 241 */ 242 for (i = 0; i < labels - 2; i++) { 243 dns_label_t label; 244 dns_name_getlabel(name, i, &label); 245 if ((label.length == 5 && 246 strncasecmp((char *)label.base, "\x04_spf", 5) == 247 0) || 248 (label.length == 12 && 249 strncasecmp((char *)label.base, "\x0b_spf_verify", 250 12) == 0) || 251 (label.length == 10 && 252 strncasecmp((char *)label.base, "\x09_spf_rate", 253 10) == 0)) 254 { 255 return (true); 256 } 257 } 258 } 259 260 return (dns_name_ishostname(name, wildcard)); 261} 262 263static bool 264checknames_in_a(ARGS_CHECKNAMES) { 265 REQUIRE(rdata->type == dns_rdatatype_a); 266 REQUIRE(rdata->rdclass == dns_rdataclass_in); 267 268 UNUSED(rdata); 269 UNUSED(owner); 270 UNUSED(bad); 271 272 return (true); 273} 274 275static int 276casecompare_in_a(ARGS_COMPARE) { 277 return (compare_in_a(rdata1, rdata2)); 278} 279 280#endif /* RDATA_IN_1_A_1_C */ 281