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