1 /*
2  * Copyright (C) 2004, 2007-2009, 2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2002  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
19 
20 #ifndef RDATA_GENERIC_TXT_16_C
21 #define RDATA_GENERIC_TXT_16_C
22 
23 #define RRTYPE_TXT_ATTRIBUTES (0)
24 
25 static inline isc_result_t
generic_fromtext_txt(ARGS_FROMTEXT)26 generic_fromtext_txt(ARGS_FROMTEXT) {
27 	isc_token_t token;
28 	int strings;
29 
30 	UNUSED(type);
31 	UNUSED(rdclass);
32 	UNUSED(origin);
33 	UNUSED(options);
34 	UNUSED(callbacks);
35 
36 	strings = 0;
37 	if ((options & DNS_RDATA_UNKNOWNESCAPE) != 0) {
38 		isc_textregion_t r;
39 		DE_CONST("#", r.base);
40 		r.length = 1;
41 		RETERR(txt_fromtext(&r, target));
42 		strings++;
43 	}
44 	for (;;) {
45 		RETERR(isc_lex_getmastertoken(lexer, &token,
46 					      isc_tokentype_qstring,
47 					      ISC_TRUE));
48 		if (token.type != isc_tokentype_qstring &&
49 		    token.type != isc_tokentype_string)
50 			break;
51 		RETTOK(txt_fromtext(&token.value.as_textregion, target));
52 		strings++;
53 	}
54 	/* Let upper layer handle eol/eof. */
55 	isc_lex_ungettoken(lexer, &token);
56 	return (strings == 0 ? ISC_R_UNEXPECTEDEND : ISC_R_SUCCESS);
57 }
58 
59 static inline isc_result_t
generic_totext_txt(ARGS_TOTEXT)60 generic_totext_txt(ARGS_TOTEXT) {
61 	isc_region_t region;
62 
63 	UNUSED(tctx);
64 
65 	dns_rdata_toregion(rdata, &region);
66 
67 	while (region.length > 0) {
68 		RETERR(txt_totext(&region, ISC_TRUE, target));
69 		if (region.length > 0)
70 			RETERR(str_totext(" ", target));
71 	}
72 
73 	return (ISC_R_SUCCESS);
74 }
75 
76 static inline isc_result_t
generic_fromwire_txt(ARGS_FROMWIRE)77 generic_fromwire_txt(ARGS_FROMWIRE) {
78 	isc_result_t result;
79 
80 	UNUSED(type);
81 	UNUSED(dctx);
82 	UNUSED(rdclass);
83 	UNUSED(options);
84 
85 	do {
86 		result = txt_fromwire(source, target);
87 		if (result != ISC_R_SUCCESS)
88 			return (result);
89 	} while (!buffer_empty(source));
90 	return (ISC_R_SUCCESS);
91 }
92 
93 static inline isc_result_t
fromtext_txt(ARGS_FROMTEXT)94 fromtext_txt(ARGS_FROMTEXT) {
95 
96 	REQUIRE(type == dns_rdatatype_txt);
97 
98 	return (generic_fromtext_txt(rdclass, type, lexer, origin, options,
99 				     target, callbacks));
100 }
101 
102 static inline isc_result_t
totext_txt(ARGS_TOTEXT)103 totext_txt(ARGS_TOTEXT) {
104 
105 	REQUIRE(rdata->type == dns_rdatatype_txt);
106 
107 	return (generic_totext_txt(rdata, tctx, target));
108 }
109 
110 static inline isc_result_t
fromwire_txt(ARGS_FROMWIRE)111 fromwire_txt(ARGS_FROMWIRE) {
112 
113 	REQUIRE(type == dns_rdatatype_txt);
114 
115 	return (generic_fromwire_txt(rdclass, type, source, dctx, options,
116 				     target));
117 }
118 
119 static inline isc_result_t
towire_txt(ARGS_TOWIRE)120 towire_txt(ARGS_TOWIRE) {
121 
122 	REQUIRE(rdata->type == dns_rdatatype_txt);
123 
124 	UNUSED(cctx);
125 
126 	return (mem_tobuffer(target, rdata->data, rdata->length));
127 }
128 
129 static inline int
compare_txt(ARGS_COMPARE)130 compare_txt(ARGS_COMPARE) {
131 	isc_region_t r1;
132 	isc_region_t r2;
133 
134 	REQUIRE(rdata1->type == rdata2->type);
135 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
136 	REQUIRE(rdata1->type == dns_rdatatype_txt);
137 
138 	dns_rdata_toregion(rdata1, &r1);
139 	dns_rdata_toregion(rdata2, &r2);
140 	return (isc_region_compare(&r1, &r2));
141 }
142 
143 static inline isc_result_t
generic_fromstruct_txt(ARGS_FROMSTRUCT)144 generic_fromstruct_txt(ARGS_FROMSTRUCT) {
145 	dns_rdata_txt_t *txt = source;
146 	isc_region_t region;
147 	isc_uint8_t length;
148 
149 	REQUIRE(source != NULL);
150 	REQUIRE(txt->common.rdtype == type);
151 	REQUIRE(txt->common.rdclass == rdclass);
152 	REQUIRE(txt->txt != NULL && txt->txt_len != 0);
153 
154 	UNUSED(type);
155 	UNUSED(rdclass);
156 
157 	region.base = txt->txt;
158 	region.length = txt->txt_len;
159 	while (region.length > 0) {
160 		length = uint8_fromregion(&region);
161 		isc_region_consume(&region, 1);
162 		if (region.length < length)
163 			return (ISC_R_UNEXPECTEDEND);
164 		isc_region_consume(&region, length);
165 	}
166 
167 	return (mem_tobuffer(target, txt->txt, txt->txt_len));
168 }
169 
170 static inline isc_result_t
generic_tostruct_txt(ARGS_TOSTRUCT)171 generic_tostruct_txt(ARGS_TOSTRUCT) {
172 	dns_rdata_txt_t *txt = target;
173 	isc_region_t r;
174 
175 	REQUIRE(target != NULL);
176 	REQUIRE(txt->common.rdclass == rdata->rdclass);
177 	REQUIRE(txt->common.rdtype == rdata->type);
178 	REQUIRE(!ISC_LINK_LINKED(&txt->common, link));
179 
180 	dns_rdata_toregion(rdata, &r);
181 	txt->txt_len = r.length;
182 	txt->txt = mem_maybedup(mctx, r.base, r.length);
183 	if (txt->txt == NULL)
184 		return (ISC_R_NOMEMORY);
185 
186 	txt->offset = 0;
187 	txt->mctx = mctx;
188 	return (ISC_R_SUCCESS);
189 }
190 
191 static inline void
generic_freestruct_txt(ARGS_FREESTRUCT)192 generic_freestruct_txt(ARGS_FREESTRUCT) {
193 	dns_rdata_txt_t *txt = source;
194 
195 	REQUIRE(source != NULL);
196 
197 	if (txt->mctx == NULL)
198 		return;
199 
200 	if (txt->txt != NULL)
201 		isc_mem_free(txt->mctx, txt->txt);
202 	txt->mctx = NULL;
203 }
204 
205 static inline isc_result_t
fromstruct_txt(ARGS_FROMSTRUCT)206 fromstruct_txt(ARGS_FROMSTRUCT) {
207 
208 	REQUIRE(type == dns_rdatatype_txt);
209 
210 	return (generic_fromstruct_txt(rdclass, type, source, target));
211 }
212 
213 static inline isc_result_t
tostruct_txt(ARGS_TOSTRUCT)214 tostruct_txt(ARGS_TOSTRUCT) {
215 	dns_rdata_txt_t *txt = target;
216 
217 	REQUIRE(rdata->type == dns_rdatatype_txt);
218 	REQUIRE(target != NULL);
219 
220 	txt->common.rdclass = rdata->rdclass;
221 	txt->common.rdtype = rdata->type;
222 	ISC_LINK_INIT(&txt->common, link);
223 
224 	return (generic_tostruct_txt(rdata, target, mctx));
225 }
226 
227 static inline void
freestruct_txt(ARGS_FREESTRUCT)228 freestruct_txt(ARGS_FREESTRUCT) {
229 	dns_rdata_txt_t *txt = source;
230 
231 	REQUIRE(source != NULL);
232 	REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
233 
234 	generic_freestruct_txt(source);
235 }
236 
237 static inline isc_result_t
additionaldata_txt(ARGS_ADDLDATA)238 additionaldata_txt(ARGS_ADDLDATA) {
239 	REQUIRE(rdata->type == dns_rdatatype_txt);
240 
241 	UNUSED(rdata);
242 	UNUSED(add);
243 	UNUSED(arg);
244 
245 	return (ISC_R_SUCCESS);
246 }
247 
248 static inline isc_result_t
digest_txt(ARGS_DIGEST)249 digest_txt(ARGS_DIGEST) {
250 	isc_region_t r;
251 
252 	REQUIRE(rdata->type == dns_rdatatype_txt);
253 
254 	dns_rdata_toregion(rdata, &r);
255 
256 	return ((digest)(arg, &r));
257 }
258 
259 static inline isc_boolean_t
checkowner_txt(ARGS_CHECKOWNER)260 checkowner_txt(ARGS_CHECKOWNER) {
261 
262 	REQUIRE(type == dns_rdatatype_txt);
263 
264 	UNUSED(name);
265 	UNUSED(type);
266 	UNUSED(rdclass);
267 	UNUSED(wildcard);
268 
269 	return (ISC_TRUE);
270 }
271 
272 static inline isc_boolean_t
checknames_txt(ARGS_CHECKNAMES)273 checknames_txt(ARGS_CHECKNAMES) {
274 
275 	REQUIRE(rdata->type == dns_rdatatype_txt);
276 
277 	UNUSED(rdata);
278 	UNUSED(owner);
279 	UNUSED(bad);
280 
281 	return (ISC_TRUE);
282 }
283 
284 static inline isc_result_t
casecompare_txt(ARGS_COMPARE)285 casecompare_txt(ARGS_COMPARE) {
286 	return (compare_txt(rdata1, rdata2));
287 }
288 
289 static isc_result_t
generic_txt_first(dns_rdata_txt_t * txt)290 generic_txt_first(dns_rdata_txt_t *txt) {
291 
292 	REQUIRE(txt != NULL);
293 	REQUIRE(txt->txt != NULL || txt->txt_len == 0);
294 
295 	if (txt->txt_len == 0)
296 		return (ISC_R_NOMORE);
297 
298 	txt->offset = 0;
299 	return (ISC_R_SUCCESS);
300 }
301 
302 static isc_result_t
generic_txt_next(dns_rdata_txt_t * txt)303 generic_txt_next(dns_rdata_txt_t *txt) {
304 	isc_region_t r;
305 	isc_uint8_t length;
306 
307 	REQUIRE(txt != NULL);
308 	REQUIRE(txt->txt != NULL && txt->txt_len != 0);
309 
310 	INSIST(txt->offset + 1 <= txt->txt_len);
311 	r.base = txt->txt + txt->offset;
312 	r.length = txt->txt_len - txt->offset;
313 	length = uint8_fromregion(&r);
314 	INSIST(txt->offset + 1 + length <= txt->txt_len);
315 	txt->offset = txt->offset + 1 + length;
316 	if (txt->offset == txt->txt_len)
317 		return (ISC_R_NOMORE);
318 	return (ISC_R_SUCCESS);
319 }
320 
321 static isc_result_t
generic_txt_current(dns_rdata_txt_t * txt,dns_rdata_txt_string_t * string)322 generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) {
323 	isc_region_t r;
324 
325 	REQUIRE(txt != NULL);
326 	REQUIRE(string != NULL);
327 	REQUIRE(txt->txt != NULL);
328 	REQUIRE(txt->offset < txt->txt_len);
329 
330 	INSIST(txt->offset + 1 <= txt->txt_len);
331 	r.base = txt->txt + txt->offset;
332 	r.length = txt->txt_len - txt->offset;
333 
334 	string->length = uint8_fromregion(&r);
335 	isc_region_consume(&r, 1);
336 	string->data = r.base;
337 	INSIST(txt->offset + 1 + string->length <= txt->txt_len);
338 
339 	return (ISC_R_SUCCESS);
340 }
341 
342 isc_result_t
dns_rdata_txt_first(dns_rdata_txt_t * txt)343 dns_rdata_txt_first(dns_rdata_txt_t *txt) {
344 
345 	REQUIRE(txt != NULL);
346 	REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
347 
348 	return (generic_txt_first(txt));
349 }
350 
351 isc_result_t
dns_rdata_txt_next(dns_rdata_txt_t * txt)352 dns_rdata_txt_next(dns_rdata_txt_t *txt) {
353 
354 	REQUIRE(txt != NULL);
355 	REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
356 
357 	return (generic_txt_next(txt));
358 }
359 
360 isc_result_t
dns_rdata_txt_current(dns_rdata_txt_t * txt,dns_rdata_txt_string_t * string)361 dns_rdata_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) {
362 
363 	REQUIRE(txt != NULL);
364 	REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
365 
366 	return (generic_txt_current(txt, string));
367 }
368 #endif	/* RDATA_GENERIC_TXT_16_C */
369