xref: /openbsd-src/usr.bin/dig/lib/dns/rdata.c (revision 5c389b79544373bccfce668b646e62e7ba9802a3)
1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* $Id: rdata.c,v 1.35 2022/07/03 12:07:52 florian Exp $ */
18 
19 /*! \file */
20 
21 #include <arpa/inet.h>
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include <isc/base64.h>
27 #include <isc/hex.h>
28 #include <isc/util.h>
29 #include <isc/buffer.h>
30 
31 #include <dns/cert.h>
32 #include <dns/compress.h>
33 #include <dns/keyvalues.h>
34 #include <dns/rcode.h>
35 #include <dns/rdata.h>
36 #include <dns/rdatatype.h>
37 #include <dns/result.h>
38 #include <dns/time.h>
39 #include <dns/ttl.h>
40 
41 #define RETERR(x) \
42 	do { \
43 		isc_result_t _r = (x); \
44 		if (_r != ISC_R_SUCCESS) \
45 			return (_r); \
46 	} while (0)
47 
48 #define ARGS_TOTEXT	dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
49 			isc_buffer_t *target
50 
51 #define ARGS_FROMWIRE	int rdclass, dns_rdatatype_t type, \
52 			isc_buffer_t *source, dns_decompress_t *dctx, \
53 			unsigned int options, isc_buffer_t *target
54 
55 #define ARGS_TOWIRE	dns_rdata_t *rdata, dns_compress_t *cctx, \
56 			isc_buffer_t *target
57 
58 #define ARGS_FROMSTRUCT	int rdclass, dns_rdatatype_t type, \
59 			void *source, isc_buffer_t *target
60 
61 #define ARGS_TOSTRUCT	const dns_rdata_t *rdata, void *target
62 
63 #define ARGS_FREESTRUCT void *source
64 
65 #define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
66 			dns_rdatatype_t type, int wildcard
67 
68 /*%
69  * Context structure for the totext_ functions.
70  * Contains formatting options for rdata-to-text
71  * conversion.
72  */
73 typedef struct dns_rdata_textctx {
74 	dns_name_t *origin;	/*%< Current origin, or NULL. */
75 	unsigned int flags;	/*%< DNS_STYLEFLAG_*  */
76 	unsigned int width;	/*%< Width of rdata column. */
77 	const char *linebreak;	/*%< Line break string. */
78 } dns_rdata_textctx_t;
79 
80 typedef struct dns_rdata_type_lookup {
81 	const char	*type;
82 	int		 val;
83 } dns_rdata_type_lookup_t;
84 
85 static isc_result_t
86 txt_totext(isc_region_t *source, int quote, isc_buffer_t *target);
87 
88 static isc_result_t
89 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
90 
91 static isc_result_t
92 multitxt_totext(isc_region_t *source, isc_buffer_t *target);
93 
94 static int
95 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
96 
97 static unsigned int
98 name_length(dns_name_t *name);
99 
100 static isc_result_t
101 inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
102 
103 static int
104 buffer_empty(isc_buffer_t *source);
105 
106 static isc_result_t
107 uint32_tobuffer(uint32_t, isc_buffer_t *target);
108 
109 static isc_result_t
110 uint16_tobuffer(uint32_t, isc_buffer_t *target);
111 
112 static isc_result_t
113 name_tobuffer(dns_name_t *name, isc_buffer_t *target);
114 
115 static uint32_t
116 uint32_fromregion(isc_region_t *region);
117 
118 static uint16_t
119 uint16_fromregion(isc_region_t *region);
120 
121 static uint8_t
122 uint8_fromregion(isc_region_t *region);
123 
124 static uint8_t
125 uint8_consume_fromregion(isc_region_t *region);
126 
127 static isc_result_t
128 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
129 
130 static isc_result_t
131 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
132 	     isc_buffer_t *target);
133 
134 static isc_result_t
135 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
136 	       isc_buffer_t *target);
137 
138 static inline isc_result_t
139 generic_totext_key(ARGS_TOTEXT);
140 
141 static inline isc_result_t
142 generic_fromwire_key(ARGS_FROMWIRE);
143 
144 static isc_result_t
145 generic_totext_txt(ARGS_TOTEXT);
146 
147 static isc_result_t
148 generic_fromwire_txt(ARGS_FROMWIRE);
149 
150 static isc_result_t
151 generic_totext_ds(ARGS_TOTEXT);
152 
153 static isc_result_t
154 generic_fromwire_ds(ARGS_FROMWIRE);
155 
156 static isc_result_t
157 generic_totext_tlsa(ARGS_TOTEXT);
158 
159 static isc_result_t
160 generic_fromwire_tlsa(ARGS_FROMWIRE);
161 
162 static inline isc_result_t
163 name_duporclone(dns_name_t *source, dns_name_t *target) {
164 
165 	return (dns_name_dup(source, target));
166 }
167 
168 static inline void *
169 mem_maybedup(void *source, size_t length) {
170 	void *copy;
171 
172 	copy = malloc(length);
173 	if (copy != NULL)
174 		memmove(copy, source, length);
175 
176 	return (copy);
177 }
178 
179 static inline isc_result_t
180 typemap_totext(isc_region_t *sr, dns_rdata_textctx_t *tctx,
181 	       isc_buffer_t *target)
182 {
183 	unsigned int i, j, k;
184 	unsigned int window, len;
185 	int first = 1;
186 
187 	for (i = 0; i < sr->length; i += len) {
188 		if (tctx != NULL &&
189 		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
190 			RETERR(isc_str_tobuffer(tctx->linebreak, target));
191 			first = 1;
192 		}
193 		INSIST(i + 2 <= sr->length);
194 		window = sr->base[i];
195 		len = sr->base[i + 1];
196 		INSIST(len > 0 && len <= 32);
197 		i += 2;
198 		INSIST(i + len <= sr->length);
199 		for (j = 0; j < len; j++) {
200 			dns_rdatatype_t t;
201 			if (sr->base[i + j] == 0)
202 				continue;
203 			for (k = 0; k < 8; k++) {
204 				if ((sr->base[i + j] & (0x80 >> k)) == 0)
205 					continue;
206 				t = window * 256 + j * 8 + k;
207 				if (!first)
208 					RETERR(isc_str_tobuffer(" ", target));
209 				first = 0;
210 				RETERR(dns_rdatatype_totext(t, target));
211 			}
212 		}
213 	}
214 	return (ISC_R_SUCCESS);
215 }
216 
217 static isc_result_t
218 typemap_test(isc_region_t *sr, int allow_empty) {
219 	unsigned int window, lastwindow = 0;
220 	unsigned int len;
221 	int first = 1;
222 	unsigned int i;
223 
224 	for (i = 0; i < sr->length; i += len) {
225 		/*
226 		 * Check for overflow.
227 		 */
228 		if (i + 2 > sr->length)
229 			return (DNS_R_FORMERR);
230 		window = sr->base[i];
231 		len = sr->base[i + 1];
232 		i += 2;
233 		/*
234 		 * Check that bitmap windows are in the correct order.
235 		 */
236 		if (!first && window <= lastwindow)
237 			return (DNS_R_FORMERR);
238 		/*
239 		 * Check for legal lengths.
240 		 */
241 		if (len < 1 || len > 32)
242 			return (DNS_R_FORMERR);
243 		/*
244 		 * Check for overflow.
245 		 */
246 		if (i + len > sr->length)
247 			return (DNS_R_FORMERR);
248 		/*
249 		 * The last octet of the bitmap must be non zero.
250 		 */
251 		if (sr->base[i + len - 1] == 0)
252 			return (DNS_R_FORMERR);
253 		lastwindow = window;
254 		first = 0;
255 	}
256 	if (i != sr->length)
257 		return (DNS_R_EXTRADATA);
258 	if (!allow_empty && first)
259 		return (DNS_R_FORMERR);
260 	return (ISC_R_SUCCESS);
261 }
262 
263 static const char decdigits[] = "0123456789";
264 
265 #include "code.h"
266 
267 /***
268  *** Initialization
269  ***/
270 
271 void
272 dns_rdata_init(dns_rdata_t *rdata) {
273 
274 	REQUIRE(rdata != NULL);
275 
276 	rdata->data = NULL;
277 	rdata->length = 0;
278 	rdata->rdclass = 0;
279 	rdata->type = 0;
280 	rdata->flags = 0;
281 	ISC_LINK_INIT(rdata, link);
282 	/* ISC_LIST_INIT(rdata->list); */
283 }
284 
285 void
286 dns_rdata_reset(dns_rdata_t *rdata) {
287 
288 	REQUIRE(rdata != NULL);
289 
290 	REQUIRE(!ISC_LINK_LINKED(rdata, link));
291 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
292 
293 	rdata->data = NULL;
294 	rdata->length = 0;
295 	rdata->rdclass = 0;
296 	rdata->type = 0;
297 	rdata->flags = 0;
298 }
299 
300 /***
301  ***
302  ***/
303 
304 void
305 dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
306 
307 	REQUIRE(src != NULL);
308 	REQUIRE(target != NULL);
309 
310 	REQUIRE(DNS_RDATA_INITIALIZED(target));
311 
312 	REQUIRE(DNS_RDATA_VALIDFLAGS(src));
313 	REQUIRE(DNS_RDATA_VALIDFLAGS(target));
314 
315 	target->data = src->data;
316 	target->length = src->length;
317 	target->rdclass = src->rdclass;
318 	target->type = src->type;
319 	target->flags = src->flags;
320 }
321 
322 /***
323  *** Conversions
324  ***/
325 
326 void
327 dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
328 		     dns_rdatatype_t type, isc_region_t *r)
329 {
330 
331 	REQUIRE(rdata != NULL);
332 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
333 	REQUIRE(r != NULL);
334 
335 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
336 
337 	rdata->data = r->base;
338 	rdata->length = r->length;
339 	rdata->rdclass = rdclass;
340 	rdata->type = type;
341 	rdata->flags = 0;
342 }
343 
344 void
345 dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
346 
347 	REQUIRE(rdata != NULL);
348 	REQUIRE(r != NULL);
349 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
350 
351 	r->base = rdata->data;
352 	r->length = rdata->length;
353 }
354 
355 isc_result_t
356 dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
357 		   dns_rdatatype_t type, isc_buffer_t *source,
358 		   dns_decompress_t *dctx, unsigned int options,
359 		   isc_buffer_t *target)
360 {
361 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
362 	isc_region_t region;
363 	isc_buffer_t ss;
364 	isc_buffer_t st;
365 	int use_default = 0;
366 	uint32_t activelength;
367 	unsigned int length;
368 
369 	REQUIRE(dctx != NULL);
370 	if (rdata != NULL) {
371 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
372 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
373 	}
374 	REQUIRE(source != NULL);
375 	REQUIRE(target != NULL);
376 
377 	if (type == 0)
378 		return (DNS_R_FORMERR);
379 
380 	ss = *source;
381 	st = *target;
382 
383 	activelength = isc_buffer_activelength(source);
384 	INSIST(activelength < 65536);
385 
386 	FROMWIRESWITCH
387 
388 	if (use_default) {
389 		if (activelength > isc_buffer_availablelength(target))
390 			result = ISC_R_NOSPACE;
391 		else {
392 			isc_buffer_putmem(target, isc_buffer_current(source),
393 					  activelength);
394 			isc_buffer_forward(source, activelength);
395 			result = ISC_R_SUCCESS;
396 		}
397 	}
398 
399 	/*
400 	 * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH
401 	 * as we cannot transmit it.
402 	 */
403 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
404 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
405 		result = DNS_R_FORMERR;
406 
407 	/*
408 	 * We should have consumed all of our buffer.
409 	 */
410 	if (result == ISC_R_SUCCESS && !buffer_empty(source))
411 		result = DNS_R_EXTRADATA;
412 
413 	if (rdata != NULL && result == ISC_R_SUCCESS) {
414 		region.base = isc_buffer_used(&st);
415 		region.length = length;
416 		dns_rdata_fromregion(rdata, rdclass, type, &region);
417 	}
418 
419 	if (result != ISC_R_SUCCESS) {
420 		*source = ss;
421 		*target = st;
422 	}
423 	return (result);
424 }
425 
426 isc_result_t
427 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
428 		 isc_buffer_t *target)
429 {
430 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
431 	int use_default = 0;
432 	isc_region_t tr;
433 	isc_buffer_t st;
434 
435 	REQUIRE(rdata != NULL);
436 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
437 
438 	/*
439 	 * Some DynDNS meta-RRs have empty rdata.
440 	 */
441 	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
442 		INSIST(rdata->length == 0);
443 		return (ISC_R_SUCCESS);
444 	}
445 
446 	st = *target;
447 
448 	TOWIRESWITCH
449 
450 	if (use_default) {
451 		isc_buffer_availableregion(target, &tr);
452 		if (tr.length < rdata->length)
453 			return (ISC_R_NOSPACE);
454 		memmove(tr.base, rdata->data, rdata->length);
455 		isc_buffer_add(target, rdata->length);
456 		return (ISC_R_SUCCESS);
457 	}
458 	if (result != ISC_R_SUCCESS) {
459 		*target = st;
460 		INSIST(target->used < 65536);
461 		dns_compress_rollback(cctx, (uint16_t)target->used);
462 	}
463 	return (result);
464 }
465 
466 static isc_result_t
467 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
468 	       isc_buffer_t *target)
469 {
470 	isc_result_t result;
471 	char buf[sizeof("65535")];
472 	isc_region_t sr;
473 
474 	strlcpy(buf, "\\# ", sizeof(buf));
475 	result = isc_str_tobuffer(buf, target);
476 	if (result != ISC_R_SUCCESS)
477 		return (result);
478 
479 	dns_rdata_toregion(rdata, &sr);
480 	INSIST(sr.length < 65536);
481 	snprintf(buf, sizeof(buf), "%u", sr.length);
482 	result = isc_str_tobuffer(buf, target);
483 	if (result != ISC_R_SUCCESS)
484 		return (result);
485 
486 	if (sr.length != 0U) {
487 		if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
488 			result = isc_str_tobuffer(" ( ", target);
489 		else
490 			result = isc_str_tobuffer(" ", target);
491 
492 		if (result != ISC_R_SUCCESS)
493 			return (result);
494 
495 		if (tctx->width == 0) /* No splitting */
496 			result = isc_hex_totext(&sr, 0, "", target);
497 		else
498 			result = isc_hex_totext(&sr, tctx->width - 2,
499 						tctx->linebreak,
500 						target);
501 		if (result == ISC_R_SUCCESS &&
502 		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
503 			result = isc_str_tobuffer(" )", target);
504 	}
505 	return (result);
506 }
507 
508 static isc_result_t
509 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
510 	     isc_buffer_t *target)
511 {
512 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
513 	int use_default = 0;
514 	unsigned int cur;
515 
516 	REQUIRE(rdata != NULL);
517 	REQUIRE(tctx->origin == NULL ||	dns_name_isabsolute(tctx->origin));
518 
519 	/*
520 	 * Some DynDNS meta-RRs have empty rdata.
521 	 */
522 	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
523 		INSIST(rdata->length == 0);
524 		return (ISC_R_SUCCESS);
525 	}
526 
527 	cur = isc_buffer_usedlength(target);
528 
529 	TOTEXTSWITCH
530 
531 	if (use_default || (result == ISC_R_NOTIMPLEMENTED)) {
532 		unsigned int u = isc_buffer_usedlength(target);
533 
534 		INSIST(u >= cur);
535 		isc_buffer_subtract(target, u - cur);
536 		result = unknown_totext(rdata, tctx, target);
537 	}
538 
539 	return (result);
540 }
541 
542 isc_result_t
543 dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
544 {
545 	dns_rdata_textctx_t tctx;
546 
547 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
548 
549 	/*
550 	 * Set up formatting options for single-line output.
551 	 */
552 	tctx.origin = origin;
553 	tctx.flags = 0;
554 	tctx.width = 60;
555 	tctx.linebreak = " ";
556 	return (rdata_totext(rdata, &tctx, target));
557 }
558 
559 isc_result_t
560 dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
561 		    unsigned int flags, unsigned int width,
562 		    unsigned int split_width, const char *linebreak,
563 		    isc_buffer_t *target)
564 {
565 	dns_rdata_textctx_t tctx;
566 
567 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
568 
569 	/*
570 	 * Set up formatting options for formatted output.
571 	 */
572 	tctx.origin = origin;
573 	tctx.flags = flags;
574 	if (split_width == 0xffffffff)
575 		tctx.width = width;
576 	else
577 		tctx.width = split_width;
578 
579 	if ((flags & DNS_STYLEFLAG_MULTILINE) != 0)
580 		tctx.linebreak = linebreak;
581 	else {
582 		if (split_width == 0xffffffff)
583 			tctx.width = 60; /* Used for hex word length only. */
584 		tctx.linebreak = " ";
585 	}
586 	return (rdata_totext(rdata, &tctx, target));
587 }
588 
589 isc_result_t
590 dns_rdata_fromstruct_soa(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
591 		     dns_rdatatype_t type, dns_rdata_soa_t *soa,
592 		     isc_buffer_t *target)
593 {
594 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
595 	isc_buffer_t st;
596 	isc_region_t region;
597 	unsigned int length;
598 
599 	REQUIRE(soa != NULL);
600 	if (rdata != NULL) {
601 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
602 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
603 	}
604 
605 	st = *target;
606 	result = fromstruct_soa(rdclass, type, soa, target);
607 
608 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
609 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
610 		result = ISC_R_NOSPACE;
611 
612 	if (rdata != NULL && result == ISC_R_SUCCESS) {
613 		region.base = isc_buffer_used(&st);
614 		region.length = length;
615 		dns_rdata_fromregion(rdata, rdclass, type, &region);
616 	}
617 	if (result != ISC_R_SUCCESS)
618 		*target = st;
619 	return (result);
620 }
621 
622 isc_result_t
623 dns_rdata_fromstruct_tsig(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
624 		     dns_rdatatype_t type, dns_rdata_any_tsig_t *tsig,
625 		     isc_buffer_t *target)
626 {
627 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
628 	isc_buffer_t st;
629 	isc_region_t region;
630 	unsigned int length;
631 
632 	REQUIRE(tsig != NULL);
633 	if (rdata != NULL) {
634 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
635 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
636 	}
637 
638 	st = *target;
639 	result = fromstruct_any_tsig(rdclass, type, tsig, target);
640 
641 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
642 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
643 		result = ISC_R_NOSPACE;
644 
645 	if (rdata != NULL && result == ISC_R_SUCCESS) {
646 		region.base = isc_buffer_used(&st);
647 		region.length = length;
648 		dns_rdata_fromregion(rdata, rdclass, type, &region);
649 	}
650 	if (result != ISC_R_SUCCESS)
651 		*target = st;
652 	return (result);
653 }
654 
655 isc_result_t
656 dns_rdata_tostruct_cname(const dns_rdata_t *rdata, dns_rdata_cname_t *cname) {
657 	REQUIRE(rdata != NULL);
658 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
659 
660 	return (tostruct_cname(rdata, cname));
661 }
662 
663 isc_result_t
664 dns_rdata_tostruct_ns(const dns_rdata_t *rdata, dns_rdata_ns_t *ns) {
665 	REQUIRE(rdata != NULL);
666 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
667 
668 	return (tostruct_ns(rdata, ns));
669 }
670 
671 isc_result_t
672 dns_rdata_tostruct_soa(const dns_rdata_t *rdata, dns_rdata_soa_t *soa) {
673 	REQUIRE(rdata != NULL);
674 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
675 
676 	return (tostruct_soa(rdata, soa));
677 }
678 
679 isc_result_t
680 dns_rdata_tostruct_tsig(const dns_rdata_t *rdata, dns_rdata_any_tsig_t *tsig) {
681 	REQUIRE(rdata != NULL);
682 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
683 
684 	return (tostruct_any_tsig(rdata, tsig));
685 }
686 
687 void
688 dns_rdata_freestruct_cname(dns_rdata_cname_t *cname) {
689 	REQUIRE(cname != NULL);
690 
691 	freestruct_cname(cname);
692 }
693 
694 void
695 dns_rdata_freestruct_ns(dns_rdata_ns_t *ns) {
696 	REQUIRE(ns != NULL);
697 
698 	freestruct_ns(ns);
699 }
700 
701 void
702 dns_rdata_freestruct_soa(dns_rdata_soa_t *soa) {
703 	REQUIRE(soa != NULL);
704 
705 	freestruct_soa(soa);
706 }
707 
708 void
709 dns_rdata_freestruct_tsig(dns_rdata_any_tsig_t *tsig) {
710 	REQUIRE(tsig != NULL);
711 
712 	freestruct_any_tsig(tsig);
713 }
714 
715 int
716 dns_rdata_checkowner_nsec3(dns_name_t *name, dns_rdataclass_t rdclass,
717 		     dns_rdatatype_t type, int wildcard)
718 {
719 	return checkowner_nsec3(name, rdclass, type, wildcard);
720 }
721 
722 unsigned int
723 dns_rdatatype_attributes(dns_rdatatype_t type)
724 {
725 	switch (type) {
726 	case 0:
727 	case 31:
728 	case 32:
729 	case 34:
730 	case 100:
731 	case 101:
732 	case 102:
733 		return (DNS_RDATATYPEATTR_RESERVED);
734 	default:
735 		return (0);
736 	}
737 }
738 
739 static int
740 type_cmp(const void *k, const void *e)
741 {
742 	return (strcasecmp(k, ((const dns_rdata_type_lookup_t *)e)->type));
743 }
744 
745 isc_result_t
746 dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
747 	/* This has to be sorted always. */
748 	static const dns_rdata_type_lookup_t type_lookup[] = {
749 		{"a",		1},
750 		{"a6",		38},
751 		{"aaaa",	28},
752 		{"afsdb",	18},
753 		{"any",		255},
754 		{"apl",		42},
755 		{"atma",	34},
756 		{"avc",		258},
757 		{"axfr",	252},
758 		{"caa",		257},
759 		{"cdnskey",	60},
760 		{"cds",		59},
761 		{"cert",	37},
762 		{"cname",	5},
763 		{"csync",	62},
764 		{"dhcid",	49},
765 		{"dlv",		32769},
766 		{"dname",	39},
767 		{"dnskey",	48},
768 		{"doa",		259},
769 		{"ds",		43},
770 		{"eid",		31},
771 		{"eui48",	108},
772 		{"eui64",	109},
773 		{"gid",		102},
774 		{"gpos",	27},
775 		{"hinfo",	13},
776 		{"hip",		55},
777 		{"https",	65},
778 		{"ipseckey",	45},
779 		{"isdn",	20},
780 		{"ixfr",	251},
781 		{"key",		25},
782 		{"keydata",	65533},
783 		{"kx",		36},
784 		{"l32",		105},
785 		{"l64",		106},
786 		{"loc",		29},
787 		{"lp",		107},
788 		{"maila",	254},
789 		{"mailb",	253},
790 		{"mb",		7},
791 		{"md",		3},
792 		{"mf",		4},
793 		{"mg",		8},
794 		{"minfo",	14},
795 		{"mr",		9},
796 		{"mx",		15},
797 		{"naptr",	35},
798 		{"nid",		104},
799 		{"nimloc",	32},
800 		{"ninfo",	56},
801 		{"ns",		2},
802 		{"nsap",	22},
803 		{"nsap-ptr",	23},
804 		{"nsec",	47},
805 		{"nsec3",	50},
806 		{"nsec3param",	51},
807 		{"null",	10},
808 		{"nxt",		30},
809 		{"openpgpkey",	61},
810 		{"opt",		41},
811 		{"ptr",		12},
812 		{"px",		26},
813 		{"reserved0",	0},
814 		{"rkey",	57},
815 		{"rp",		17},
816 		{"rrsig",	46},
817 		{"rt",		21},
818 		{"sig",		24},
819 		{"sink",	40},
820 		{"smimea",	53},
821 		{"soa",		6},
822 		{"spf",		99},
823 		{"srv",		33},
824 		{"sshfp",	44},
825 		{"svcb",	64},
826 		{"ta",		32768},
827 		{"talink",	58},
828 		{"tkey",	249},
829 		{"tlsa",	52},
830 		{"tsig",	250},
831 		{"txt",		16},
832 		{"uid",		101},
833 		{"uinfo",	100},
834 		{"unspec",	103},
835 		{"uri",		256},
836 		{"wks",		11},
837 		{"x25",		19},
838 		{"zonemd",	63},
839 	};
840 	const dns_rdata_type_lookup_t *p;
841 	unsigned int n;
842 	char lookup[sizeof("nsec3param")];
843 
844 	n = source->length;
845 
846 	if (n == 0)
847 		return (DNS_R_UNKNOWN);
848 
849 	/* source->base is not required to be NUL terminated. */
850 	if ((size_t)snprintf(lookup, sizeof(lookup), "%.*s", n, source->base)
851 	    >= sizeof(lookup))
852 		return (DNS_R_UNKNOWN);
853 
854 	p = bsearch(lookup, type_lookup,
855 	    sizeof(type_lookup)/sizeof(type_lookup[0]), sizeof(type_lookup[0]),
856 	    type_cmp);
857 
858 	if (p) {
859 		if ((dns_rdatatype_attributes(p->val) &
860 		    DNS_RDATATYPEATTR_RESERVED) != 0)
861 			return (ISC_R_NOTIMPLEMENTED);
862 		*typep = p->val;
863 		return (ISC_R_SUCCESS);
864 	}
865 
866 	if (n > 4 && strncasecmp("type", lookup, 4) == 0) {
867 		int val;
868 		const char *errstr;
869 		val = strtonum(lookup + 4, 0, UINT16_MAX, &errstr);
870 		if (errstr == NULL) {
871 			*typep = val;
872 			return (ISC_R_SUCCESS);
873 		}
874 	}
875 
876 	return (DNS_R_UNKNOWN);
877 }
878 
879 isc_result_t
880 dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
881 	char buf[sizeof("TYPE65535")];
882 
883 	switch (type) {
884 	case 0:
885 		return (isc_str_tobuffer("RESERVED0", target));
886 	case 1:
887 		return (isc_str_tobuffer("A", target));
888 	case 2:
889 		return (isc_str_tobuffer("NS", target));
890 	case 3:
891 		return (isc_str_tobuffer("MD", target));
892 	case 4:
893 		return (isc_str_tobuffer("MF", target));
894 	case 5:
895 		return (isc_str_tobuffer("CNAME", target));
896 	case 6:
897 		return (isc_str_tobuffer("SOA", target));
898 	case 7:
899 		return (isc_str_tobuffer("MB", target));
900 	case 8:
901 		return (isc_str_tobuffer("MG", target));
902 	case 9:
903 		return (isc_str_tobuffer("MR", target));
904 	case 10:
905 		return (isc_str_tobuffer("NULL", target));
906 	case 11:
907 		return (isc_str_tobuffer("WKS", target));
908 	case 12:
909 		return (isc_str_tobuffer("PTR", target));
910 	case 13:
911 		return (isc_str_tobuffer("HINFO", target));
912 	case 14:
913 		return (isc_str_tobuffer("MINFO", target));
914 	case 15:
915 		return (isc_str_tobuffer("MX", target));
916 	case 16:
917 		return (isc_str_tobuffer("TXT", target));
918 	case 17:
919 		return (isc_str_tobuffer("RP", target));
920 	case 18:
921 		return (isc_str_tobuffer("AFSDB", target));
922 	case 19:
923 		return (isc_str_tobuffer("X25", target));
924 	case 20:
925 		return (isc_str_tobuffer("ISDN", target));
926 	case 21:
927 		return (isc_str_tobuffer("RT", target));
928 	case 22:
929 		return (isc_str_tobuffer("NSAP", target));
930 	case 23:
931 		return (isc_str_tobuffer("NSAP-PTR", target));
932 	case 24:
933 		return (isc_str_tobuffer("SIG", target));
934 	case 25:
935 		return (isc_str_tobuffer("KEY", target));
936 	case 26:
937 		return (isc_str_tobuffer("PX", target));
938 	case 27:
939 		return (isc_str_tobuffer("GPOS", target));
940 	case 28:
941 		return (isc_str_tobuffer("AAAA", target));
942 	case 29:
943 		return (isc_str_tobuffer("LOC", target));
944 	case 30:
945 		return (isc_str_tobuffer("NXT", target));
946 	case 31:
947 		return (isc_str_tobuffer("EID", target));
948 	case 32:
949 		return (isc_str_tobuffer("NIMLOC", target));
950 	case 33:
951 		return (isc_str_tobuffer("SRV", target));
952 	case 34:
953 		return (isc_str_tobuffer("ATMA", target));
954 	case 35:
955 		return (isc_str_tobuffer("NAPTR", target));
956 	case 36:
957 		return (isc_str_tobuffer("KX", target));
958 	case 37:
959 		return (isc_str_tobuffer("CERT", target));
960 	case 38:
961 		return (isc_str_tobuffer("A6", target));
962 	case 39:
963 		return (isc_str_tobuffer("DNAME", target));
964 	case 40:
965 		return (isc_str_tobuffer("SINK", target));
966 	case 41:
967 		return (isc_str_tobuffer("OPT", target));
968 	case 42:
969 		return (isc_str_tobuffer("APL", target));
970 	case 43:
971 		return (isc_str_tobuffer("DS", target));
972 	case 44:
973 		return (isc_str_tobuffer("SSHFP", target));
974 	case 45:
975 		return (isc_str_tobuffer("IPSECKEY", target));
976 	case 46:
977 		return (isc_str_tobuffer("RRSIG", target));
978 	case 47:
979 		return (isc_str_tobuffer("NSEC", target));
980 	case 48:
981 		return (isc_str_tobuffer("DNSKEY", target));
982 	case 49:
983 		return (isc_str_tobuffer("DHCID", target));
984 	case 50:
985 		return (isc_str_tobuffer("NSEC3", target));
986 	case 51:
987 		return (isc_str_tobuffer("NSEC3PARAM", target));
988 	case 52:
989 		return (isc_str_tobuffer("TLSA", target));
990 	case 53:
991 		return (isc_str_tobuffer("SMIMEA", target));
992 	case 55:
993 		return (isc_str_tobuffer("HIP", target));
994 	case 56:
995 		return (isc_str_tobuffer("NINFO", target));
996 	case 57:
997 		return (isc_str_tobuffer("RKEY", target));
998 	case 58:
999 		return (isc_str_tobuffer("TALINK", target));
1000 	case 59:
1001 		return (isc_str_tobuffer("CDS", target));
1002 	case 60:
1003 		return (isc_str_tobuffer("CDNSKEY", target));
1004 	case 61:
1005 		return (isc_str_tobuffer("OPENPGPKEY", target));
1006 	case 62:
1007 		return (isc_str_tobuffer("CSYNC", target));
1008 	case 63:
1009 		return (isc_str_tobuffer("ZONEMD", target));
1010 	case 64:
1011 		return (isc_str_tobuffer("SVCB", target));
1012 	case 65:
1013 		return (isc_str_tobuffer("HTTPS", target));
1014 	case 99:
1015 		return (isc_str_tobuffer("SPF", target));
1016 	case 100:
1017 		return (isc_str_tobuffer("UINFO", target));
1018 	case 101:
1019 		return (isc_str_tobuffer("UID", target));
1020 	case 102:
1021 		return (isc_str_tobuffer("GID", target));
1022 	case 103:
1023 		return (isc_str_tobuffer("UNSPEC", target));
1024 	case 104:
1025 		return (isc_str_tobuffer("NID", target));
1026 	case 105:
1027 		return (isc_str_tobuffer("L32", target));
1028 	case 106:
1029 		return (isc_str_tobuffer("L64", target));
1030 	case 107:
1031 		return (isc_str_tobuffer("LP", target));
1032 	case 108:
1033 		return (isc_str_tobuffer("EUI48", target));
1034 	case 109:
1035 		return (isc_str_tobuffer("EUI64", target));
1036 	case 249:
1037 		return (isc_str_tobuffer("TKEY", target));
1038 	case 250:
1039 		return (isc_str_tobuffer("TSIG", target));
1040 	case 251:
1041 		return (isc_str_tobuffer("IXFR", target));
1042 	case 252:
1043 		return (isc_str_tobuffer("AXFR", target));
1044 	case 253:
1045 		return (isc_str_tobuffer("MAILB", target));
1046 	case 254:
1047 		return (isc_str_tobuffer("MAILA", target));
1048 	case 255:
1049 		return (isc_str_tobuffer("ANY", target));
1050 	case 256:
1051 		return (isc_str_tobuffer("URI", target));
1052 	case 257:
1053 		return (isc_str_tobuffer("CAA", target));
1054 	case 258:
1055 		return (isc_str_tobuffer("AVC", target));
1056 	case 259:
1057 		return (isc_str_tobuffer("DOA", target));
1058 	case 32768:
1059 		return (isc_str_tobuffer("TA", target));
1060 	case 32769:
1061 		return (isc_str_tobuffer("DLV", target));
1062 	default:
1063 		snprintf(buf, sizeof(buf), "TYPE%u", type);
1064 		return (isc_str_tobuffer(buf, target));
1065 	}
1066 }
1067 
1068 void
1069 dns_rdatatype_format(dns_rdatatype_t rdtype,
1070 		     char *array, unsigned int size)
1071 {
1072 	isc_result_t result;
1073 	isc_buffer_t buf;
1074 
1075 	if (size == 0U)
1076 		return;
1077 
1078 	isc_buffer_init(&buf, array, size);
1079 	result = dns_rdatatype_totext(rdtype, &buf);
1080 	/*
1081 	 * Null terminate.
1082 	 */
1083 	if (result == ISC_R_SUCCESS) {
1084 		if (isc_buffer_availablelength(&buf) >= 1)
1085 			isc_buffer_putuint8(&buf, 0);
1086 		else
1087 			result = ISC_R_NOSPACE;
1088 	}
1089 	if (result != ISC_R_SUCCESS)
1090 		strlcpy(array, "<unknown>", size);
1091 }
1092 
1093 /*
1094  * Private function.
1095  */
1096 
1097 static unsigned int
1098 name_length(dns_name_t *name) {
1099 	return (name->length);
1100 }
1101 
1102 static isc_result_t
1103 txt_totext(isc_region_t *source, int quote, isc_buffer_t *target) {
1104 	unsigned int tl;
1105 	unsigned int n;
1106 	unsigned char *sp;
1107 	char *tp;
1108 	isc_region_t region;
1109 
1110 	isc_buffer_availableregion(target, &region);
1111 	sp = source->base;
1112 	tp = (char *)region.base;
1113 	tl = region.length;
1114 
1115 	n = *sp++;
1116 
1117 	REQUIRE(n + 1 <= source->length);
1118 	if (n == 0U)
1119 		REQUIRE(quote);
1120 
1121 	if (quote) {
1122 		if (tl < 1)
1123 			return (ISC_R_NOSPACE);
1124 		*tp++ = '"';
1125 		tl--;
1126 	}
1127 	while (n--) {
1128 		/*
1129 		 * \DDD space (0x20) if not quoting.
1130 		 */
1131 		if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) {
1132 			if (tl < 4)
1133 				return (ISC_R_NOSPACE);
1134 			*tp++ = 0x5c;
1135 			*tp++ = 0x30 + ((*sp / 100) % 10);
1136 			*tp++ = 0x30 + ((*sp / 10) % 10);
1137 			*tp++ = 0x30 + (*sp % 10);
1138 			sp++;
1139 			tl -= 4;
1140 			continue;
1141 		}
1142 		/*
1143 		 * Escape double quote and backslash.  If we are not
1144 		 * enclosing the string in double quotes also escape
1145 		 * at sign and semicolon.
1146 		 */
1147 		if (*sp == 0x22 || *sp == 0x5c ||
1148 		    (!quote && (*sp == 0x40 || *sp == 0x3b))) {
1149 			if (tl < 2)
1150 				return (ISC_R_NOSPACE);
1151 			*tp++ = '\\';
1152 			tl--;
1153 		}
1154 		if (tl < 1)
1155 			return (ISC_R_NOSPACE);
1156 		*tp++ = *sp++;
1157 		tl--;
1158 	}
1159 	if (quote) {
1160 		if (tl < 1)
1161 			return (ISC_R_NOSPACE);
1162 		*tp++ = '"';
1163 		tl--;
1164 		POST(tl);
1165 	}
1166 	isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
1167 	isc_region_consume(source, *source->base + 1);
1168 	return (ISC_R_SUCCESS);
1169 }
1170 
1171 static isc_result_t
1172 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
1173 	unsigned int n;
1174 	isc_region_t sregion;
1175 	isc_region_t tregion;
1176 
1177 	isc_buffer_activeregion(source, &sregion);
1178 	if (sregion.length == 0)
1179 		return (ISC_R_UNEXPECTEDEND);
1180 	n = *sregion.base + 1;
1181 	if (n > sregion.length)
1182 		return (ISC_R_UNEXPECTEDEND);
1183 
1184 	isc_buffer_availableregion(target, &tregion);
1185 	if (n > tregion.length)
1186 		return (ISC_R_NOSPACE);
1187 
1188 	if (tregion.base != sregion.base)
1189 		memmove(tregion.base, sregion.base, n);
1190 	isc_buffer_forward(source, n);
1191 	isc_buffer_add(target, n);
1192 	return (ISC_R_SUCCESS);
1193 }
1194 
1195 /*
1196  * Conversion of TXT-like rdata fields without length limits.
1197  */
1198 static isc_result_t
1199 multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
1200 	unsigned int tl;
1201 	unsigned int n0, n;
1202 	unsigned char *sp;
1203 	char *tp;
1204 	isc_region_t region;
1205 
1206 	isc_buffer_availableregion(target, &region);
1207 	sp = source->base;
1208 	tp = (char *)region.base;
1209 	tl = region.length;
1210 
1211 	if (tl < 1)
1212 		return (ISC_R_NOSPACE);
1213 	*tp++ = '"';
1214 	tl--;
1215 	do {
1216 		n = source->length;
1217 		n0 = source->length - 1;
1218 
1219 		while (n--) {
1220 			if (*sp < 0x20 || *sp >= 0x7f) {
1221 				if (tl < 4)
1222 					return (ISC_R_NOSPACE);
1223 				*tp++ = 0x5c;
1224 				*tp++ = 0x30 + ((*sp / 100) % 10);
1225 				*tp++ = 0x30 + ((*sp / 10) % 10);
1226 				*tp++ = 0x30 + (*sp % 10);
1227 				sp++;
1228 				tl -= 4;
1229 				continue;
1230 			}
1231 			/* double quote, backslash */
1232 			if (*sp == 0x22 || *sp == 0x5c) {
1233 				if (tl < 2)
1234 					return (ISC_R_NOSPACE);
1235 				*tp++ = '\\';
1236 				tl--;
1237 			}
1238 			if (tl < 1)
1239 				return (ISC_R_NOSPACE);
1240 			*tp++ = *sp++;
1241 			tl--;
1242 		}
1243 		isc_region_consume(source, n0 + 1);
1244 	} while (source->length != 0);
1245 	if (tl < 1)
1246 		return (ISC_R_NOSPACE);
1247 	*tp++ = '"';
1248 	tl--;
1249 	POST(tl);
1250 	isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
1251 	return (ISC_R_SUCCESS);
1252 }
1253 
1254 static int
1255 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
1256 	int l1, l2;
1257 
1258 	if (origin == NULL)
1259 		goto return_false;
1260 
1261 	if (dns_name_compare(origin, dns_rootname) == 0)
1262 		goto return_false;
1263 
1264 	if (!dns_name_issubdomain(name, origin))
1265 		goto return_false;
1266 
1267 	l1 = dns_name_countlabels(name);
1268 	l2 = dns_name_countlabels(origin);
1269 
1270 	if (l1 == l2)
1271 		goto return_false;
1272 
1273 	/* Master files should be case preserving. */
1274 	dns_name_getlabelsequence(name, l1 - l2, l2, target);
1275 	if (!dns_name_caseequal(origin, target))
1276 		goto return_false;
1277 
1278 	dns_name_getlabelsequence(name, 0, l1 - l2, target);
1279 	return (1);
1280 
1281 return_false:
1282 	*target = *name;
1283 	return (0);
1284 }
1285 
1286 static isc_result_t
1287 inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
1288 	char tmpbuf[64];
1289 
1290 	/* Note - inet_ntop doesn't do size checking on its input. */
1291 	if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
1292 		return (ISC_R_NOSPACE);
1293 	if (strlen(tmpbuf) > isc_buffer_availablelength(target))
1294 		return (ISC_R_NOSPACE);
1295 	isc_buffer_putstr(target, tmpbuf);
1296 	return (ISC_R_SUCCESS);
1297 }
1298 
1299 static int
1300 buffer_empty(isc_buffer_t *source) {
1301 	return((source->current == source->active) ? 1 : 0);
1302 }
1303 
1304 static isc_result_t
1305 uint32_tobuffer(uint32_t value, isc_buffer_t *target) {
1306 	isc_region_t region;
1307 
1308 	isc_buffer_availableregion(target, &region);
1309 	if (region.length < 4)
1310 		return (ISC_R_NOSPACE);
1311 	isc_buffer_putuint32(target, value);
1312 	return (ISC_R_SUCCESS);
1313 }
1314 
1315 static isc_result_t
1316 uint16_tobuffer(uint32_t value, isc_buffer_t *target) {
1317 	isc_region_t region;
1318 
1319 	if (value > 0xffff)
1320 		return (ISC_R_RANGE);
1321 	isc_buffer_availableregion(target, &region);
1322 	if (region.length < 2)
1323 		return (ISC_R_NOSPACE);
1324 	isc_buffer_putuint16(target, (uint16_t)value);
1325 	return (ISC_R_SUCCESS);
1326 }
1327 
1328 static isc_result_t
1329 name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
1330 	isc_region_t r;
1331 	dns_name_toregion(name, &r);
1332 	return (isc_buffer_copyregion(target, &r));
1333 }
1334 
1335 static uint32_t
1336 uint32_fromregion(isc_region_t *region) {
1337 	uint32_t value;
1338 
1339 	REQUIRE(region->length >= 4);
1340 	value = region->base[0] << 24;
1341 	value |= region->base[1] << 16;
1342 	value |= region->base[2] << 8;
1343 	value |= region->base[3];
1344 	return(value);
1345 }
1346 
1347 static uint16_t
1348 uint16_fromregion(isc_region_t *region) {
1349 
1350 	REQUIRE(region->length >= 2);
1351 
1352 	return ((region->base[0] << 8) | region->base[1]);
1353 }
1354 
1355 static uint8_t
1356 uint8_fromregion(isc_region_t *region) {
1357 
1358 	REQUIRE(region->length >= 1);
1359 
1360 	return (region->base[0]);
1361 }
1362 
1363 static uint8_t
1364 uint8_consume_fromregion(isc_region_t *region) {
1365 	uint8_t r = uint8_fromregion(region);
1366 
1367 	isc_region_consume(region, 1);
1368 	return r;
1369 }
1370 
1371 static const char atob_digits[86] =
1372 	"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
1373 	"abcdefghijklmnopqrstu";
1374 /*
1375  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
1376  * Computes the number of bytes, and three kinds of simple checksums.
1377  * Incoming bytes are collected into 32-bit words, then printed in base 85:
1378  *	exp(85,5) > exp(2,32)
1379  * The ASCII characters used are between '!' and 'u';
1380  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
1381  *
1382  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
1383  * the atob/btoa programs, released with the compress program, in mod.sources.
1384  * Modified by Mike Schwartz 8/19/86 for use in BIND.
1385  * Modified to be re-entrant 3/2/99.
1386  */
1387 
1388 struct state {
1389 	int32_t Ceor;
1390 	int32_t Csum;
1391 	int32_t Crot;
1392 	int32_t word;
1393 	int32_t bcount;
1394 };
1395 
1396 #define Ceor state->Ceor
1397 #define Csum state->Csum
1398 #define Crot state->Crot
1399 #define word state->word
1400 #define bcount state->bcount
1401 
1402 static isc_result_t	byte_btoa(int c, isc_buffer_t *, struct state *state);
1403 
1404 /*
1405  * Encode binary byte c into ASCII representation and place into *bufp,
1406  * advancing bufp.
1407  */
1408 static isc_result_t
1409 byte_btoa(int c, isc_buffer_t *target, struct state *state) {
1410 	isc_region_t tr;
1411 
1412 	isc_buffer_availableregion(target, &tr);
1413 	Ceor ^= c;
1414 	Csum += c;
1415 	Csum += 1;
1416 	if ((Crot & 0x80000000)) {
1417 		Crot <<= 1;
1418 		Crot += 1;
1419 	} else {
1420 		Crot <<= 1;
1421 	}
1422 	Crot += c;
1423 
1424 	word <<= 8;
1425 	word |= c;
1426 	if (bcount == 3) {
1427 		if (word == 0) {
1428 			if (tr.length < 1)
1429 				return (ISC_R_NOSPACE);
1430 			tr.base[0] = 'z';
1431 			isc_buffer_add(target, 1);
1432 		} else {
1433 		    register int tmp = 0;
1434 		    register int32_t tmpword = word;
1435 
1436 		    if (tmpword < 0) {
1437 			   /*
1438 			    * Because some don't support u_long.
1439 			    */
1440 			tmp = 32;
1441 			tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
1442 		    }
1443 		    if (tmpword < 0) {
1444 			tmp = 64;
1445 			tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
1446 		    }
1447 			if (tr.length < 5)
1448 				return (ISC_R_NOSPACE);
1449 			tr.base[0] = atob_digits[(tmpword /
1450 					      (int32_t)(85 * 85 * 85 * 85))
1451 						+ tmp];
1452 			tmpword %= (int32_t)(85 * 85 * 85 * 85);
1453 			tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
1454 			tmpword %= (85 * 85 * 85);
1455 			tr.base[2] = atob_digits[tmpword / (85 * 85)];
1456 			tmpword %= (85 * 85);
1457 			tr.base[3] = atob_digits[tmpword / 85];
1458 			tmpword %= 85;
1459 			tr.base[4] = atob_digits[tmpword];
1460 			isc_buffer_add(target, 5);
1461 		}
1462 		bcount = 0;
1463 	} else {
1464 		bcount += 1;
1465 	}
1466 	return (ISC_R_SUCCESS);
1467 }
1468 
1469 /*
1470  * Encode the binary data from inbuf, of length inbuflen, into a
1471  * target.  Return success/failure status
1472  */
1473 static isc_result_t
1474 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
1475 	int inc;
1476 	struct state statebuf, *state = &statebuf;
1477 	char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
1478 
1479 	Ceor = Csum = Crot = word = bcount = 0;
1480 	for (inc = 0; inc < inbuflen; inbuf++, inc++)
1481 		RETERR(byte_btoa(*inbuf, target, state));
1482 
1483 	while (bcount != 0)
1484 		RETERR(byte_btoa(0, target, state));
1485 
1486 	/*
1487 	 * Put byte count and checksum information at end of buffer,
1488 	 * delimited by 'x'
1489 	 */
1490 	snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1491 	return (isc_str_tobuffer(buf, target));
1492 }
1493 
1494 dns_rdatatype_t
1495 dns_rdata_covers(dns_rdata_t *rdata) {
1496 	if (rdata->type == dns_rdatatype_rrsig)
1497 		return (covers_rrsig(rdata));
1498 	return (covers_sig(rdata));
1499 }
1500