1 /* $NetBSD: txt_16.c,v 1.12 2026/01/29 18:37:53 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_GENERIC_TXT_16_C 17 #define RDATA_GENERIC_TXT_16_C 18 19 #define RRTYPE_TXT_ATTRIBUTES (0) 20 21 static isc_result_t 22 generic_fromtext_txt(ARGS_FROMTEXT) { 23 isc_token_t token; 24 int strings; 25 26 UNUSED(type); 27 UNUSED(rdclass); 28 UNUSED(origin); 29 UNUSED(options); 30 UNUSED(callbacks); 31 32 strings = 0; 33 if ((options & DNS_RDATA_UNKNOWNESCAPE) != 0) { 34 isc_textregion_t r; 35 r.base = UNCONST("#"); 36 r.length = 1; 37 RETERR(txt_fromtext(&r, target)); 38 strings++; 39 } 40 for (;;) { 41 RETERR(isc_lex_getmastertoken(lexer, &token, 42 isc_tokentype_qstring, true)); 43 if (token.type != isc_tokentype_qstring && 44 token.type != isc_tokentype_string) 45 { 46 break; 47 } 48 RETTOK(txt_fromtext(&token.value.as_textregion, target)); 49 strings++; 50 } 51 /* Let upper layer handle eol/eof. */ 52 isc_lex_ungettoken(lexer, &token); 53 return strings == 0 ? ISC_R_UNEXPECTEDEND : ISC_R_SUCCESS; 54 } 55 56 static isc_result_t 57 generic_totext_txt(ARGS_TOTEXT) { 58 isc_region_t region; 59 60 UNUSED(tctx); 61 62 dns_rdata_toregion(rdata, ®ion); 63 64 while (region.length > 0) { 65 RETERR(txt_totext(®ion, true, target)); 66 if (region.length > 0) { 67 RETERR(str_totext(" ", target)); 68 } 69 } 70 71 return ISC_R_SUCCESS; 72 } 73 74 static isc_result_t 75 generic_fromwire_txt(ARGS_FROMWIRE) { 76 isc_result_t result; 77 78 UNUSED(type); 79 UNUSED(dctx); 80 UNUSED(rdclass); 81 82 do { 83 result = txt_fromwire(source, target); 84 if (result != ISC_R_SUCCESS) { 85 return result; 86 } 87 } while (!buffer_empty(source)); 88 return ISC_R_SUCCESS; 89 } 90 91 static isc_result_t 92 fromtext_txt(ARGS_FROMTEXT) { 93 REQUIRE(type == dns_rdatatype_txt); 94 95 return generic_fromtext_txt(CALL_FROMTEXT); 96 } 97 98 static isc_result_t 99 totext_txt(ARGS_TOTEXT) { 100 REQUIRE(rdata != NULL); 101 REQUIRE(rdata->type == dns_rdatatype_txt); 102 103 return generic_totext_txt(CALL_TOTEXT); 104 } 105 106 static isc_result_t 107 fromwire_txt(ARGS_FROMWIRE) { 108 REQUIRE(type == dns_rdatatype_txt); 109 110 return generic_fromwire_txt(CALL_FROMWIRE); 111 } 112 113 static isc_result_t 114 towire_txt(ARGS_TOWIRE) { 115 REQUIRE(rdata->type == dns_rdatatype_txt); 116 117 UNUSED(cctx); 118 119 return mem_tobuffer(target, rdata->data, rdata->length); 120 } 121 122 static int 123 compare_txt(ARGS_COMPARE) { 124 isc_region_t r1; 125 isc_region_t r2; 126 127 REQUIRE(rdata1->type == rdata2->type); 128 REQUIRE(rdata1->rdclass == rdata2->rdclass); 129 REQUIRE(rdata1->type == dns_rdatatype_txt); 130 131 dns_rdata_toregion(rdata1, &r1); 132 dns_rdata_toregion(rdata2, &r2); 133 return isc_region_compare(&r1, &r2); 134 } 135 136 static isc_result_t 137 generic_fromstruct_txt(ARGS_FROMSTRUCT) { 138 dns_rdata_txt_t *txt = source; 139 isc_region_t region; 140 uint8_t length; 141 142 REQUIRE(txt != NULL); 143 REQUIRE(txt->common.rdtype == type); 144 REQUIRE(txt->common.rdclass == rdclass); 145 REQUIRE(txt->txt != NULL && txt->txt_len != 0); 146 147 UNUSED(type); 148 UNUSED(rdclass); 149 150 region.base = txt->txt; 151 region.length = txt->txt_len; 152 while (region.length > 0) { 153 length = uint8_fromregion(®ion); 154 isc_region_consume(®ion, 1); 155 if (region.length < length) { 156 return ISC_R_UNEXPECTEDEND; 157 } 158 isc_region_consume(®ion, length); 159 } 160 161 return mem_tobuffer(target, txt->txt, txt->txt_len); 162 } 163 164 static isc_result_t 165 generic_tostruct_txt(ARGS_TOSTRUCT) { 166 dns_rdata_txt_t *txt = target; 167 isc_region_t r; 168 169 REQUIRE(txt != NULL); 170 REQUIRE(txt->common.rdclass == rdata->rdclass); 171 REQUIRE(txt->common.rdtype == rdata->type); 172 REQUIRE(!ISC_LINK_LINKED(&txt->common, link)); 173 174 dns_rdata_toregion(rdata, &r); 175 txt->txt_len = r.length; 176 txt->txt = mem_maybedup(mctx, r.base, r.length); 177 txt->offset = 0; 178 txt->mctx = mctx; 179 return ISC_R_SUCCESS; 180 } 181 182 static void 183 generic_freestruct_txt(ARGS_FREESTRUCT) { 184 dns_rdata_txt_t *txt = source; 185 186 REQUIRE(txt != NULL); 187 188 if (txt->mctx == NULL) { 189 return; 190 } 191 192 if (txt->txt != NULL) { 193 isc_mem_free(txt->mctx, txt->txt); 194 } 195 txt->mctx = NULL; 196 } 197 198 static isc_result_t 199 fromstruct_txt(ARGS_FROMSTRUCT) { 200 REQUIRE(type == dns_rdatatype_txt); 201 202 return generic_fromstruct_txt(CALL_FROMSTRUCT); 203 } 204 205 static isc_result_t 206 tostruct_txt(ARGS_TOSTRUCT) { 207 dns_rdata_txt_t *txt = target; 208 209 REQUIRE(rdata->type == dns_rdatatype_txt); 210 REQUIRE(txt != NULL); 211 212 DNS_RDATACOMMON_INIT(txt, rdata->type, rdata->rdclass); 213 214 return generic_tostruct_txt(CALL_TOSTRUCT); 215 } 216 217 static void 218 freestruct_txt(ARGS_FREESTRUCT) { 219 dns_rdata_txt_t *txt = source; 220 221 REQUIRE(txt != NULL); 222 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 223 224 generic_freestruct_txt(source); 225 } 226 227 static isc_result_t 228 additionaldata_txt(ARGS_ADDLDATA) { 229 REQUIRE(rdata->type == dns_rdatatype_txt); 230 231 UNUSED(rdata); 232 UNUSED(owner); 233 UNUSED(add); 234 UNUSED(arg); 235 236 return ISC_R_SUCCESS; 237 } 238 239 static isc_result_t 240 digest_txt(ARGS_DIGEST) { 241 isc_region_t r; 242 243 REQUIRE(rdata->type == dns_rdatatype_txt); 244 245 dns_rdata_toregion(rdata, &r); 246 247 return (digest)(arg, &r); 248 } 249 250 static bool 251 checkowner_txt(ARGS_CHECKOWNER) { 252 REQUIRE(type == dns_rdatatype_txt); 253 254 UNUSED(name); 255 UNUSED(type); 256 UNUSED(rdclass); 257 UNUSED(wildcard); 258 259 return true; 260 } 261 262 static bool 263 checknames_txt(ARGS_CHECKNAMES) { 264 REQUIRE(rdata->type == dns_rdatatype_txt); 265 266 UNUSED(rdata); 267 UNUSED(owner); 268 UNUSED(bad); 269 270 return true; 271 } 272 273 static int 274 casecompare_txt(ARGS_COMPARE) { 275 return compare_txt(rdata1, rdata2); 276 } 277 278 static isc_result_t 279 generic_txt_first(dns_rdata_txt_t *txt) { 280 REQUIRE(txt != NULL); 281 REQUIRE(txt->txt != NULL || txt->txt_len == 0); 282 283 if (txt->txt_len == 0) { 284 return ISC_R_NOMORE; 285 } 286 287 txt->offset = 0; 288 return ISC_R_SUCCESS; 289 } 290 291 static isc_result_t 292 generic_txt_next(dns_rdata_txt_t *txt) { 293 isc_region_t r; 294 uint8_t length; 295 296 REQUIRE(txt != NULL); 297 REQUIRE(txt->txt != NULL && txt->txt_len != 0); 298 299 INSIST(txt->offset + 1 <= txt->txt_len); 300 r.base = txt->txt + txt->offset; 301 r.length = txt->txt_len - txt->offset; 302 length = uint8_fromregion(&r); 303 INSIST(txt->offset + 1 + length <= txt->txt_len); 304 txt->offset = txt->offset + 1 + length; 305 if (txt->offset == txt->txt_len) { 306 return ISC_R_NOMORE; 307 } 308 return ISC_R_SUCCESS; 309 } 310 311 static isc_result_t 312 generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { 313 isc_region_t r; 314 315 REQUIRE(txt != NULL); 316 REQUIRE(string != NULL); 317 REQUIRE(txt->txt != NULL); 318 REQUIRE(txt->offset < txt->txt_len); 319 320 INSIST(txt->offset + 1 <= txt->txt_len); 321 r.base = txt->txt + txt->offset; 322 r.length = txt->txt_len - txt->offset; 323 324 string->length = uint8_fromregion(&r); 325 isc_region_consume(&r, 1); 326 string->data = r.base; 327 INSIST(txt->offset + 1 + string->length <= txt->txt_len); 328 329 return ISC_R_SUCCESS; 330 } 331 332 isc_result_t 333 dns_rdata_txt_first(dns_rdata_txt_t *txt) { 334 REQUIRE(txt != NULL); 335 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 336 337 return generic_txt_first(txt); 338 } 339 340 isc_result_t 341 dns_rdata_txt_next(dns_rdata_txt_t *txt) { 342 REQUIRE(txt != NULL); 343 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 344 345 return generic_txt_next(txt); 346 } 347 348 isc_result_t 349 dns_rdata_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { 350 REQUIRE(txt != NULL); 351 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 352 353 return generic_txt_current(txt, string); 354 } 355 #endif /* RDATA_GENERIC_TXT_16_C */ 356