1 /* $NetBSD: tlsa_52.c,v 1.11 2025/01/26 16:25:33 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 /* rfc6698.txt */ 17 18 #ifndef RDATA_GENERIC_TLSA_52_C 19 #define RDATA_GENERIC_TLSA_52_C 20 21 #define RRTYPE_TLSA_ATTRIBUTES 0 22 23 static isc_result_t 24 generic_fromtext_tlsa(ARGS_FROMTEXT) { 25 isc_token_t token; 26 27 UNUSED(type); 28 UNUSED(rdclass); 29 UNUSED(origin); 30 UNUSED(options); 31 UNUSED(callbacks); 32 33 /* 34 * Certificate Usage. 35 */ 36 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 37 false)); 38 if (token.value.as_ulong > 0xffU) { 39 RETTOK(ISC_R_RANGE); 40 } 41 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 42 43 /* 44 * Selector. 45 */ 46 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 47 false)); 48 if (token.value.as_ulong > 0xffU) { 49 RETTOK(ISC_R_RANGE); 50 } 51 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 52 53 /* 54 * Matching type. 55 */ 56 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 57 false)); 58 if (token.value.as_ulong > 0xffU) { 59 RETTOK(ISC_R_RANGE); 60 } 61 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 62 63 /* 64 * Certificate Association Data. 65 */ 66 return isc_hex_tobuffer(lexer, target, -2); 67 } 68 69 static isc_result_t 70 generic_totext_tlsa(ARGS_TOTEXT) { 71 isc_region_t sr; 72 char buf[sizeof("64000 ")]; 73 unsigned int n; 74 75 REQUIRE(rdata->length != 0); 76 77 UNUSED(tctx); 78 79 dns_rdata_toregion(rdata, &sr); 80 81 /* 82 * Certificate Usage. 83 */ 84 n = uint8_fromregion(&sr); 85 isc_region_consume(&sr, 1); 86 snprintf(buf, sizeof(buf), "%u ", n); 87 RETERR(str_totext(buf, target)); 88 89 /* 90 * Selector. 91 */ 92 n = uint8_fromregion(&sr); 93 isc_region_consume(&sr, 1); 94 snprintf(buf, sizeof(buf), "%u ", n); 95 RETERR(str_totext(buf, target)); 96 97 /* 98 * Matching type. 99 */ 100 n = uint8_fromregion(&sr); 101 isc_region_consume(&sr, 1); 102 snprintf(buf, sizeof(buf), "%u", n); 103 RETERR(str_totext(buf, target)); 104 105 /* 106 * Certificate Association Data. 107 */ 108 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 109 RETERR(str_totext(" (", target)); 110 } 111 RETERR(str_totext(tctx->linebreak, target)); 112 if (tctx->width == 0) { /* No splitting */ 113 RETERR(isc_hex_totext(&sr, 0, "", target)); 114 } else { 115 RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, 116 target)); 117 } 118 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 119 RETERR(str_totext(" )", target)); 120 } 121 return ISC_R_SUCCESS; 122 } 123 124 static isc_result_t 125 generic_fromwire_tlsa(ARGS_FROMWIRE) { 126 isc_region_t sr; 127 128 UNUSED(type); 129 UNUSED(rdclass); 130 UNUSED(dctx); 131 132 isc_buffer_activeregion(source, &sr); 133 134 /* Usage(1), Selector(1), Type(1), Data(1+) */ 135 if (sr.length < 4) { 136 return ISC_R_UNEXPECTEDEND; 137 } 138 139 isc_buffer_forward(source, sr.length); 140 return mem_tobuffer(target, sr.base, sr.length); 141 } 142 143 static isc_result_t 144 fromtext_tlsa(ARGS_FROMTEXT) { 145 REQUIRE(type == dns_rdatatype_tlsa); 146 147 return generic_fromtext_tlsa(CALL_FROMTEXT); 148 } 149 150 static isc_result_t 151 totext_tlsa(ARGS_TOTEXT) { 152 REQUIRE(rdata->type == dns_rdatatype_tlsa); 153 154 return generic_totext_tlsa(CALL_TOTEXT); 155 } 156 157 static isc_result_t 158 fromwire_tlsa(ARGS_FROMWIRE) { 159 REQUIRE(type == dns_rdatatype_tlsa); 160 161 return generic_fromwire_tlsa(CALL_FROMWIRE); 162 } 163 164 static isc_result_t 165 towire_tlsa(ARGS_TOWIRE) { 166 isc_region_t sr; 167 168 REQUIRE(rdata->type == dns_rdatatype_tlsa); 169 REQUIRE(rdata->length != 0); 170 171 UNUSED(cctx); 172 173 dns_rdata_toregion(rdata, &sr); 174 return mem_tobuffer(target, sr.base, sr.length); 175 } 176 177 static int 178 compare_tlsa(ARGS_COMPARE) { 179 isc_region_t r1; 180 isc_region_t r2; 181 182 REQUIRE(rdata1->type == rdata2->type); 183 REQUIRE(rdata1->rdclass == rdata2->rdclass); 184 REQUIRE(rdata1->type == dns_rdatatype_tlsa); 185 REQUIRE(rdata1->length != 0); 186 REQUIRE(rdata2->length != 0); 187 188 dns_rdata_toregion(rdata1, &r1); 189 dns_rdata_toregion(rdata2, &r2); 190 return isc_region_compare(&r1, &r2); 191 } 192 193 static isc_result_t 194 generic_fromstruct_tlsa(ARGS_FROMSTRUCT) { 195 dns_rdata_tlsa_t *tlsa = source; 196 197 REQUIRE(tlsa != NULL); 198 REQUIRE(tlsa->common.rdtype == type); 199 REQUIRE(tlsa->common.rdclass == rdclass); 200 201 UNUSED(type); 202 UNUSED(rdclass); 203 204 RETERR(uint8_tobuffer(tlsa->usage, target)); 205 RETERR(uint8_tobuffer(tlsa->selector, target)); 206 RETERR(uint8_tobuffer(tlsa->match, target)); 207 208 return mem_tobuffer(target, tlsa->data, tlsa->length); 209 } 210 211 static isc_result_t 212 generic_tostruct_tlsa(ARGS_TOSTRUCT) { 213 dns_rdata_tlsa_t *tlsa = target; 214 isc_region_t region; 215 216 REQUIRE(tlsa != NULL); 217 REQUIRE(rdata->length != 0); 218 219 REQUIRE(tlsa != NULL); 220 REQUIRE(tlsa->common.rdclass == rdata->rdclass); 221 REQUIRE(tlsa->common.rdtype == rdata->type); 222 REQUIRE(!ISC_LINK_LINKED(&tlsa->common, link)); 223 224 dns_rdata_toregion(rdata, ®ion); 225 226 tlsa->usage = uint8_fromregion(®ion); 227 isc_region_consume(®ion, 1); 228 tlsa->selector = uint8_fromregion(®ion); 229 isc_region_consume(®ion, 1); 230 tlsa->match = uint8_fromregion(®ion); 231 isc_region_consume(®ion, 1); 232 tlsa->length = region.length; 233 234 tlsa->data = mem_maybedup(mctx, region.base, region.length); 235 tlsa->mctx = mctx; 236 return ISC_R_SUCCESS; 237 } 238 239 static void 240 generic_freestruct_tlsa(ARGS_FREESTRUCT) { 241 dns_rdata_tlsa_t *tlsa = source; 242 243 REQUIRE(tlsa != NULL); 244 245 if (tlsa->mctx == NULL) { 246 return; 247 } 248 249 if (tlsa->data != NULL) { 250 isc_mem_free(tlsa->mctx, tlsa->data); 251 } 252 tlsa->mctx = NULL; 253 } 254 255 static isc_result_t 256 fromstruct_tlsa(ARGS_FROMSTRUCT) { 257 REQUIRE(type == dns_rdatatype_tlsa); 258 259 return generic_fromstruct_tlsa(CALL_FROMSTRUCT); 260 } 261 262 static isc_result_t 263 tostruct_tlsa(ARGS_TOSTRUCT) { 264 dns_rdata_tlsa_t *tlsa = target; 265 266 REQUIRE(rdata->type == dns_rdatatype_tlsa); 267 REQUIRE(tlsa != NULL); 268 269 tlsa->common.rdclass = rdata->rdclass; 270 tlsa->common.rdtype = rdata->type; 271 ISC_LINK_INIT(&tlsa->common, link); 272 273 return generic_tostruct_tlsa(CALL_TOSTRUCT); 274 } 275 276 static void 277 freestruct_tlsa(ARGS_FREESTRUCT) { 278 dns_rdata_tlsa_t *tlsa = source; 279 280 REQUIRE(tlsa != NULL); 281 REQUIRE(tlsa->common.rdtype == dns_rdatatype_tlsa); 282 283 generic_freestruct_tlsa(source); 284 } 285 286 static isc_result_t 287 additionaldata_tlsa(ARGS_ADDLDATA) { 288 REQUIRE(rdata->type == dns_rdatatype_tlsa); 289 290 UNUSED(rdata); 291 UNUSED(owner); 292 UNUSED(add); 293 UNUSED(arg); 294 295 return ISC_R_SUCCESS; 296 } 297 298 static isc_result_t 299 digest_tlsa(ARGS_DIGEST) { 300 isc_region_t r; 301 302 REQUIRE(rdata->type == dns_rdatatype_tlsa); 303 304 dns_rdata_toregion(rdata, &r); 305 306 return (digest)(arg, &r); 307 } 308 309 static bool 310 checkowner_tlsa(ARGS_CHECKOWNER) { 311 REQUIRE(type == dns_rdatatype_tlsa); 312 313 UNUSED(name); 314 UNUSED(type); 315 UNUSED(rdclass); 316 UNUSED(wildcard); 317 318 return true; 319 } 320 321 static bool 322 checknames_tlsa(ARGS_CHECKNAMES) { 323 REQUIRE(rdata->type == dns_rdatatype_tlsa); 324 325 UNUSED(rdata); 326 UNUSED(owner); 327 UNUSED(bad); 328 329 return true; 330 } 331 332 static int 333 casecompare_tlsa(ARGS_COMPARE) { 334 return compare_tlsa(rdata1, rdata2); 335 } 336 337 #endif /* RDATA_GENERIC_TLSA_52_C */ 338