Home | History | Annotate | Line # | Download | only in generic
      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, &region);
     63 
     64 	while (region.length > 0) {
     65 		RETERR(txt_totext(&region, 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(&region);
    154 		isc_region_consume(&region, 1);
    155 		if (region.length < length) {
    156 			return ISC_R_UNEXPECTEDEND;
    157 		}
    158 		isc_region_consume(&region, 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