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
generic_fromtext_txt(ARGS_FROMTEXT)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
generic_totext_txt(ARGS_TOTEXT)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
generic_fromwire_txt(ARGS_FROMWIRE)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
fromtext_txt(ARGS_FROMTEXT)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
totext_txt(ARGS_TOTEXT)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
fromwire_txt(ARGS_FROMWIRE)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
towire_txt(ARGS_TOWIRE)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
compare_txt(ARGS_COMPARE)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
generic_fromstruct_txt(ARGS_FROMSTRUCT)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(&region);
155 		isc_region_consume(&region, 1);
156 		if (region.length < length) {
157 			return (ISC_R_UNEXPECTEDEND);
158 		}
159 		isc_region_consume(&region, length);
160 	}
161 
162 	return (mem_tobuffer(target, txt->txt, txt->txt_len));
163 }
164 
165 static isc_result_t
generic_tostruct_txt(ARGS_TOSTRUCT)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
generic_freestruct_txt(ARGS_FREESTRUCT)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
fromstruct_txt(ARGS_FROMSTRUCT)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
tostruct_txt(ARGS_TOSTRUCT)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
freestruct_txt(ARGS_FREESTRUCT)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
additionaldata_txt(ARGS_ADDLDATA)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
digest_txt(ARGS_DIGEST)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
checkowner_txt(ARGS_CHECKOWNER)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
checknames_txt(ARGS_CHECKNAMES)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
casecompare_txt(ARGS_COMPARE)280 casecompare_txt(ARGS_COMPARE) {
281 	return (compare_txt(rdata1, rdata2));
282 }
283 
284 static isc_result_t
generic_txt_first(dns_rdata_txt_t * txt)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
generic_txt_next(dns_rdata_txt_t * txt)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
generic_txt_current(dns_rdata_txt_t * txt,dns_rdata_txt_string_t * string)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
dns_rdata_txt_first(dns_rdata_txt_t * txt)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
dns_rdata_txt_next(dns_rdata_txt_t * txt)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
dns_rdata_txt_current(dns_rdata_txt_t * txt,dns_rdata_txt_string_t * string)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