xref: /netbsd-src/external/mpl/dhcp/bind/dist/lib/dns/rdata/generic/caa_257.c (revision 4afad4b7fa6d4a0d3dedf41d1587a7250710ae54)
1 /*	$NetBSD: caa_257.c,v 1.1 2024/02/18 20:57:40 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
fromtext_caa(ARGS_FROMTEXT)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
totext_caa(ARGS_TOTEXT)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
fromwire_caa(ARGS_FROMWIRE)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 	UNUSED(options);
377 
378 	/*
379 	 * Flags
380 	 */
381 	isc_buffer_activeregion(source, &sr);
382 	if (sr.length < 2) {
383 		return (ISC_R_UNEXPECTEDEND);
384 	}
385 
386 	/*
387 	 * Flags, tag length
388 	 */
389 	RETERR(mem_tobuffer(target, sr.base, 2));
390 	len = sr.base[1];
391 	isc_region_consume(&sr, 2);
392 	isc_buffer_forward(source, 2);
393 
394 	/*
395 	 * Zero length tag fields are illegal.
396 	 */
397 	if (sr.length < len || len == 0) {
398 		RETERR(DNS_R_FORMERR);
399 	}
400 
401 	/* Check the Tag's value */
402 	for (i = 0; i < len; i++) {
403 		if (!alphanumeric[sr.base[i]]) {
404 			RETERR(DNS_R_FORMERR);
405 			/*
406 			 * Tag + Value
407 			 */
408 		}
409 	}
410 	/*
411 	 * Tag + Value
412 	 */
413 	isc_buffer_forward(source, sr.length);
414 	return (mem_tobuffer(target, sr.base, sr.length));
415 }
416 
417 static isc_result_t
towire_caa(ARGS_TOWIRE)418 towire_caa(ARGS_TOWIRE) {
419 	isc_region_t region;
420 
421 	REQUIRE(rdata->type == dns_rdatatype_caa);
422 	REQUIRE(rdata->length >= 3U);
423 	REQUIRE(rdata->data != NULL);
424 
425 	UNUSED(cctx);
426 
427 	dns_rdata_toregion(rdata, &region);
428 	return (mem_tobuffer(target, region.base, region.length));
429 }
430 
431 static int
compare_caa(ARGS_COMPARE)432 compare_caa(ARGS_COMPARE) {
433 	isc_region_t r1, r2;
434 
435 	REQUIRE(rdata1->type == rdata2->type);
436 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
437 	REQUIRE(rdata1->type == dns_rdatatype_caa);
438 	REQUIRE(rdata1->length >= 3U);
439 	REQUIRE(rdata2->length >= 3U);
440 	REQUIRE(rdata1->data != NULL);
441 	REQUIRE(rdata2->data != NULL);
442 
443 	dns_rdata_toregion(rdata1, &r1);
444 	dns_rdata_toregion(rdata2, &r2);
445 	return (isc_region_compare(&r1, &r2));
446 }
447 
448 static isc_result_t
fromstruct_caa(ARGS_FROMSTRUCT)449 fromstruct_caa(ARGS_FROMSTRUCT) {
450 	dns_rdata_caa_t *caa = source;
451 	isc_region_t region;
452 	unsigned int i;
453 
454 	REQUIRE(type == dns_rdatatype_caa);
455 	REQUIRE(caa != NULL);
456 	REQUIRE(caa->common.rdtype == type);
457 	REQUIRE(caa->common.rdclass == rdclass);
458 	REQUIRE(caa->tag != NULL && caa->tag_len != 0);
459 	REQUIRE(caa->value != NULL);
460 
461 	UNUSED(type);
462 	UNUSED(rdclass);
463 
464 	/*
465 	 * Flags
466 	 */
467 	RETERR(uint8_tobuffer(caa->flags, target));
468 
469 	/*
470 	 * Tag length
471 	 */
472 	RETERR(uint8_tobuffer(caa->tag_len, target));
473 
474 	/*
475 	 * Tag
476 	 */
477 	region.base = caa->tag;
478 	region.length = caa->tag_len;
479 	for (i = 0; i < region.length; i++) {
480 		if (!alphanumeric[region.base[i]]) {
481 			RETERR(DNS_R_SYNTAX);
482 		}
483 	}
484 	RETERR(isc_buffer_copyregion(target, &region));
485 
486 	/*
487 	 * Value
488 	 */
489 	region.base = caa->value;
490 	region.length = caa->value_len;
491 	return (isc_buffer_copyregion(target, &region));
492 }
493 
494 static isc_result_t
tostruct_caa(ARGS_TOSTRUCT)495 tostruct_caa(ARGS_TOSTRUCT) {
496 	dns_rdata_caa_t *caa = target;
497 	isc_region_t sr;
498 
499 	REQUIRE(rdata->type == dns_rdatatype_caa);
500 	REQUIRE(caa != NULL);
501 	REQUIRE(rdata->length >= 3U);
502 	REQUIRE(rdata->data != NULL);
503 
504 	caa->common.rdclass = rdata->rdclass;
505 	caa->common.rdtype = rdata->type;
506 	ISC_LINK_INIT(&caa->common, link);
507 
508 	dns_rdata_toregion(rdata, &sr);
509 
510 	/*
511 	 * Flags
512 	 */
513 	if (sr.length < 1) {
514 		return (ISC_R_UNEXPECTEDEND);
515 	}
516 	caa->flags = uint8_fromregion(&sr);
517 	isc_region_consume(&sr, 1);
518 
519 	/*
520 	 * Tag length
521 	 */
522 	if (sr.length < 1) {
523 		return (ISC_R_UNEXPECTEDEND);
524 	}
525 	caa->tag_len = uint8_fromregion(&sr);
526 	isc_region_consume(&sr, 1);
527 
528 	/*
529 	 * Tag
530 	 */
531 	if (sr.length < caa->tag_len) {
532 		return (ISC_R_UNEXPECTEDEND);
533 	}
534 	caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len);
535 	if (caa->tag == NULL) {
536 		return (ISC_R_NOMEMORY);
537 	}
538 	isc_region_consume(&sr, caa->tag_len);
539 
540 	/*
541 	 * Value
542 	 */
543 	caa->value_len = sr.length;
544 	caa->value = mem_maybedup(mctx, sr.base, sr.length);
545 	if (caa->value == NULL) {
546 		return (ISC_R_NOMEMORY);
547 	}
548 
549 	caa->mctx = mctx;
550 	return (ISC_R_SUCCESS);
551 }
552 
553 static void
freestruct_caa(ARGS_FREESTRUCT)554 freestruct_caa(ARGS_FREESTRUCT) {
555 	dns_rdata_caa_t *caa = (dns_rdata_caa_t *)source;
556 
557 	REQUIRE(caa != NULL);
558 	REQUIRE(caa->common.rdtype == dns_rdatatype_caa);
559 
560 	if (caa->mctx == NULL) {
561 		return;
562 	}
563 
564 	if (caa->tag != NULL) {
565 		isc_mem_free(caa->mctx, caa->tag);
566 	}
567 	if (caa->value != NULL) {
568 		isc_mem_free(caa->mctx, caa->value);
569 	}
570 	caa->mctx = NULL;
571 }
572 
573 static isc_result_t
additionaldata_caa(ARGS_ADDLDATA)574 additionaldata_caa(ARGS_ADDLDATA) {
575 	REQUIRE(rdata->type == dns_rdatatype_caa);
576 	REQUIRE(rdata->data != NULL);
577 	REQUIRE(rdata->length >= 3U);
578 
579 	UNUSED(rdata);
580 	UNUSED(add);
581 	UNUSED(arg);
582 
583 	return (ISC_R_SUCCESS);
584 }
585 
586 static isc_result_t
digest_caa(ARGS_DIGEST)587 digest_caa(ARGS_DIGEST) {
588 	isc_region_t r;
589 
590 	REQUIRE(rdata->type == dns_rdatatype_caa);
591 	REQUIRE(rdata->data != NULL);
592 	REQUIRE(rdata->length >= 3U);
593 
594 	dns_rdata_toregion(rdata, &r);
595 
596 	return ((digest)(arg, &r));
597 }
598 
599 static bool
checkowner_caa(ARGS_CHECKOWNER)600 checkowner_caa(ARGS_CHECKOWNER) {
601 	REQUIRE(type == dns_rdatatype_caa);
602 
603 	UNUSED(name);
604 	UNUSED(type);
605 	UNUSED(rdclass);
606 	UNUSED(wildcard);
607 
608 	return (true);
609 }
610 
611 static bool
checknames_caa(ARGS_CHECKNAMES)612 checknames_caa(ARGS_CHECKNAMES) {
613 	REQUIRE(rdata->type == dns_rdatatype_caa);
614 	REQUIRE(rdata->data != NULL);
615 	REQUIRE(rdata->length >= 3U);
616 
617 	UNUSED(rdata);
618 	UNUSED(owner);
619 	UNUSED(bad);
620 
621 	return (true);
622 }
623 
624 static int
casecompare_caa(ARGS_COMPARE)625 casecompare_caa(ARGS_COMPARE) {
626 	return (compare_caa(rdata1, rdata2));
627 }
628 
629 #endif /* GENERIC_CAA_257_C */
630