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, ®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
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(®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
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