1 /* $NetBSD: txt_16.c,v 1.9 2023/01/25 21:43: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 #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 DE_CONST("#", r.base); 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 UNUSED(options); 82 83 do { 84 result = txt_fromwire(source, target); 85 if (result != ISC_R_SUCCESS) { 86 return (result); 87 } 88 } while (!buffer_empty(source)); 89 return (ISC_R_SUCCESS); 90 } 91 92 static isc_result_t 93 fromtext_txt(ARGS_FROMTEXT) { 94 REQUIRE(type == dns_rdatatype_txt); 95 96 return (generic_fromtext_txt(CALL_FROMTEXT)); 97 } 98 99 static isc_result_t 100 totext_txt(ARGS_TOTEXT) { 101 REQUIRE(rdata != NULL); 102 REQUIRE(rdata->type == dns_rdatatype_txt); 103 104 return (generic_totext_txt(CALL_TOTEXT)); 105 } 106 107 static isc_result_t 108 fromwire_txt(ARGS_FROMWIRE) { 109 REQUIRE(type == dns_rdatatype_txt); 110 111 return (generic_fromwire_txt(CALL_FROMWIRE)); 112 } 113 114 static isc_result_t 115 towire_txt(ARGS_TOWIRE) { 116 REQUIRE(rdata->type == dns_rdatatype_txt); 117 118 UNUSED(cctx); 119 120 return (mem_tobuffer(target, rdata->data, rdata->length)); 121 } 122 123 static int 124 compare_txt(ARGS_COMPARE) { 125 isc_region_t r1; 126 isc_region_t r2; 127 128 REQUIRE(rdata1->type == rdata2->type); 129 REQUIRE(rdata1->rdclass == rdata2->rdclass); 130 REQUIRE(rdata1->type == dns_rdatatype_txt); 131 132 dns_rdata_toregion(rdata1, &r1); 133 dns_rdata_toregion(rdata2, &r2); 134 return (isc_region_compare(&r1, &r2)); 135 } 136 137 static isc_result_t 138 generic_fromstruct_txt(ARGS_FROMSTRUCT) { 139 dns_rdata_txt_t *txt = source; 140 isc_region_t region; 141 uint8_t length; 142 143 REQUIRE(txt != NULL); 144 REQUIRE(txt->common.rdtype == type); 145 REQUIRE(txt->common.rdclass == rdclass); 146 REQUIRE(txt->txt != NULL && txt->txt_len != 0); 147 148 UNUSED(type); 149 UNUSED(rdclass); 150 151 region.base = txt->txt; 152 region.length = txt->txt_len; 153 while (region.length > 0) { 154 length = uint8_fromregion(®ion); 155 isc_region_consume(®ion, 1); 156 if (region.length < length) { 157 return (ISC_R_UNEXPECTEDEND); 158 } 159 isc_region_consume(®ion, length); 160 } 161 162 return (mem_tobuffer(target, txt->txt, txt->txt_len)); 163 } 164 165 static isc_result_t 166 generic_tostruct_txt(ARGS_TOSTRUCT) { 167 dns_rdata_txt_t *txt = target; 168 isc_region_t r; 169 170 REQUIRE(txt != NULL); 171 REQUIRE(txt->common.rdclass == rdata->rdclass); 172 REQUIRE(txt->common.rdtype == rdata->type); 173 REQUIRE(!ISC_LINK_LINKED(&txt->common, link)); 174 175 dns_rdata_toregion(rdata, &r); 176 txt->txt_len = r.length; 177 txt->txt = mem_maybedup(mctx, r.base, r.length); 178 if (txt->txt == NULL) { 179 return (ISC_R_NOMEMORY); 180 } 181 182 txt->offset = 0; 183 txt->mctx = mctx; 184 return (ISC_R_SUCCESS); 185 } 186 187 static void 188 generic_freestruct_txt(ARGS_FREESTRUCT) { 189 dns_rdata_txt_t *txt = source; 190 191 REQUIRE(txt != NULL); 192 193 if (txt->mctx == NULL) { 194 return; 195 } 196 197 if (txt->txt != NULL) { 198 isc_mem_free(txt->mctx, txt->txt); 199 } 200 txt->mctx = NULL; 201 } 202 203 static isc_result_t 204 fromstruct_txt(ARGS_FROMSTRUCT) { 205 REQUIRE(type == dns_rdatatype_txt); 206 207 return (generic_fromstruct_txt(CALL_FROMSTRUCT)); 208 } 209 210 static isc_result_t 211 tostruct_txt(ARGS_TOSTRUCT) { 212 dns_rdata_txt_t *txt = target; 213 214 REQUIRE(rdata->type == dns_rdatatype_txt); 215 REQUIRE(txt != NULL); 216 217 txt->common.rdclass = rdata->rdclass; 218 txt->common.rdtype = rdata->type; 219 ISC_LINK_INIT(&txt->common, link); 220 221 return (generic_tostruct_txt(CALL_TOSTRUCT)); 222 } 223 224 static void 225 freestruct_txt(ARGS_FREESTRUCT) { 226 dns_rdata_txt_t *txt = source; 227 228 REQUIRE(txt != NULL); 229 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 230 231 generic_freestruct_txt(source); 232 } 233 234 static isc_result_t 235 additionaldata_txt(ARGS_ADDLDATA) { 236 REQUIRE(rdata->type == dns_rdatatype_txt); 237 238 UNUSED(rdata); 239 UNUSED(add); 240 UNUSED(arg); 241 242 return (ISC_R_SUCCESS); 243 } 244 245 static isc_result_t 246 digest_txt(ARGS_DIGEST) { 247 isc_region_t r; 248 249 REQUIRE(rdata->type == dns_rdatatype_txt); 250 251 dns_rdata_toregion(rdata, &r); 252 253 return ((digest)(arg, &r)); 254 } 255 256 static bool 257 checkowner_txt(ARGS_CHECKOWNER) { 258 REQUIRE(type == dns_rdatatype_txt); 259 260 UNUSED(name); 261 UNUSED(type); 262 UNUSED(rdclass); 263 UNUSED(wildcard); 264 265 return (true); 266 } 267 268 static bool 269 checknames_txt(ARGS_CHECKNAMES) { 270 REQUIRE(rdata->type == dns_rdatatype_txt); 271 272 UNUSED(rdata); 273 UNUSED(owner); 274 UNUSED(bad); 275 276 return (true); 277 } 278 279 static int 280 casecompare_txt(ARGS_COMPARE) { 281 return (compare_txt(rdata1, rdata2)); 282 } 283 284 static isc_result_t 285 generic_txt_first(dns_rdata_txt_t *txt) { 286 REQUIRE(txt != NULL); 287 REQUIRE(txt->txt != NULL || txt->txt_len == 0); 288 289 if (txt->txt_len == 0) { 290 return (ISC_R_NOMORE); 291 } 292 293 txt->offset = 0; 294 return (ISC_R_SUCCESS); 295 } 296 297 static isc_result_t 298 generic_txt_next(dns_rdata_txt_t *txt) { 299 isc_region_t r; 300 uint8_t length; 301 302 REQUIRE(txt != NULL); 303 REQUIRE(txt->txt != NULL && txt->txt_len != 0); 304 305 INSIST(txt->offset + 1 <= txt->txt_len); 306 r.base = txt->txt + txt->offset; 307 r.length = txt->txt_len - txt->offset; 308 length = uint8_fromregion(&r); 309 INSIST(txt->offset + 1 + length <= txt->txt_len); 310 txt->offset = txt->offset + 1 + length; 311 if (txt->offset == txt->txt_len) { 312 return (ISC_R_NOMORE); 313 } 314 return (ISC_R_SUCCESS); 315 } 316 317 static isc_result_t 318 generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { 319 isc_region_t r; 320 321 REQUIRE(txt != NULL); 322 REQUIRE(string != NULL); 323 REQUIRE(txt->txt != NULL); 324 REQUIRE(txt->offset < txt->txt_len); 325 326 INSIST(txt->offset + 1 <= txt->txt_len); 327 r.base = txt->txt + txt->offset; 328 r.length = txt->txt_len - txt->offset; 329 330 string->length = uint8_fromregion(&r); 331 isc_region_consume(&r, 1); 332 string->data = r.base; 333 INSIST(txt->offset + 1 + string->length <= txt->txt_len); 334 335 return (ISC_R_SUCCESS); 336 } 337 338 isc_result_t 339 dns_rdata_txt_first(dns_rdata_txt_t *txt) { 340 REQUIRE(txt != NULL); 341 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 342 343 return (generic_txt_first(txt)); 344 } 345 346 isc_result_t 347 dns_rdata_txt_next(dns_rdata_txt_t *txt) { 348 REQUIRE(txt != NULL); 349 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 350 351 return (generic_txt_next(txt)); 352 } 353 354 isc_result_t 355 dns_rdata_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { 356 REQUIRE(txt != NULL); 357 REQUIRE(txt->common.rdtype == dns_rdatatype_txt); 358 359 return (generic_txt_current(txt, string)); 360 } 361 #endif /* RDATA_GENERIC_TXT_16_C */ 362