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.36 2024/04/23 13:34:50 jsg 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 */
73typedef 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
80typedef struct dns_rdata_type_lookup {
81	const char	*type;
82	int		 val;
83} dns_rdata_type_lookup_t;
84
85static isc_result_t
86txt_totext(isc_region_t *source, int quote, isc_buffer_t *target);
87
88static isc_result_t
89txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
90
91static isc_result_t
92multitxt_totext(isc_region_t *source, isc_buffer_t *target);
93
94static int
95name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
96
97static unsigned int
98name_length(dns_name_t *name);
99
100static isc_result_t
101inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
102
103static int
104buffer_empty(isc_buffer_t *source);
105
106static isc_result_t
107uint32_tobuffer(uint32_t, isc_buffer_t *target);
108
109static isc_result_t
110uint16_tobuffer(uint32_t, isc_buffer_t *target);
111
112static isc_result_t
113name_tobuffer(dns_name_t *name, isc_buffer_t *target);
114
115static uint32_t
116uint32_fromregion(isc_region_t *region);
117
118static uint16_t
119uint16_fromregion(isc_region_t *region);
120
121static uint8_t
122uint8_fromregion(isc_region_t *region);
123
124static uint8_t
125uint8_consume_fromregion(isc_region_t *region);
126
127static isc_result_t
128btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
129
130static isc_result_t
131rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
132	     isc_buffer_t *target);
133
134static isc_result_t
135unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
136	       isc_buffer_t *target);
137
138static inline isc_result_t
139generic_totext_key(ARGS_TOTEXT);
140
141static inline isc_result_t
142generic_fromwire_key(ARGS_FROMWIRE);
143
144static isc_result_t
145generic_totext_txt(ARGS_TOTEXT);
146
147static isc_result_t
148generic_fromwire_txt(ARGS_FROMWIRE);
149
150static isc_result_t
151generic_totext_ds(ARGS_TOTEXT);
152
153static isc_result_t
154generic_fromwire_ds(ARGS_FROMWIRE);
155
156static isc_result_t
157generic_totext_tlsa(ARGS_TOTEXT);
158
159static isc_result_t
160generic_fromwire_tlsa(ARGS_FROMWIRE);
161
162static inline isc_result_t
163name_duporclone(dns_name_t *source, dns_name_t *target) {
164
165	return (dns_name_dup(source, target));
166}
167
168static inline void *
169mem_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
179static inline isc_result_t
180typemap_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
217static isc_result_t
218typemap_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
263static const char decdigits[] = "0123456789";
264
265#include "code.h"
266
267/***
268 *** Initialization
269 ***/
270
271void
272dns_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
285void
286dns_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
304void
305dns_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
326void
327dns_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
344void
345dns_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
355isc_result_t
356dns_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
426isc_result_t
427dns_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
466static isc_result_t
467unknown_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
508static isc_result_t
509rdata_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
542isc_result_t
543dns_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
559isc_result_t
560dns_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
589isc_result_t
590dns_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
622isc_result_t
623dns_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
655isc_result_t
656dns_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
663isc_result_t
664dns_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
671isc_result_t
672dns_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
679isc_result_t
680dns_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
687void
688dns_rdata_freestruct_cname(dns_rdata_cname_t *cname) {
689	REQUIRE(cname != NULL);
690
691	freestruct_cname(cname);
692}
693
694void
695dns_rdata_freestruct_ns(dns_rdata_ns_t *ns) {
696	REQUIRE(ns != NULL);
697
698	freestruct_ns(ns);
699}
700
701void
702dns_rdata_freestruct_soa(dns_rdata_soa_t *soa) {
703	REQUIRE(soa != NULL);
704
705	freestruct_soa(soa);
706}
707
708void
709dns_rdata_freestruct_tsig(dns_rdata_any_tsig_t *tsig) {
710	REQUIRE(tsig != NULL);
711
712	freestruct_any_tsig(tsig);
713}
714
715int
716dns_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
722unsigned int
723dns_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
739static int
740type_cmp(const void *k, const void *e)
741{
742	return (strcasecmp(k, ((const dns_rdata_type_lookup_t *)e)->type));
743}
744
745isc_result_t
746dns_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
879isc_result_t
880dns_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
1068void
1069dns_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
1097static unsigned int
1098name_length(dns_name_t *name) {
1099	return (name->length);
1100}
1101
1102static isc_result_t
1103txt_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
1171static isc_result_t
1172txt_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 */
1198static isc_result_t
1199multitxt_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
1254static int
1255name_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
1281return_false:
1282	*target = *name;
1283	return (0);
1284}
1285
1286static isc_result_t
1287inet_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
1299static int
1300buffer_empty(isc_buffer_t *source) {
1301	return((source->current == source->active) ? 1 : 0);
1302}
1303
1304static isc_result_t
1305uint32_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
1315static isc_result_t
1316uint16_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
1328static isc_result_t
1329name_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
1335static uint32_t
1336uint32_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
1347static uint16_t
1348uint16_fromregion(isc_region_t *region) {
1349
1350	REQUIRE(region->length >= 2);
1351
1352	return ((region->base[0] << 8) | region->base[1]);
1353}
1354
1355static uint8_t
1356uint8_fromregion(isc_region_t *region) {
1357
1358	REQUIRE(region->length >= 1);
1359
1360	return (region->base[0]);
1361}
1362
1363static uint8_t
1364uint8_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
1371static 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
1388struct 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
1402static 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 */
1408static isc_result_t
1409byte_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)) + tmp];
1451			tmpword %= (int32_t)(85 * 85 * 85 * 85);
1452			tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
1453			tmpword %= (85 * 85 * 85);
1454			tr.base[2] = atob_digits[tmpword / (85 * 85)];
1455			tmpword %= (85 * 85);
1456			tr.base[3] = atob_digits[tmpword / 85];
1457			tmpword %= 85;
1458			tr.base[4] = atob_digits[tmpword];
1459			isc_buffer_add(target, 5);
1460		}
1461		bcount = 0;
1462	} else {
1463		bcount += 1;
1464	}
1465	return (ISC_R_SUCCESS);
1466}
1467
1468/*
1469 * Encode the binary data from inbuf, of length inbuflen, into a
1470 * target.  Return success/failure status
1471 */
1472static isc_result_t
1473btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
1474	int inc;
1475	struct state statebuf, *state = &statebuf;
1476	char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
1477
1478	Ceor = Csum = Crot = word = bcount = 0;
1479	for (inc = 0; inc < inbuflen; inbuf++, inc++)
1480		RETERR(byte_btoa(*inbuf, target, state));
1481
1482	while (bcount != 0)
1483		RETERR(byte_btoa(0, target, state));
1484
1485	/*
1486	 * Put byte count and checksum information at end of buffer,
1487	 * delimited by 'x'
1488	 */
1489	snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1490	return (isc_str_tobuffer(buf, target));
1491}
1492
1493dns_rdatatype_t
1494dns_rdata_covers(dns_rdata_t *rdata) {
1495	if (rdata->type == dns_rdatatype_rrsig)
1496		return (covers_rrsig(rdata));
1497	return (covers_sig(rdata));
1498}
1499