xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/caa_257.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: caa_257.c,v 1.10 2025/01/26 16:25: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 GENERIC_CAA_257_C
17 #define GENERIC_CAA_257_C 1
18 
19 #define RRTYPE_CAA_ATTRIBUTES (0)
20 
21 static unsigned char const alphanumeric[256] = {
22 	/* 0x00-0x0f */ 0,
23 	0,
24 	0,
25 	0,
26 	0,
27 	0,
28 	0,
29 	0,
30 	0,
31 	0,
32 	0,
33 	0,
34 	0,
35 	0,
36 	0,
37 	0,
38 	/* 0x10-0x1f */ 0,
39 	0,
40 	0,
41 	0,
42 	0,
43 	0,
44 	0,
45 	0,
46 	0,
47 	0,
48 	0,
49 	0,
50 	0,
51 	0,
52 	0,
53 	0,
54 	/* 0x20-0x2f */ 0,
55 	0,
56 	0,
57 	0,
58 	0,
59 	0,
60 	0,
61 	0,
62 	0,
63 	0,
64 	0,
65 	0,
66 	0,
67 	0,
68 	0,
69 	0,
70 	/* 0x30-0x3f */ 1,
71 	1,
72 	1,
73 	1,
74 	1,
75 	1,
76 	1,
77 	1,
78 	1,
79 	1,
80 	0,
81 	0,
82 	0,
83 	0,
84 	0,
85 	0,
86 	/* 0x40-0x4f */ 0,
87 	1,
88 	1,
89 	1,
90 	1,
91 	1,
92 	1,
93 	1,
94 	1,
95 	1,
96 	1,
97 	1,
98 	1,
99 	1,
100 	1,
101 	1,
102 	/* 0x50-0x5f */ 1,
103 	1,
104 	1,
105 	1,
106 	1,
107 	1,
108 	1,
109 	1,
110 	1,
111 	1,
112 	1,
113 	0,
114 	0,
115 	0,
116 	0,
117 	0,
118 	/* 0x60-0x6f */ 0,
119 	1,
120 	1,
121 	1,
122 	1,
123 	1,
124 	1,
125 	1,
126 	1,
127 	1,
128 	1,
129 	1,
130 	1,
131 	1,
132 	1,
133 	1,
134 	/* 0x70-0x7f */ 1,
135 	1,
136 	1,
137 	1,
138 	1,
139 	1,
140 	1,
141 	1,
142 	1,
143 	1,
144 	1,
145 	0,
146 	0,
147 	0,
148 	0,
149 	0,
150 	/* 0x80-0x8f */ 0,
151 	0,
152 	0,
153 	0,
154 	0,
155 	0,
156 	0,
157 	0,
158 	0,
159 	0,
160 	0,
161 	0,
162 	0,
163 	0,
164 	0,
165 	0,
166 	/* 0x90-0x9f */ 0,
167 	0,
168 	0,
169 	0,
170 	0,
171 	0,
172 	0,
173 	0,
174 	0,
175 	0,
176 	0,
177 	0,
178 	0,
179 	0,
180 	0,
181 	0,
182 	/* 0xa0-0xaf */ 0,
183 	0,
184 	0,
185 	0,
186 	0,
187 	0,
188 	0,
189 	0,
190 	0,
191 	0,
192 	0,
193 	0,
194 	0,
195 	0,
196 	0,
197 	0,
198 	/* 0xb0-0xbf */ 0,
199 	0,
200 	0,
201 	0,
202 	0,
203 	0,
204 	0,
205 	0,
206 	0,
207 	0,
208 	0,
209 	0,
210 	0,
211 	0,
212 	0,
213 	0,
214 	/* 0xc0-0xcf */ 0,
215 	0,
216 	0,
217 	0,
218 	0,
219 	0,
220 	0,
221 	0,
222 	0,
223 	0,
224 	0,
225 	0,
226 	0,
227 	0,
228 	0,
229 	0,
230 	/* 0xd0-0xdf */ 0,
231 	0,
232 	0,
233 	0,
234 	0,
235 	0,
236 	0,
237 	0,
238 	0,
239 	0,
240 	0,
241 	0,
242 	0,
243 	0,
244 	0,
245 	0,
246 	/* 0xe0-0xef */ 0,
247 	0,
248 	0,
249 	0,
250 	0,
251 	0,
252 	0,
253 	0,
254 	0,
255 	0,
256 	0,
257 	0,
258 	0,
259 	0,
260 	0,
261 	0,
262 	/* 0xf0-0xff */ 0,
263 	0,
264 	0,
265 	0,
266 	0,
267 	0,
268 	0,
269 	0,
270 	0,
271 	0,
272 	0,
273 	0,
274 	0,
275 	0,
276 	0,
277 	0,
278 };
279 
280 static isc_result_t
281 fromtext_caa(ARGS_FROMTEXT) {
282 	isc_token_t token;
283 	isc_textregion_t tr;
284 	uint8_t flags;
285 	unsigned int i;
286 
287 	REQUIRE(type == dns_rdatatype_caa);
288 
289 	UNUSED(type);
290 	UNUSED(rdclass);
291 	UNUSED(origin);
292 	UNUSED(options);
293 	UNUSED(callbacks);
294 
295 	/* Flags. */
296 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
297 				      false));
298 	if (token.value.as_ulong > 255U) {
299 		RETTOK(ISC_R_RANGE);
300 	}
301 	flags = (uint8_t)(token.value.as_ulong & 255U);
302 	RETERR(uint8_tobuffer(flags, target));
303 
304 	/*
305 	 * Tag
306 	 */
307 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
308 				      false));
309 	tr = token.value.as_textregion;
310 	for (i = 0; i < tr.length; i++) {
311 		if (!alphanumeric[(unsigned char)tr.base[i]]) {
312 			RETTOK(DNS_R_SYNTAX);
313 		}
314 	}
315 	RETERR(uint8_tobuffer(tr.length, target));
316 	RETERR(mem_tobuffer(target, tr.base, tr.length));
317 
318 	/*
319 	 * Value
320 	 */
321 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
322 				      false));
323 	if (token.type != isc_tokentype_qstring &&
324 	    token.type != isc_tokentype_string)
325 	{
326 		RETERR(DNS_R_SYNTAX);
327 	}
328 	RETERR(multitxt_fromtext(&token.value.as_textregion, target));
329 	return ISC_R_SUCCESS;
330 }
331 
332 static isc_result_t
333 totext_caa(ARGS_TOTEXT) {
334 	isc_region_t region;
335 	uint8_t flags;
336 	char buf[256];
337 
338 	UNUSED(tctx);
339 
340 	REQUIRE(rdata->type == dns_rdatatype_caa);
341 	REQUIRE(rdata->length >= 3U);
342 	REQUIRE(rdata->data != NULL);
343 
344 	dns_rdata_toregion(rdata, &region);
345 
346 	/*
347 	 * Flags
348 	 */
349 	flags = uint8_consume_fromregion(&region);
350 	snprintf(buf, sizeof(buf), "%u ", flags);
351 	RETERR(str_totext(buf, target));
352 
353 	/*
354 	 * Tag
355 	 */
356 	RETERR(txt_totext(&region, false, target));
357 	RETERR(str_totext(" ", target));
358 
359 	/*
360 	 * Value
361 	 */
362 	RETERR(multitxt_totext(&region, target));
363 	return ISC_R_SUCCESS;
364 }
365 
366 static isc_result_t
367 fromwire_caa(ARGS_FROMWIRE) {
368 	isc_region_t sr;
369 	unsigned int len, i;
370 
371 	REQUIRE(type == dns_rdatatype_caa);
372 
373 	UNUSED(type);
374 	UNUSED(rdclass);
375 	UNUSED(dctx);
376 
377 	/*
378 	 * Flags
379 	 */
380 	isc_buffer_activeregion(source, &sr);
381 	if (sr.length < 2) {
382 		return ISC_R_UNEXPECTEDEND;
383 	}
384 
385 	/*
386 	 * Flags, tag length
387 	 */
388 	RETERR(mem_tobuffer(target, sr.base, 2));
389 	len = sr.base[1];
390 	isc_region_consume(&sr, 2);
391 	isc_buffer_forward(source, 2);
392 
393 	/*
394 	 * Zero length tag fields are illegal.
395 	 */
396 	if (sr.length < len || len == 0) {
397 		RETERR(DNS_R_FORMERR);
398 	}
399 
400 	/* Check the Tag's value */
401 	for (i = 0; i < len; i++) {
402 		if (!alphanumeric[sr.base[i]]) {
403 			RETERR(DNS_R_FORMERR);
404 			/*
405 			 * Tag + Value
406 			 */
407 		}
408 	}
409 	/*
410 	 * Tag + Value
411 	 */
412 	isc_buffer_forward(source, sr.length);
413 	return mem_tobuffer(target, sr.base, sr.length);
414 }
415 
416 static isc_result_t
417 towire_caa(ARGS_TOWIRE) {
418 	isc_region_t region;
419 
420 	REQUIRE(rdata->type == dns_rdatatype_caa);
421 	REQUIRE(rdata->length >= 3U);
422 	REQUIRE(rdata->data != NULL);
423 
424 	UNUSED(cctx);
425 
426 	dns_rdata_toregion(rdata, &region);
427 	return mem_tobuffer(target, region.base, region.length);
428 }
429 
430 static int
431 compare_caa(ARGS_COMPARE) {
432 	isc_region_t r1, r2;
433 
434 	REQUIRE(rdata1->type == rdata2->type);
435 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
436 	REQUIRE(rdata1->type == dns_rdatatype_caa);
437 	REQUIRE(rdata1->length >= 3U);
438 	REQUIRE(rdata2->length >= 3U);
439 	REQUIRE(rdata1->data != NULL);
440 	REQUIRE(rdata2->data != NULL);
441 
442 	dns_rdata_toregion(rdata1, &r1);
443 	dns_rdata_toregion(rdata2, &r2);
444 	return isc_region_compare(&r1, &r2);
445 }
446 
447 static isc_result_t
448 fromstruct_caa(ARGS_FROMSTRUCT) {
449 	dns_rdata_caa_t *caa = source;
450 	isc_region_t region;
451 	unsigned int i;
452 
453 	REQUIRE(type == dns_rdatatype_caa);
454 	REQUIRE(caa != NULL);
455 	REQUIRE(caa->common.rdtype == type);
456 	REQUIRE(caa->common.rdclass == rdclass);
457 	REQUIRE(caa->tag != NULL && caa->tag_len != 0);
458 	REQUIRE(caa->value != NULL);
459 
460 	UNUSED(type);
461 	UNUSED(rdclass);
462 
463 	/*
464 	 * Flags
465 	 */
466 	RETERR(uint8_tobuffer(caa->flags, target));
467 
468 	/*
469 	 * Tag length
470 	 */
471 	RETERR(uint8_tobuffer(caa->tag_len, target));
472 
473 	/*
474 	 * Tag
475 	 */
476 	region.base = caa->tag;
477 	region.length = caa->tag_len;
478 	for (i = 0; i < region.length; i++) {
479 		if (!alphanumeric[region.base[i]]) {
480 			RETERR(DNS_R_SYNTAX);
481 		}
482 	}
483 	RETERR(isc_buffer_copyregion(target, &region));
484 
485 	/*
486 	 * Value
487 	 */
488 	region.base = caa->value;
489 	region.length = caa->value_len;
490 	return isc_buffer_copyregion(target, &region);
491 }
492 
493 static isc_result_t
494 tostruct_caa(ARGS_TOSTRUCT) {
495 	dns_rdata_caa_t *caa = target;
496 	isc_region_t sr;
497 
498 	REQUIRE(rdata->type == dns_rdatatype_caa);
499 	REQUIRE(caa != NULL);
500 	REQUIRE(rdata->length >= 3U);
501 	REQUIRE(rdata->data != NULL);
502 
503 	caa->common.rdclass = rdata->rdclass;
504 	caa->common.rdtype = rdata->type;
505 	ISC_LINK_INIT(&caa->common, link);
506 
507 	dns_rdata_toregion(rdata, &sr);
508 
509 	/*
510 	 * Flags
511 	 */
512 	caa->flags = uint8_fromregion(&sr);
513 	isc_region_consume(&sr, 1);
514 
515 	/*
516 	 * Tag length
517 	 */
518 	caa->tag_len = uint8_fromregion(&sr);
519 	isc_region_consume(&sr, 1);
520 
521 	/*
522 	 * Tag
523 	 */
524 	INSIST(sr.length >= caa->tag_len);
525 	caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len);
526 	isc_region_consume(&sr, caa->tag_len);
527 
528 	/*
529 	 * Value
530 	 */
531 	caa->value_len = sr.length;
532 	caa->value = mem_maybedup(mctx, sr.base, sr.length);
533 
534 	caa->mctx = mctx;
535 	return ISC_R_SUCCESS;
536 }
537 
538 static void
539 freestruct_caa(ARGS_FREESTRUCT) {
540 	dns_rdata_caa_t *caa = (dns_rdata_caa_t *)source;
541 
542 	REQUIRE(caa != NULL);
543 	REQUIRE(caa->common.rdtype == dns_rdatatype_caa);
544 
545 	if (caa->mctx == NULL) {
546 		return;
547 	}
548 
549 	if (caa->tag != NULL) {
550 		isc_mem_free(caa->mctx, caa->tag);
551 	}
552 	if (caa->value != NULL) {
553 		isc_mem_free(caa->mctx, caa->value);
554 	}
555 	caa->mctx = NULL;
556 }
557 
558 static isc_result_t
559 additionaldata_caa(ARGS_ADDLDATA) {
560 	REQUIRE(rdata->type == dns_rdatatype_caa);
561 	REQUIRE(rdata->data != NULL);
562 	REQUIRE(rdata->length >= 3U);
563 
564 	UNUSED(rdata);
565 	UNUSED(owner);
566 	UNUSED(add);
567 	UNUSED(arg);
568 
569 	return ISC_R_SUCCESS;
570 }
571 
572 static isc_result_t
573 digest_caa(ARGS_DIGEST) {
574 	isc_region_t r;
575 
576 	REQUIRE(rdata->type == dns_rdatatype_caa);
577 	REQUIRE(rdata->data != NULL);
578 	REQUIRE(rdata->length >= 3U);
579 
580 	dns_rdata_toregion(rdata, &r);
581 
582 	return (digest)(arg, &r);
583 }
584 
585 static bool
586 checkowner_caa(ARGS_CHECKOWNER) {
587 	REQUIRE(type == dns_rdatatype_caa);
588 
589 	UNUSED(name);
590 	UNUSED(type);
591 	UNUSED(rdclass);
592 	UNUSED(wildcard);
593 
594 	return true;
595 }
596 
597 static bool
598 checknames_caa(ARGS_CHECKNAMES) {
599 	REQUIRE(rdata->type == dns_rdatatype_caa);
600 	REQUIRE(rdata->data != NULL);
601 	REQUIRE(rdata->length >= 3U);
602 
603 	UNUSED(rdata);
604 	UNUSED(owner);
605 	UNUSED(bad);
606 
607 	return true;
608 }
609 
610 static int
611 casecompare_caa(ARGS_COMPARE) {
612 	return compare_caa(rdata1, rdata2);
613 }
614 
615 #endif /* GENERIC_CAA_257_C */
616