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