1 /* $NetBSD: a_1.c,v 1.9 2025/01/26 16:25:30 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 /* by Bjorn.Victor@it.uu.se, 2005-05-07 */ 17 /* Based on generic/soa_6.c and generic/mx_15.c */ 18 19 #ifndef RDATA_CH_3_A_1_C 20 #define RDATA_CH_3_A_1_C 21 22 #include <isc/net.h> 23 24 #define RRTYPE_A_ATTRIBUTES (0) 25 26 static isc_result_t 27 fromtext_ch_a(ARGS_FROMTEXT) { 28 isc_token_t token; 29 dns_name_t name; 30 isc_buffer_t buffer; 31 32 REQUIRE(type == dns_rdatatype_a); 33 REQUIRE(rdclass == dns_rdataclass_ch); /* 3 */ 34 35 UNUSED(type); 36 UNUSED(callbacks); 37 38 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 39 false)); 40 41 /* get domain name */ 42 dns_name_init(&name, NULL); 43 buffer_fromregion(&buffer, &token.value.as_region); 44 if (origin == NULL) { 45 origin = dns_rootname; 46 } 47 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 48 if ((options & DNS_RDATA_CHECKNAMES) != 0 && 49 (options & DNS_RDATA_CHECKREVERSE) != 0) 50 { 51 bool ok; 52 ok = dns_name_ishostname(&name, false); 53 if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) { 54 RETTOK(DNS_R_BADNAME); 55 } 56 if (!ok && callbacks != NULL) { 57 warn_badname(&name, lexer, callbacks); 58 } 59 } 60 61 /* 16-bit octal address */ 62 RETERR(isc_lex_getoctaltoken(lexer, &token, false)); 63 if (token.value.as_ulong > 0xffffU) { 64 RETTOK(ISC_R_RANGE); 65 } 66 return uint16_tobuffer(token.value.as_ulong, target); 67 } 68 69 static isc_result_t 70 totext_ch_a(ARGS_TOTEXT) { 71 isc_region_t region; 72 dns_name_t name; 73 dns_name_t prefix; 74 unsigned int opts; 75 char buf[sizeof("0177777")]; 76 uint16_t addr; 77 78 REQUIRE(rdata->type == dns_rdatatype_a); 79 REQUIRE(rdata->rdclass == dns_rdataclass_ch); /* 3 */ 80 REQUIRE(rdata->length != 0); 81 82 dns_name_init(&name, NULL); 83 dns_name_init(&prefix, NULL); 84 85 dns_rdata_toregion(rdata, ®ion); 86 dns_name_fromregion(&name, ®ion); 87 isc_region_consume(®ion, name_length(&name)); 88 addr = uint16_fromregion(®ion); 89 90 opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT 91 : 0; 92 RETERR(dns_name_totext(&prefix, opts, target)); 93 94 snprintf(buf, sizeof(buf), "%o", addr); /* note octal */ 95 RETERR(str_totext(" ", target)); 96 return str_totext(buf, target); 97 } 98 99 static isc_result_t 100 fromwire_ch_a(ARGS_FROMWIRE) { 101 isc_region_t sregion; 102 isc_region_t tregion; 103 dns_name_t name; 104 105 REQUIRE(type == dns_rdatatype_a); 106 REQUIRE(rdclass == dns_rdataclass_ch); 107 108 UNUSED(type); 109 UNUSED(rdclass); 110 111 dctx = dns_decompress_setpermitted(dctx, true); 112 113 dns_name_init(&name, NULL); 114 115 RETERR(dns_name_fromwire(&name, source, dctx, target)); 116 117 isc_buffer_activeregion(source, &sregion); 118 isc_buffer_availableregion(target, &tregion); 119 if (sregion.length < 2) { 120 return ISC_R_UNEXPECTEDEND; 121 } 122 if (tregion.length < 2) { 123 return ISC_R_NOSPACE; 124 } 125 126 memmove(tregion.base, sregion.base, 2); 127 isc_buffer_forward(source, 2); 128 isc_buffer_add(target, 2); 129 130 return ISC_R_SUCCESS; 131 } 132 133 static isc_result_t 134 towire_ch_a(ARGS_TOWIRE) { 135 dns_name_t name; 136 dns_offsets_t offsets; 137 isc_region_t sregion; 138 isc_region_t tregion; 139 140 REQUIRE(rdata->type == dns_rdatatype_a); 141 REQUIRE(rdata->rdclass == dns_rdataclass_ch); 142 REQUIRE(rdata->length != 0); 143 144 dns_compress_setpermitted(cctx, true); 145 146 dns_name_init(&name, offsets); 147 148 dns_rdata_toregion(rdata, &sregion); 149 150 dns_name_fromregion(&name, &sregion); 151 isc_region_consume(&sregion, name_length(&name)); 152 RETERR(dns_name_towire(&name, cctx, target, NULL)); 153 154 isc_buffer_availableregion(target, &tregion); 155 if (tregion.length < 2) { 156 return ISC_R_NOSPACE; 157 } 158 159 memmove(tregion.base, sregion.base, 2); 160 isc_buffer_add(target, 2); 161 return ISC_R_SUCCESS; 162 } 163 164 static int 165 compare_ch_a(ARGS_COMPARE) { 166 dns_name_t name1; 167 dns_name_t name2; 168 isc_region_t region1; 169 isc_region_t region2; 170 int order; 171 172 REQUIRE(rdata1->type == rdata2->type); 173 REQUIRE(rdata1->rdclass == rdata2->rdclass); 174 REQUIRE(rdata1->type == dns_rdatatype_a); 175 REQUIRE(rdata1->rdclass == dns_rdataclass_ch); 176 REQUIRE(rdata1->length != 0); 177 REQUIRE(rdata2->length != 0); 178 179 dns_name_init(&name1, NULL); 180 dns_name_init(&name2, NULL); 181 182 dns_rdata_toregion(rdata1, ®ion1); 183 dns_rdata_toregion(rdata2, ®ion2); 184 185 dns_name_fromregion(&name1, ®ion1); 186 dns_name_fromregion(&name2, ®ion2); 187 isc_region_consume(®ion1, name_length(&name1)); 188 isc_region_consume(®ion2, name_length(&name2)); 189 190 order = dns_name_rdatacompare(&name1, &name2); 191 if (order != 0) { 192 return order; 193 } 194 195 order = memcmp(region1.base, region2.base, 2); 196 if (order != 0) { 197 order = (order < 0) ? -1 : 1; 198 } 199 return order; 200 } 201 202 static isc_result_t 203 fromstruct_ch_a(ARGS_FROMSTRUCT) { 204 dns_rdata_ch_a_t *a = source; 205 isc_region_t region; 206 207 REQUIRE(type == dns_rdatatype_a); 208 REQUIRE(a != NULL); 209 REQUIRE(a->common.rdtype == type); 210 REQUIRE(a->common.rdclass == rdclass); 211 212 UNUSED(type); 213 UNUSED(rdclass); 214 215 dns_name_toregion(&a->ch_addr_dom, ®ion); 216 RETERR(isc_buffer_copyregion(target, ®ion)); 217 218 return uint16_tobuffer(ntohs(a->ch_addr), target); 219 } 220 221 static isc_result_t 222 tostruct_ch_a(ARGS_TOSTRUCT) { 223 dns_rdata_ch_a_t *a = target; 224 isc_region_t region; 225 dns_name_t name; 226 227 REQUIRE(rdata->type == dns_rdatatype_a); 228 REQUIRE(rdata->rdclass == dns_rdataclass_ch); 229 REQUIRE(rdata->length != 0); 230 231 a->common.rdclass = rdata->rdclass; 232 a->common.rdtype = rdata->type; 233 ISC_LINK_INIT(&a->common, link); 234 235 dns_rdata_toregion(rdata, ®ion); 236 237 dns_name_init(&name, NULL); 238 dns_name_fromregion(&name, ®ion); 239 isc_region_consume(®ion, name_length(&name)); 240 241 dns_name_init(&a->ch_addr_dom, NULL); 242 name_duporclone(&name, mctx, &a->ch_addr_dom); 243 a->ch_addr = htons(uint16_fromregion(®ion)); 244 a->mctx = mctx; 245 return ISC_R_SUCCESS; 246 } 247 248 static void 249 freestruct_ch_a(ARGS_FREESTRUCT) { 250 dns_rdata_ch_a_t *a = source; 251 252 REQUIRE(a != NULL); 253 REQUIRE(a->common.rdtype == dns_rdatatype_a); 254 255 if (a->mctx == NULL) { 256 return; 257 } 258 259 dns_name_free(&a->ch_addr_dom, a->mctx); 260 a->mctx = NULL; 261 } 262 263 static isc_result_t 264 additionaldata_ch_a(ARGS_ADDLDATA) { 265 REQUIRE(rdata->type == dns_rdatatype_a); 266 REQUIRE(rdata->rdclass == dns_rdataclass_ch); 267 268 UNUSED(rdata); 269 UNUSED(owner); 270 UNUSED(add); 271 UNUSED(arg); 272 273 return ISC_R_SUCCESS; 274 } 275 276 static isc_result_t 277 digest_ch_a(ARGS_DIGEST) { 278 isc_region_t r; 279 dns_name_t name; 280 281 REQUIRE(rdata->type == dns_rdatatype_a); 282 REQUIRE(rdata->rdclass == dns_rdataclass_ch); 283 284 dns_rdata_toregion(rdata, &r); 285 dns_name_init(&name, NULL); 286 dns_name_fromregion(&name, &r); 287 isc_region_consume(&r, name_length(&name)); 288 RETERR(dns_name_digest(&name, digest, arg)); 289 return (digest)(arg, &r); 290 } 291 292 static bool 293 checkowner_ch_a(ARGS_CHECKOWNER) { 294 REQUIRE(type == dns_rdatatype_a); 295 REQUIRE(rdclass == dns_rdataclass_ch); 296 297 UNUSED(type); 298 299 return dns_name_ishostname(name, wildcard); 300 } 301 302 static bool 303 checknames_ch_a(ARGS_CHECKNAMES) { 304 isc_region_t region; 305 dns_name_t name; 306 307 REQUIRE(rdata->type == dns_rdatatype_a); 308 REQUIRE(rdata->rdclass == dns_rdataclass_ch); 309 310 UNUSED(owner); 311 312 dns_rdata_toregion(rdata, ®ion); 313 dns_name_init(&name, NULL); 314 dns_name_fromregion(&name, ®ion); 315 if (!dns_name_ishostname(&name, false)) { 316 if (bad != NULL) { 317 dns_name_clone(&name, bad); 318 } 319 return false; 320 } 321 322 return true; 323 } 324 325 static int 326 casecompare_ch_a(ARGS_COMPARE) { 327 return compare_ch_a(rdata1, rdata2); 328 } 329 #endif /* RDATA_CH_3_A_1_C */ 330