xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata.c (revision f3cfa6f6ce31685c6c4a758bc430e69eb99f50a4)
1 /*	$NetBSD: rdata.c,v 1.4 2019/02/24 20:01:30 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 
15 /*! \file */
16 
17 #include <config.h>
18 
19 #include <ctype.h>
20 #include <inttypes.h>
21 #include <stdbool.h>
22 
23 #include <isc/base64.h>
24 #include <isc/hex.h>
25 #include <isc/lex.h>
26 #include <isc/mem.h>
27 #include <isc/parseint.h>
28 #include <isc/print.h>
29 #include <isc/string.h>
30 #include <isc/util.h>
31 
32 #include <dns/callbacks.h>
33 #include <dns/cert.h>
34 #include <dns/compress.h>
35 #include <dns/dsdigest.h>
36 #include <dns/enumtype.h>
37 #include <dns/keyflags.h>
38 #include <dns/keyvalues.h>
39 #include <dns/message.h>
40 #include <dns/rcode.h>
41 #include <dns/rdata.h>
42 #include <dns/rdataclass.h>
43 #include <dns/rdatastruct.h>
44 #include <dns/rdatatype.h>
45 #include <dns/result.h>
46 #include <dns/secalg.h>
47 #include <dns/secproto.h>
48 #include <dns/time.h>
49 #include <dns/ttl.h>
50 
51 #define RETERR(x) \
52 	do { \
53 		isc_result_t _r = (x); \
54 		if (_r != ISC_R_SUCCESS) \
55 			return (_r); \
56 	} while (/*CONSTCOND*/0)
57 
58 #define RETTOK(x) \
59 	do { \
60 		isc_result_t _r = (x); \
61 		if (_r != ISC_R_SUCCESS) { \
62 			isc_lex_ungettoken(lexer, &token); \
63 			return (_r); \
64 		} \
65 	} while (/*CONSTCOND*/0)
66 
67 #define CHECK(op)						\
68 	do { result = (op);					\
69 		if (result != ISC_R_SUCCESS) goto cleanup;	\
70 	} while (0)
71 
72 #define CHECKTOK(op)						\
73 	do { result = (op);					\
74 		if (result != ISC_R_SUCCESS) {			\
75 			isc_lex_ungettoken(lexer, &token);	\
76 			goto cleanup;				\
77 		}						\
78 	} while (0)
79 
80 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
81 
82 #define ARGS_FROMTEXT	int rdclass, dns_rdatatype_t type, \
83 			isc_lex_t *lexer, const dns_name_t *origin, \
84 			unsigned int options, isc_buffer_t *target, \
85 			dns_rdatacallbacks_t *callbacks
86 
87 #define ARGS_TOTEXT	dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
88 			isc_buffer_t *target
89 
90 #define ARGS_FROMWIRE	int rdclass, dns_rdatatype_t type, \
91 			isc_buffer_t *source, dns_decompress_t *dctx, \
92 			unsigned int options, isc_buffer_t *target
93 
94 #define ARGS_TOWIRE	dns_rdata_t *rdata, dns_compress_t *cctx, \
95 			isc_buffer_t *target
96 
97 #define ARGS_COMPARE	const dns_rdata_t *rdata1, const dns_rdata_t *rdata2
98 
99 #define ARGS_FROMSTRUCT	int rdclass, dns_rdatatype_t type, \
100 			void *source, isc_buffer_t *target
101 
102 #define ARGS_TOSTRUCT	const dns_rdata_t *rdata, void *target, isc_mem_t *mctx
103 
104 #define ARGS_FREESTRUCT void *source
105 
106 #define ARGS_ADDLDATA	dns_rdata_t *rdata, dns_additionaldatafunc_t add, \
107 			void *arg
108 
109 #define ARGS_DIGEST	dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg
110 
111 #define ARGS_CHECKOWNER const dns_name_t *name, dns_rdataclass_t rdclass, \
112 			dns_rdatatype_t type, bool wildcard
113 
114 #define ARGS_CHECKNAMES dns_rdata_t *rdata, const dns_name_t *owner, \
115 			dns_name_t *bad
116 
117 
118 /*%
119  * Context structure for the totext_ functions.
120  * Contains formatting options for rdata-to-text
121  * conversion.
122  */
123 typedef struct dns_rdata_textctx {
124 	const dns_name_t *origin;	/*%< Current origin, or NULL. */
125 	dns_masterstyle_flags_t flags;	/*%< DNS_STYLEFLAG_*  */
126 	unsigned int width;	/*%< Width of rdata column. */
127 	const char *linebreak;	/*%< Line break string. */
128 } dns_rdata_textctx_t;
129 
130 static isc_result_t
131 txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target);
132 
133 static isc_result_t
134 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
135 
136 static isc_result_t
137 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
138 
139 static isc_result_t
140 multitxt_totext(isc_region_t *source, isc_buffer_t *target);
141 
142 static isc_result_t
143 multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
144 
145 static bool
146 name_prefix(dns_name_t *name, const dns_name_t *origin, dns_name_t *target);
147 
148 static unsigned int
149 name_length(const dns_name_t *name);
150 
151 static isc_result_t
152 str_totext(const char *source, isc_buffer_t *target);
153 
154 static isc_result_t
155 inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
156 
157 static bool
158 buffer_empty(isc_buffer_t *source);
159 
160 static void
161 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);
162 
163 static isc_result_t
164 uint32_tobuffer(uint32_t, isc_buffer_t *target);
165 
166 static isc_result_t
167 uint16_tobuffer(uint32_t, isc_buffer_t *target);
168 
169 static isc_result_t
170 uint8_tobuffer(uint32_t, isc_buffer_t *target);
171 
172 static isc_result_t
173 name_tobuffer(const dns_name_t *name, isc_buffer_t *target);
174 
175 static uint32_t
176 uint32_fromregion(isc_region_t *region);
177 
178 static uint16_t
179 uint16_fromregion(isc_region_t *region);
180 
181 static uint8_t
182 uint8_fromregion(isc_region_t *region);
183 
184 static uint8_t
185 uint8_consume_fromregion(isc_region_t *region);
186 
187 static isc_result_t
188 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
189 
190 static int
191 hexvalue(char value);
192 
193 static int
194 decvalue(char value);
195 
196 static isc_result_t
197 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
198 
199 static isc_result_t
200 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);
201 
202 static void
203 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...)
204      ISC_FORMAT_PRINTF(2, 3);
205 
206 static void
207 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
208 	       dns_rdatacallbacks_t *callbacks, const char *name,
209 	       unsigned long line, isc_token_t *token, isc_result_t result);
210 
211 static void
212 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);
213 
214 static isc_result_t
215 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
216 	     isc_buffer_t *target);
217 
218 static void
219 warn_badname(const dns_name_t *name, isc_lex_t *lexer,
220 	     dns_rdatacallbacks_t *callbacks);
221 
222 static void
223 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
224 	   dns_rdatacallbacks_t *callbacks);
225 
226 static uint16_t
227 uint16_consume_fromregion(isc_region_t *region);
228 
229 static isc_result_t
230 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
231 	       isc_buffer_t *target);
232 
233 static inline isc_result_t
234 generic_fromtext_key(ARGS_FROMTEXT);
235 
236 static inline isc_result_t
237 generic_totext_key(ARGS_TOTEXT);
238 
239 static inline isc_result_t
240 generic_fromwire_key(ARGS_FROMWIRE);
241 
242 static inline isc_result_t
243 generic_fromstruct_key(ARGS_FROMSTRUCT);
244 
245 static inline isc_result_t
246 generic_tostruct_key(ARGS_TOSTRUCT);
247 
248 static inline void
249 generic_freestruct_key(ARGS_FREESTRUCT);
250 
251 static isc_result_t
252 generic_fromtext_txt(ARGS_FROMTEXT);
253 
254 static isc_result_t
255 generic_totext_txt(ARGS_TOTEXT);
256 
257 static isc_result_t
258 generic_fromwire_txt(ARGS_FROMWIRE);
259 
260 static isc_result_t
261 generic_fromstruct_txt(ARGS_FROMSTRUCT);
262 
263 static isc_result_t
264 generic_tostruct_txt(ARGS_TOSTRUCT);
265 
266 static void
267 generic_freestruct_txt(ARGS_FREESTRUCT);
268 
269 static isc_result_t
270 generic_txt_first(dns_rdata_txt_t *txt);
271 
272 static isc_result_t
273 generic_txt_next(dns_rdata_txt_t *txt);
274 
275 static isc_result_t
276 generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string);
277 
278 static isc_result_t
279 generic_totext_ds(ARGS_TOTEXT);
280 
281 static isc_result_t
282 generic_tostruct_ds(ARGS_TOSTRUCT);
283 
284 static isc_result_t
285 generic_fromtext_ds(ARGS_FROMTEXT);
286 
287 static isc_result_t
288 generic_fromwire_ds(ARGS_FROMWIRE);
289 
290 static isc_result_t
291 generic_fromstruct_ds(ARGS_FROMSTRUCT);
292 
293 static isc_result_t
294 generic_fromtext_tlsa(ARGS_FROMTEXT);
295 
296 static isc_result_t
297 generic_totext_tlsa(ARGS_TOTEXT);
298 
299 static isc_result_t
300 generic_fromwire_tlsa(ARGS_FROMWIRE);
301 
302 static isc_result_t
303 generic_fromstruct_tlsa(ARGS_FROMSTRUCT);
304 
305 static isc_result_t
306 generic_tostruct_tlsa(ARGS_TOSTRUCT);
307 
308 static void
309 generic_freestruct_tlsa(ARGS_FREESTRUCT);
310 
311 /*% INT16 Size */
312 #define NS_INT16SZ	2
313 /*% IPv6 Address Size */
314 #define NS_LOCATORSZ	8
315 
316 /*
317  * Active Diretory gc._msdcs.<forest> prefix.
318  */
319 static unsigned char gc_msdcs_data[]  = "\002gc\006_msdcs";
320 static unsigned char gc_msdcs_offset [] = { 0, 3 };
321 
322 static dns_name_t const gc_msdcs =
323 	DNS_NAME_INITNONABSOLUTE(gc_msdcs_data, gc_msdcs_offset);
324 
325 /*%
326  *	convert presentation level address to network order binary form.
327  * \return
328  *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
329  * \note
330  *	(1) does not touch `dst' unless it's returning 1.
331  */
332 static inline int
333 locator_pton(const char *src, unsigned char *dst) {
334 	static const char xdigits_l[] = "0123456789abcdef",
335 			  xdigits_u[] = "0123456789ABCDEF";
336 	unsigned char tmp[NS_LOCATORSZ];
337 	unsigned char *tp = tmp, *endp;
338 	const char *xdigits;
339 	int ch, seen_xdigits;
340 	unsigned int val;
341 
342 	memset(tp, '\0', NS_LOCATORSZ);
343 	endp = tp + NS_LOCATORSZ;
344 	seen_xdigits = 0;
345 	val = 0;
346 	while ((ch = *src++) != '\0') {
347 		const char *pch;
348 
349 		pch = strchr((xdigits = xdigits_l), ch);
350 		if (pch == NULL)
351 			pch = strchr((xdigits = xdigits_u), ch);
352 		if (pch != NULL) {
353 			val <<= 4;
354 			val |= (pch - xdigits);
355 			if (++seen_xdigits > 4)
356 				return (0);
357 			continue;
358 		}
359 		if (ch == ':') {
360 			if (!seen_xdigits)
361 				return (0);
362 			if (tp + NS_INT16SZ > endp)
363 				return (0);
364 			*tp++ = (unsigned char) (val >> 8) & 0xff;
365 			*tp++ = (unsigned char) val & 0xff;
366 			seen_xdigits = 0;
367 			val = 0;
368 			continue;
369 		}
370 		return (0);
371 	}
372 	if (seen_xdigits) {
373 		if (tp + NS_INT16SZ > endp)
374 			return (0);
375 		*tp++ = (unsigned char) (val >> 8) & 0xff;
376 		*tp++ = (unsigned char) val & 0xff;
377 	}
378 	if (tp != endp)
379 		return (0);
380 	memmove(dst, tmp, NS_LOCATORSZ);
381 	return (1);
382 }
383 
384 static inline isc_result_t
385 name_duporclone(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
386 
387 	if (mctx != NULL)
388 		return (dns_name_dup(source, mctx, target));
389 	dns_name_clone(source, target);
390 	return (ISC_R_SUCCESS);
391 }
392 
393 static inline void *
394 mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
395 	void *copy;
396 
397 	if (mctx == NULL)
398 		return (source);
399 	copy = isc_mem_allocate(mctx, length);
400 	if (copy != NULL)
401 		memmove(copy, source, length);
402 
403 	return (copy);
404 }
405 
406 static inline isc_result_t
407 typemap_fromtext(isc_lex_t *lexer, isc_buffer_t *target,
408 		 bool allow_empty)
409 {
410 	isc_token_t token;
411 	unsigned char bm[8*1024]; /* 64k bits */
412 	dns_rdatatype_t covered, max_used;
413 	int octet;
414 	unsigned int max_octet, newend, end;
415 	int window;
416 	bool first = true;
417 
418 	max_used = 0;
419 	bm[0] = 0;
420 	end = 0;
421 
422 	do {
423 		RETERR(isc_lex_getmastertoken(lexer, &token,
424 					      isc_tokentype_string, true));
425 		if (token.type != isc_tokentype_string)
426 			break;
427 		RETTOK(dns_rdatatype_fromtext(&covered,
428 					      &token.value.as_textregion));
429 		if (covered > max_used) {
430 			newend = covered / 8;
431 			if (newend > end) {
432 				memset(&bm[end + 1], 0, newend - end);
433 				end = newend;
434 			}
435 			max_used = covered;
436 		}
437 		bm[covered/8] |= (0x80>>(covered%8));
438 		first = false;
439 	} while (1);
440 	isc_lex_ungettoken(lexer, &token);
441 	if (!allow_empty && first)
442 		return (DNS_R_FORMERR);
443 
444 	for (window = 0; window < 256 ; window++) {
445 		if (max_used < window * 256)
446 			break;
447 
448 		max_octet = max_used - (window * 256);
449 		if (max_octet >= 256)
450 			max_octet = 31;
451 		else
452 			max_octet /= 8;
453 
454 		/*
455 		 * Find if we have a type in this window.
456 		 */
457 		for (octet = max_octet; octet >= 0; octet--) {
458 			if (bm[window * 32 + octet] != 0)
459 				break;
460 		}
461 		if (octet < 0)
462 			continue;
463 		RETERR(uint8_tobuffer(window, target));
464 		RETERR(uint8_tobuffer(octet + 1, target));
465 		RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
466 	}
467 	return (ISC_R_SUCCESS);
468 }
469 
470 static inline isc_result_t
471 typemap_totext(isc_region_t *sr, dns_rdata_textctx_t *tctx,
472 	       isc_buffer_t *target)
473 {
474 	unsigned int i, j, k;
475 	unsigned int window, len;
476 	bool first = true;
477 
478 	for (i = 0; i < sr->length; i += len) {
479 		if (tctx != NULL &&
480 		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
481 			RETERR(str_totext(tctx->linebreak, target));
482 			first = true;
483 		}
484 		INSIST(i + 2 <= sr->length);
485 		window = sr->base[i];
486 		len = sr->base[i + 1];
487 		INSIST(len > 0 && len <= 32);
488 		i += 2;
489 		INSIST(i + len <= sr->length);
490 		for (j = 0; j < len; j++) {
491 			dns_rdatatype_t t;
492 			if (sr->base[i + j] == 0)
493 				continue;
494 			for (k = 0; k < 8; k++) {
495 				if ((sr->base[i + j] & (0x80 >> k)) == 0)
496 					continue;
497 				t = window * 256 + j * 8 + k;
498 				if (!first)
499 					RETERR(str_totext(" ", target));
500 				first = false;
501 				if (dns_rdatatype_isknown(t)) {
502 					RETERR(dns_rdatatype_totext(t, target));
503 				} else {
504 					char buf[sizeof("TYPE65535")];
505 					snprintf(buf, sizeof(buf), "TYPE%u", t);
506 					RETERR(str_totext(buf, target));
507 				}
508 			}
509 		}
510 	}
511 	return (ISC_R_SUCCESS);
512 }
513 
514 static isc_result_t
515 typemap_test(isc_region_t *sr, bool allow_empty) {
516 	unsigned int window, lastwindow = 0;
517 	unsigned int len;
518 	bool first = true;
519 	unsigned int i;
520 
521 	for (i = 0; i < sr->length; i += len) {
522 		/*
523 		 * Check for overflow.
524 		 */
525 		if (i + 2 > sr->length)
526 			RETERR(DNS_R_FORMERR);
527 		window = sr->base[i];
528 		len = sr->base[i + 1];
529 		i += 2;
530 		/*
531 		 * Check that bitmap windows are in the correct order.
532 		 */
533 		if (!first && window <= lastwindow)
534 			RETERR(DNS_R_FORMERR);
535 		/*
536 		 * Check for legal lengths.
537 		 */
538 		if (len < 1 || len > 32)
539 			RETERR(DNS_R_FORMERR);
540 		/*
541 		 * Check for overflow.
542 		 */
543 		if (i + len > sr->length)
544 			RETERR(DNS_R_FORMERR);
545 		/*
546 		 * The last octet of the bitmap must be non zero.
547 		 */
548 		if (sr->base[i + len - 1] == 0)
549 			RETERR(DNS_R_FORMERR);
550 		lastwindow = window;
551 		first = false;
552 	}
553 	if (i != sr->length)
554 		return (DNS_R_EXTRADATA);
555 	if (!allow_empty && first)
556 		RETERR(DNS_R_FORMERR);
557 	return (ISC_R_SUCCESS);
558 }
559 
560 static const char hexdigits[] = "0123456789abcdef";
561 static const char decdigits[] = "0123456789";
562 
563 #include "code.h"
564 
565 #define META 0x0001
566 #define RESERVED 0x0002
567 
568 /***
569  *** Initialization
570  ***/
571 
572 void
573 dns_rdata_init(dns_rdata_t *rdata) {
574 
575 	REQUIRE(rdata != NULL);
576 
577 	rdata->data = NULL;
578 	rdata->length = 0;
579 	rdata->rdclass = 0;
580 	rdata->type = 0;
581 	rdata->flags = 0;
582 	ISC_LINK_INIT(rdata, link);
583 	/* ISC_LIST_INIT(rdata->list); */
584 }
585 
586 void
587 dns_rdata_reset(dns_rdata_t *rdata) {
588 
589 	REQUIRE(rdata != NULL);
590 
591 	REQUIRE(!ISC_LINK_LINKED(rdata, link));
592 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
593 
594 	rdata->data = NULL;
595 	rdata->length = 0;
596 	rdata->rdclass = 0;
597 	rdata->type = 0;
598 	rdata->flags = 0;
599 }
600 
601 /***
602  ***
603  ***/
604 
605 void
606 dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
607 
608 	REQUIRE(src != NULL);
609 	REQUIRE(target != NULL);
610 
611 	REQUIRE(DNS_RDATA_INITIALIZED(target));
612 
613 	REQUIRE(DNS_RDATA_VALIDFLAGS(src));
614 	REQUIRE(DNS_RDATA_VALIDFLAGS(target));
615 
616 	target->data = src->data;
617 	target->length = src->length;
618 	target->rdclass = src->rdclass;
619 	target->type = src->type;
620 	target->flags = src->flags;
621 }
622 
623 
624 /***
625  *** Comparisons
626  ***/
627 
628 int
629 dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
630 	int result = 0;
631 	bool use_default = false;
632 
633 	REQUIRE(rdata1 != NULL);
634 	REQUIRE(rdata2 != NULL);
635 	REQUIRE(rdata1->length == 0 || rdata1->data != NULL);
636 	REQUIRE(rdata2->length == 0 || rdata2->data != NULL);
637 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
638 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
639 
640 	if (rdata1->rdclass != rdata2->rdclass)
641 		return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
642 
643 	if (rdata1->type != rdata2->type)
644 		return (rdata1->type < rdata2->type ? -1 : 1);
645 
646 	COMPARESWITCH
647 
648 	if (use_default) {
649 		isc_region_t r1;
650 		isc_region_t r2;
651 
652 		dns_rdata_toregion(rdata1, &r1);
653 		dns_rdata_toregion(rdata2, &r2);
654 		result = isc_region_compare(&r1, &r2);
655 	}
656 	return (result);
657 }
658 
659 int
660 dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
661 	int result = 0;
662 	bool use_default = false;
663 
664 	REQUIRE(rdata1 != NULL);
665 	REQUIRE(rdata2 != NULL);
666 	REQUIRE(rdata1->length == 0 || rdata1->data != NULL);
667 	REQUIRE(rdata2->length == 0 || rdata2->data != NULL);
668 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
669 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
670 
671 	if (rdata1->rdclass != rdata2->rdclass)
672 		return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
673 
674 	if (rdata1->type != rdata2->type)
675 		return (rdata1->type < rdata2->type ? -1 : 1);
676 
677 	CASECOMPARESWITCH
678 
679 	if (use_default) {
680 		isc_region_t r1;
681 		isc_region_t r2;
682 
683 		dns_rdata_toregion(rdata1, &r1);
684 		dns_rdata_toregion(rdata2, &r2);
685 		result = isc_region_compare(&r1, &r2);
686 	}
687 	return (result);
688 }
689 
690 /***
691  *** Conversions
692  ***/
693 
694 void
695 dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
696 		     dns_rdatatype_t type, isc_region_t *r)
697 {
698 
699 	REQUIRE(rdata != NULL);
700 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
701 	REQUIRE(r != NULL);
702 
703 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
704 
705 	rdata->data = r->base;
706 	rdata->length = r->length;
707 	rdata->rdclass = rdclass;
708 	rdata->type = type;
709 	rdata->flags = 0;
710 }
711 
712 void
713 dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
714 
715 	REQUIRE(rdata != NULL);
716 	REQUIRE(r != NULL);
717 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
718 
719 	r->base = rdata->data;
720 	r->length = rdata->length;
721 }
722 
723 isc_result_t
724 dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
725 		   dns_rdatatype_t type, isc_buffer_t *source,
726 		   dns_decompress_t *dctx, unsigned int options,
727 		   isc_buffer_t *target)
728 {
729 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
730 	isc_region_t region;
731 	isc_buffer_t ss;
732 	isc_buffer_t st;
733 	bool use_default = false;
734 	uint32_t activelength;
735 	unsigned int length;
736 
737 	REQUIRE(dctx != NULL);
738 	if (rdata != NULL) {
739 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
740 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
741 	}
742 	REQUIRE(source != NULL);
743 	REQUIRE(target != NULL);
744 
745 	if (type == 0)
746 		return (DNS_R_FORMERR);
747 
748 	ss = *source;
749 	st = *target;
750 
751 	activelength = isc_buffer_activelength(source);
752 	INSIST(activelength < 65536);
753 
754 	FROMWIRESWITCH
755 
756 	if (use_default) {
757 		if (activelength > isc_buffer_availablelength(target))
758 			result = ISC_R_NOSPACE;
759 		else {
760 			isc_buffer_putmem(target, isc_buffer_current(source),
761 					  activelength);
762 			isc_buffer_forward(source, activelength);
763 			result = ISC_R_SUCCESS;
764 		}
765 	}
766 
767 	/*
768 	 * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH
769 	 * as we cannot transmit it.
770 	 */
771 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
772 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
773 		result = DNS_R_FORMERR;
774 
775 	/*
776 	 * We should have consumed all of our buffer.
777 	 */
778 	if (result == ISC_R_SUCCESS && !buffer_empty(source))
779 		result = DNS_R_EXTRADATA;
780 
781 	if (rdata != NULL && result == ISC_R_SUCCESS) {
782 		region.base = isc_buffer_used(&st);
783 		region.length = length;
784 		dns_rdata_fromregion(rdata, rdclass, type, &region);
785 	}
786 
787 	if (result != ISC_R_SUCCESS) {
788 		*source = ss;
789 		*target = st;
790 	}
791 	return (result);
792 }
793 
794 isc_result_t
795 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
796 		 isc_buffer_t *target)
797 {
798 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
799 	bool use_default = false;
800 	isc_region_t tr;
801 	isc_buffer_t st;
802 
803 	REQUIRE(rdata != NULL);
804 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
805 
806 	/*
807 	 * Some DynDNS meta-RRs have empty rdata.
808 	 */
809 	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
810 		INSIST(rdata->length == 0);
811 		return (ISC_R_SUCCESS);
812 	}
813 
814 	st = *target;
815 
816 	TOWIRESWITCH
817 
818 	if (use_default) {
819 		isc_buffer_availableregion(target, &tr);
820 		if (tr.length < rdata->length)
821 			return (ISC_R_NOSPACE);
822 		memmove(tr.base, rdata->data, rdata->length);
823 		isc_buffer_add(target, rdata->length);
824 		return (ISC_R_SUCCESS);
825 	}
826 	if (result != ISC_R_SUCCESS) {
827 		*target = st;
828 		INSIST(target->used < 65536);
829 		dns_compress_rollback(cctx, (uint16_t)target->used);
830 	}
831 	return (result);
832 }
833 
834 /*
835  * If the binary data in 'src' is valid uncompressed wire format
836  * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS
837  * and copy the validated rdata to 'dest'.  Otherwise return an error.
838  */
839 static isc_result_t
840 rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
841 	    dns_rdatatype_t type)
842 {
843 	dns_decompress_t dctx;
844 	isc_result_t result;
845 
846 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
847 	isc_buffer_setactive(src, isc_buffer_usedlength(src));
848 	result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest);
849 	dns_decompress_invalidate(&dctx);
850 
851 	return (result);
852 }
853 
854 static isc_result_t
855 unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
856 		 isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target)
857 {
858 	isc_result_t result;
859 	isc_buffer_t *buf = NULL;
860 	isc_token_t token;
861 
862 	if (type == 0 || dns_rdatatype_ismeta(type))
863 		return (DNS_R_METATYPE);
864 
865 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
866 					false));
867 	if (token.value.as_ulong > 65535U)
868 		return (ISC_R_RANGE);
869 	result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
870 	if (result != ISC_R_SUCCESS)
871 		return (result);
872 
873 	if (token.value.as_ulong != 0U) {
874 		result = isc_hex_tobuffer(lexer, buf,
875 					  (unsigned int)token.value.as_ulong);
876 		if (result != ISC_R_SUCCESS) {
877 		       goto failure;
878 		}
879 		if (isc_buffer_usedlength(buf) != token.value.as_ulong) {
880 			result = ISC_R_UNEXPECTEDEND;
881 			goto failure;
882 		}
883 	}
884 
885 	if (dns_rdatatype_isknown(type)) {
886 		result = rdata_validate(buf, target, rdclass, type);
887 	} else {
888 		isc_region_t r;
889 		isc_buffer_usedregion(buf, &r);
890 		result = isc_buffer_copyregion(target, &r);
891 	}
892 	if (result != ISC_R_SUCCESS)
893 		goto failure;
894 
895 	isc_buffer_free(&buf);
896 	return (ISC_R_SUCCESS);
897 
898  failure:
899 	isc_buffer_free(&buf);
900 	return (result);
901 }
902 
903 isc_result_t
904 dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
905 		   dns_rdatatype_t type, isc_lex_t *lexer,
906 		   const dns_name_t *origin, unsigned int options,
907 		   isc_mem_t *mctx, isc_buffer_t *target,
908 		   dns_rdatacallbacks_t *callbacks)
909 {
910 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
911 	isc_region_t region;
912 	isc_buffer_t st;
913 	isc_token_t token;
914 	unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
915 				  ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
916 	char *name;
917 	unsigned long line;
918 	void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
919 	isc_result_t tresult;
920 	unsigned int length;
921 	bool unknown;
922 
923 	REQUIRE(origin == NULL || dns_name_isabsolute(origin) == true);
924 	if (rdata != NULL) {
925 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
926 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
927 	}
928 	if (callbacks != NULL) {
929 		REQUIRE(callbacks->warn != NULL);
930 		REQUIRE(callbacks->error != NULL);
931 	}
932 
933 	st = *target;
934 
935 	if (callbacks != NULL)
936 		callback = callbacks->error;
937 	else
938 		callback = default_fromtext_callback;
939 
940 	result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
941 					true);
942 	if (result != ISC_R_SUCCESS) {
943 		name = isc_lex_getsourcename(lexer);
944 		line = isc_lex_getsourceline(lexer);
945 		fromtext_error(callback, callbacks, name, line, NULL, result);
946 		return (result);
947 	}
948 
949 	unknown = false;
950 	if (token.type == isc_tokentype_string &&
951 	    strcmp(DNS_AS_STR(token), "\\#") == 0) {
952 		/*
953 		 * If this is a TXT record '\#' could be a escaped '#'.
954 		 * Look to see if the next token is a number and if so
955 		 * treat it as a unknown record format.
956 		 */
957 		if (type == dns_rdatatype_txt) {
958 			result = isc_lex_getmastertoken(lexer, &token,
959 							isc_tokentype_number,
960 							false);
961 			if (result == ISC_R_SUCCESS)
962 				isc_lex_ungettoken(lexer, &token);
963 		}
964 
965 		if (result == ISC_R_SUCCESS) {
966 			unknown = true;
967 			result = unknown_fromtext(rdclass, type, lexer,
968 						  mctx, target);
969 		} else
970 			options |= DNS_RDATA_UNKNOWNESCAPE;
971 	} else
972 		isc_lex_ungettoken(lexer, &token);
973 
974 	if (!unknown)
975 		FROMTEXTSWITCH
976 
977 	/*
978 	 * Consume to end of line / file.
979 	 * If not at end of line initially set error code.
980 	 * Call callback via fromtext_error once if there was an error.
981 	 */
982 	do {
983 		name = isc_lex_getsourcename(lexer);
984 		line = isc_lex_getsourceline(lexer);
985 		tresult = isc_lex_gettoken(lexer, lexoptions, &token);
986 		if (tresult != ISC_R_SUCCESS) {
987 			if (result == ISC_R_SUCCESS)
988 				result = tresult;
989 			if (callback != NULL)
990 				fromtext_error(callback, callbacks, name,
991 					       line, NULL, result);
992 			break;
993 		} else if (token.type != isc_tokentype_eol &&
994 			   token.type != isc_tokentype_eof) {
995 			if (result == ISC_R_SUCCESS)
996 				result = DNS_R_EXTRATOKEN;
997 			if (callback != NULL) {
998 				fromtext_error(callback, callbacks, name,
999 					       line, &token, result);
1000 				callback = NULL;
1001 			}
1002 		} else if (result != ISC_R_SUCCESS && callback != NULL) {
1003 			fromtext_error(callback, callbacks, name, line,
1004 				       &token, result);
1005 			break;
1006 		} else {
1007 			if (token.type == isc_tokentype_eof)
1008 				fromtext_warneof(lexer, callbacks);
1009 			break;
1010 		}
1011 	} while (1);
1012 
1013 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
1014 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
1015 		result = ISC_R_NOSPACE;
1016 
1017 	if (rdata != NULL && result == ISC_R_SUCCESS) {
1018 		region.base = isc_buffer_used(&st);
1019 		region.length = length;
1020 		dns_rdata_fromregion(rdata, rdclass, type, &region);
1021 	}
1022 	if (result != ISC_R_SUCCESS) {
1023 		*target = st;
1024 	}
1025 	return (result);
1026 }
1027 
1028 static isc_result_t
1029 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
1030 	       isc_buffer_t *target)
1031 {
1032 	isc_result_t result;
1033 	char buf[sizeof("65535")];
1034 	isc_region_t sr;
1035 
1036 	strlcpy(buf, "\\# ", sizeof(buf));
1037 	result = str_totext(buf, target);
1038 	if (result != ISC_R_SUCCESS)
1039 		return (result);
1040 
1041 	dns_rdata_toregion(rdata, &sr);
1042 	INSIST(sr.length < 65536);
1043 	snprintf(buf, sizeof(buf), "%u", sr.length);
1044 	result = str_totext(buf, target);
1045 	if (result != ISC_R_SUCCESS)
1046 		return (result);
1047 
1048 	if (sr.length != 0U) {
1049 		if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
1050 			result = str_totext(" ( ", target);
1051 		else
1052 			result = str_totext(" ", target);
1053 
1054 		if (result != ISC_R_SUCCESS)
1055 			return (result);
1056 
1057 		if (tctx->width == 0) /* No splitting */
1058 			result = isc_hex_totext(&sr, 0, "", target);
1059 		else
1060 			result = isc_hex_totext(&sr, tctx->width - 2,
1061 						tctx->linebreak,
1062 						target);
1063 		if (result == ISC_R_SUCCESS &&
1064 		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
1065 			result = str_totext(" )", target);
1066 	}
1067 	return (result);
1068 }
1069 
1070 static isc_result_t
1071 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
1072 	     isc_buffer_t *target)
1073 {
1074 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
1075 	bool use_default = false;
1076 	unsigned int cur;
1077 
1078 	REQUIRE(rdata != NULL);
1079 	REQUIRE(tctx->origin == NULL ||
1080 		dns_name_isabsolute(tctx->origin) == true);
1081 
1082 	/*
1083 	 * Some DynDNS meta-RRs have empty rdata.
1084 	 */
1085 	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1086 		INSIST(rdata->length == 0);
1087 		return (ISC_R_SUCCESS);
1088 	}
1089 
1090 	if ((tctx->flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0)
1091 		return (unknown_totext(rdata, tctx, target));
1092 
1093 	cur = isc_buffer_usedlength(target);
1094 
1095 	TOTEXTSWITCH
1096 
1097 	if (use_default || (result == ISC_R_NOTIMPLEMENTED)) {
1098 		unsigned int u = isc_buffer_usedlength(target);
1099 
1100 		INSIST(u >= cur);
1101 		isc_buffer_subtract(target, u - cur);
1102 		result = unknown_totext(rdata, tctx, target);
1103 	}
1104 
1105 	return (result);
1106 }
1107 
1108 isc_result_t
1109 dns_rdata_totext(dns_rdata_t *rdata, const dns_name_t *origin,
1110 		 isc_buffer_t *target)
1111 {
1112 	dns_rdata_textctx_t tctx;
1113 
1114 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
1115 
1116 	/*
1117 	 * Set up formatting options for single-line output.
1118 	 */
1119 	tctx.origin = origin;
1120 	tctx.flags = 0;
1121 	tctx.width = 60;
1122 	tctx.linebreak = " ";
1123 	return (rdata_totext(rdata, &tctx, target));
1124 }
1125 
1126 isc_result_t
1127 dns_rdata_tofmttext(dns_rdata_t *rdata, const dns_name_t *origin,
1128 		    dns_masterstyle_flags_t flags, unsigned int width,
1129 		    unsigned int split_width, const char *linebreak,
1130 		    isc_buffer_t *target)
1131 {
1132 	dns_rdata_textctx_t tctx;
1133 
1134 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
1135 
1136 	/*
1137 	 * Set up formatting options for formatted output.
1138 	 */
1139 	tctx.origin = origin;
1140 	tctx.flags = flags;
1141 	if (split_width == 0xffffffff)
1142 		tctx.width = width;
1143 	else
1144 		tctx.width = split_width;
1145 
1146 	if ((flags & DNS_STYLEFLAG_MULTILINE) != 0)
1147 		tctx.linebreak = linebreak;
1148 	else {
1149 		if (split_width == 0xffffffff)
1150 			tctx.width = 60; /* Used for hex word length only. */
1151 		tctx.linebreak = " ";
1152 	}
1153 	return (rdata_totext(rdata, &tctx, target));
1154 }
1155 
1156 isc_result_t
1157 dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
1158 		     dns_rdatatype_t type, void *source,
1159 		     isc_buffer_t *target)
1160 {
1161 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
1162 	isc_buffer_t st;
1163 	isc_region_t region;
1164 	bool use_default = false;
1165 	unsigned int length;
1166 
1167 	REQUIRE(source != NULL);
1168 	if (rdata != NULL) {
1169 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
1170 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
1171 	}
1172 
1173 	st = *target;
1174 
1175 	FROMSTRUCTSWITCH
1176 
1177 	if (use_default)
1178 		(void)NULL;
1179 
1180 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
1181 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
1182 		result = ISC_R_NOSPACE;
1183 
1184 	if (rdata != NULL && result == ISC_R_SUCCESS) {
1185 		region.base = isc_buffer_used(&st);
1186 		region.length = length;
1187 		dns_rdata_fromregion(rdata, rdclass, type, &region);
1188 	}
1189 	if (result != ISC_R_SUCCESS)
1190 		*target = st;
1191 	return (result);
1192 }
1193 
1194 isc_result_t
1195 dns_rdata_tostruct(const dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
1196 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
1197 	bool use_default = false;
1198 
1199 	REQUIRE(rdata != NULL);
1200 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
1201 
1202 	TOSTRUCTSWITCH
1203 
1204 	if (use_default)
1205 		(void)NULL;
1206 
1207 	return (result);
1208 }
1209 
1210 void
1211 dns_rdata_freestruct(void *source) {
1212 	dns_rdatacommon_t *common = source;
1213 	REQUIRE(source != NULL);
1214 
1215 	FREESTRUCTSWITCH
1216 }
1217 
1218 isc_result_t
1219 dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
1220 			 void *arg)
1221 {
1222 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
1223 	bool use_default = false;
1224 
1225 	/*
1226 	 * Call 'add' for each name and type from 'rdata' which is subject to
1227 	 * additional section processing.
1228 	 */
1229 
1230 	REQUIRE(rdata != NULL);
1231 	REQUIRE(add != NULL);
1232 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
1233 
1234 	ADDITIONALDATASWITCH
1235 
1236 	/* No additional processing for unknown types */
1237 	if (use_default)
1238 		result = ISC_R_SUCCESS;
1239 
1240 	return (result);
1241 }
1242 
1243 isc_result_t
1244 dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
1245 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
1246 	bool use_default = false;
1247 	isc_region_t r;
1248 
1249 	/*
1250 	 * Send 'rdata' in DNSSEC canonical form to 'digest'.
1251 	 */
1252 
1253 	REQUIRE(rdata != NULL);
1254 	REQUIRE(digest != NULL);
1255 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
1256 
1257 	DIGESTSWITCH
1258 
1259 	if (use_default) {
1260 		dns_rdata_toregion(rdata, &r);
1261 		result = (digest)(arg, &r);
1262 	}
1263 
1264 	return (result);
1265 }
1266 
1267 bool
1268 dns_rdata_checkowner(const dns_name_t *name, dns_rdataclass_t rdclass,
1269 		     dns_rdatatype_t type, bool wildcard)
1270 {
1271 	bool result;
1272 
1273 	CHECKOWNERSWITCH
1274 	return (result);
1275 }
1276 
1277 bool
1278 dns_rdata_checknames(dns_rdata_t *rdata, const dns_name_t *owner,
1279 		     dns_name_t *bad)
1280 {
1281 	bool result;
1282 
1283 	CHECKNAMESSWITCH
1284 	return (result);
1285 }
1286 
1287 unsigned int
1288 dns_rdatatype_attributes(dns_rdatatype_t type)
1289 {
1290 	RDATATYPE_ATTRIBUTE_SW
1291 	if (type >= (dns_rdatatype_t)128 && type < (dns_rdatatype_t)255)
1292 		return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META);
1293 	return (DNS_RDATATYPEATTR_UNKNOWN);
1294 }
1295 
1296 isc_result_t
1297 dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
1298 	unsigned int hash;
1299 	unsigned int n;
1300 	unsigned char a, b;
1301 
1302 	n = source->length;
1303 
1304 	if (n == 0)
1305 		return (DNS_R_UNKNOWN);
1306 
1307 	a = tolower((unsigned char)source->base[0]);
1308 	b = tolower((unsigned char)source->base[n - 1]);
1309 
1310 	hash = ((a + n) * b) % 256;
1311 
1312 	/*
1313 	 * This switch block is inlined via \#define, and will use "return"
1314 	 * to return a result to the caller if it is a valid (known)
1315 	 * rdatatype name.
1316 	 */
1317 	RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep);
1318 
1319 	if (source->length > 4 && source->length < (4 + sizeof("65000")) &&
1320 	    strncasecmp("type", source->base, 4) == 0) {
1321 		char buf[sizeof("65000")];
1322 		char *endp;
1323 		unsigned int val;
1324 
1325 		/*
1326 		 * source->base is not required to be NUL terminated.
1327 		 * Copy up to remaining bytes and NUL terminate.
1328 		 */
1329 		snprintf(buf, sizeof(buf), "%.*s",
1330 			 (int)(source->length - 4), source->base + 4);
1331 		val = strtoul(buf, &endp, 10);
1332 		if (*endp == '\0' && val <= 0xffff) {
1333 			*typep = (dns_rdatatype_t)val;
1334 			return (ISC_R_SUCCESS);
1335 		}
1336 	}
1337 
1338 	return (DNS_R_UNKNOWN);
1339 }
1340 
1341 isc_result_t
1342 dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
1343 	RDATATYPE_TOTEXT_SW
1344 
1345 	return (dns_rdatatype_tounknowntext(type, target));
1346 }
1347 
1348 isc_result_t
1349 dns_rdatatype_tounknowntext(dns_rdatatype_t type, isc_buffer_t *target) {
1350 	char buf[sizeof("TYPE65535")];
1351 
1352 	snprintf(buf, sizeof(buf), "TYPE%u", type);
1353 	return (str_totext(buf, target));
1354 }
1355 
1356 void
1357 dns_rdatatype_format(dns_rdatatype_t rdtype,
1358 		     char *array, unsigned int size)
1359 {
1360 	isc_result_t result;
1361 	isc_buffer_t buf;
1362 
1363 	if (size == 0U)
1364 		return;
1365 
1366 	isc_buffer_init(&buf, array, size);
1367 	result = dns_rdatatype_totext(rdtype, &buf);
1368 	/*
1369 	 * Null terminate.
1370 	 */
1371 	if (result == ISC_R_SUCCESS) {
1372 		if (isc_buffer_availablelength(&buf) >= 1)
1373 			isc_buffer_putuint8(&buf, 0);
1374 		else
1375 			result = ISC_R_NOSPACE;
1376 	}
1377 	if (result != ISC_R_SUCCESS)
1378 		strlcpy(array, "<unknown>", size);
1379 }
1380 
1381 /*
1382  * Private function.
1383  */
1384 
1385 static unsigned int
1386 name_length(const dns_name_t *name) {
1387 	return (name->length);
1388 }
1389 
1390 static isc_result_t
1391 txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target) {
1392 	unsigned int tl;
1393 	unsigned int n;
1394 	unsigned char *sp;
1395 	char *tp;
1396 	isc_region_t region;
1397 
1398 	isc_buffer_availableregion(target, &region);
1399 	sp = source->base;
1400 	tp = (char *)region.base;
1401 	tl = region.length;
1402 
1403 	n = *sp++;
1404 
1405 	REQUIRE(n + 1 <= source->length);
1406 	if (n == 0U)
1407 		REQUIRE(quote == true);
1408 
1409 	if (quote) {
1410 		if (tl < 1)
1411 			return (ISC_R_NOSPACE);
1412 		*tp++ = '"';
1413 		tl--;
1414 	}
1415 	while (n--) {
1416 		/*
1417 		 * \DDD space (0x20) if not quoting.
1418 		 */
1419 		if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) {
1420 			if (tl < 4)
1421 				return (ISC_R_NOSPACE);
1422 			*tp++ = 0x5c;
1423 			*tp++ = 0x30 + ((*sp / 100) % 10);
1424 			*tp++ = 0x30 + ((*sp / 10) % 10);
1425 			*tp++ = 0x30 + (*sp % 10);
1426 			sp++;
1427 			tl -= 4;
1428 			continue;
1429 		}
1430 		/*
1431 		 * Escape double quote and backslash.  If we are not
1432 		 * enclosing the string in double quotes also escape
1433 		 * at sign and semicolon.
1434 		 */
1435 		if (*sp == 0x22 || *sp == 0x5c ||
1436 		    (!quote && (*sp == 0x40 || *sp == 0x3b))) {
1437 			if (tl < 2)
1438 				return (ISC_R_NOSPACE);
1439 			*tp++ = '\\';
1440 			tl--;
1441 		}
1442 		if (tl < 1)
1443 			return (ISC_R_NOSPACE);
1444 		*tp++ = *sp++;
1445 		tl--;
1446 	}
1447 	if (quote) {
1448 		if (tl < 1)
1449 			return (ISC_R_NOSPACE);
1450 		*tp++ = '"';
1451 		tl--;
1452 		POST(tl);
1453 	}
1454 	isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
1455 	isc_region_consume(source, *source->base + 1);
1456 	return (ISC_R_SUCCESS);
1457 }
1458 
1459 static isc_result_t
1460 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
1461 	isc_region_t tregion;
1462 	bool escape;
1463 	unsigned int n, nrem;
1464 	char *s;
1465 	unsigned char *t;
1466 	int d;
1467 	int c;
1468 
1469 	isc_buffer_availableregion(target, &tregion);
1470 	s = source->base;
1471 	n = source->length;
1472 	t = tregion.base;
1473 	nrem = tregion.length;
1474 	escape = false;
1475 	if (nrem < 1)
1476 		return (ISC_R_NOSPACE);
1477 	/*
1478 	 * Length byte.
1479 	 */
1480 	nrem--;
1481 	t++;
1482 	/*
1483 	 * Maximum text string length.
1484 	 */
1485 	if (nrem > 255)
1486 		nrem = 255;
1487 	while (n-- != 0) {
1488 		c = (*s++) & 0xff;
1489 		if (escape && (d = decvalue((char)c)) != -1) {
1490 			c = d;
1491 			if (n == 0)
1492 				return (DNS_R_SYNTAX);
1493 			n--;
1494 			if ((d = decvalue(*s++)) != -1)
1495 				c = c * 10 + d;
1496 			else
1497 				return (DNS_R_SYNTAX);
1498 			if (n == 0)
1499 				return (DNS_R_SYNTAX);
1500 			n--;
1501 			if ((d = decvalue(*s++)) != -1)
1502 				c = c * 10 + d;
1503 			else
1504 				return (DNS_R_SYNTAX);
1505 			if (c > 255)
1506 				return (DNS_R_SYNTAX);
1507 		} else if (!escape && c == '\\') {
1508 			escape = true;
1509 			continue;
1510 		}
1511 		escape = false;
1512 		if (nrem == 0)
1513 			return ((tregion.length <= 256U) ?
1514 				ISC_R_NOSPACE : DNS_R_SYNTAX);
1515 		*t++ = c;
1516 		nrem--;
1517 	}
1518 	if (escape)
1519 		return (DNS_R_SYNTAX);
1520 	*tregion.base = (unsigned char)(t - tregion.base - 1);
1521 	isc_buffer_add(target, *tregion.base + 1);
1522 	return (ISC_R_SUCCESS);
1523 }
1524 
1525 static isc_result_t
1526 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
1527 	unsigned int n;
1528 	isc_region_t sregion;
1529 	isc_region_t tregion;
1530 
1531 	isc_buffer_activeregion(source, &sregion);
1532 	if (sregion.length == 0)
1533 		return (ISC_R_UNEXPECTEDEND);
1534 	n = *sregion.base + 1;
1535 	if (n > sregion.length)
1536 		return (ISC_R_UNEXPECTEDEND);
1537 
1538 	isc_buffer_availableregion(target, &tregion);
1539 	if (n > tregion.length)
1540 		return (ISC_R_NOSPACE);
1541 
1542 	if (tregion.base != sregion.base)
1543 		memmove(tregion.base, sregion.base, n);
1544 	isc_buffer_forward(source, n);
1545 	isc_buffer_add(target, n);
1546 	return (ISC_R_SUCCESS);
1547 }
1548 
1549 /*
1550  * Conversion of TXT-like rdata fields without length limits.
1551  */
1552 static isc_result_t
1553 multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
1554 	unsigned int tl;
1555 	unsigned int n0, n;
1556 	unsigned char *sp;
1557 	char *tp;
1558 	isc_region_t region;
1559 
1560 	isc_buffer_availableregion(target, &region);
1561 	sp = source->base;
1562 	tp = (char *)region.base;
1563 	tl = region.length;
1564 
1565 	if (tl < 1)
1566 		return (ISC_R_NOSPACE);
1567 	*tp++ = '"';
1568 	tl--;
1569 	do {
1570 		n = source->length;
1571 		n0 = source->length - 1;
1572 
1573 		while (n--) {
1574 			if (*sp < 0x20 || *sp >= 0x7f) {
1575 				if (tl < 4)
1576 					return (ISC_R_NOSPACE);
1577 				*tp++ = 0x5c;
1578 				*tp++ = 0x30 + ((*sp / 100) % 10);
1579 				*tp++ = 0x30 + ((*sp / 10) % 10);
1580 				*tp++ = 0x30 + (*sp % 10);
1581 				sp++;
1582 				tl -= 4;
1583 				continue;
1584 			}
1585 			/* double quote, backslash */
1586 			if (*sp == 0x22 || *sp == 0x5c) {
1587 				if (tl < 2)
1588 					return (ISC_R_NOSPACE);
1589 				*tp++ = '\\';
1590 				tl--;
1591 			}
1592 			if (tl < 1)
1593 				return (ISC_R_NOSPACE);
1594 			*tp++ = *sp++;
1595 			tl--;
1596 		}
1597 		isc_region_consume(source, n0 + 1);
1598 	} while (source->length != 0);
1599 	if (tl < 1)
1600 		return (ISC_R_NOSPACE);
1601 	*tp++ = '"';
1602 	tl--;
1603 	POST(tl);
1604 	isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
1605 	return (ISC_R_SUCCESS);
1606 }
1607 
1608 static isc_result_t
1609 multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
1610 	isc_region_t tregion;
1611 	bool escape;
1612 	unsigned int n, nrem;
1613 	char *s;
1614 	unsigned char *t0, *t;
1615 	int d;
1616 	int c;
1617 
1618 	s = source->base;
1619 	n = source->length;
1620 	escape = false;
1621 
1622 	do {
1623 		isc_buffer_availableregion(target, &tregion);
1624 		t0 = t = tregion.base;
1625 		nrem = tregion.length;
1626 		if (nrem < 1)
1627 			return (ISC_R_NOSPACE);
1628 
1629 		while (n != 0) {
1630 			--n;
1631 			c = (*s++) & 0xff;
1632 			if (escape && (d = decvalue((char)c)) != -1) {
1633 				c = d;
1634 				if (n == 0)
1635 					return (DNS_R_SYNTAX);
1636 				n--;
1637 				if ((d = decvalue(*s++)) != -1)
1638 					c = c * 10 + d;
1639 				else
1640 					return (DNS_R_SYNTAX);
1641 				if (n == 0)
1642 					return (DNS_R_SYNTAX);
1643 				n--;
1644 				if ((d = decvalue(*s++)) != -1)
1645 					c = c * 10 + d;
1646 				else
1647 					return (DNS_R_SYNTAX);
1648 				if (c > 255)
1649 					return (DNS_R_SYNTAX);
1650 			} else if (!escape && c == '\\') {
1651 				escape = true;
1652 				continue;
1653 			}
1654 			escape = false;
1655 			*t++ = c;
1656 			nrem--;
1657 			if (nrem == 0)
1658 				break;
1659 		}
1660 		if (escape)
1661 			return (DNS_R_SYNTAX);
1662 
1663 		isc_buffer_add(target, (unsigned int)(t - t0));
1664 	} while (n != 0);
1665 	return (ISC_R_SUCCESS);
1666 }
1667 
1668 static bool
1669 name_prefix(dns_name_t *name, const dns_name_t *origin, dns_name_t *target) {
1670 	int l1, l2;
1671 
1672 	if (origin == NULL)
1673 		goto return_false;
1674 
1675 	if (dns_name_compare(origin, dns_rootname) == 0)
1676 		goto return_false;
1677 
1678 	if (!dns_name_issubdomain(name, origin))
1679 		goto return_false;
1680 
1681 	l1 = dns_name_countlabels(name);
1682 	l2 = dns_name_countlabels(origin);
1683 
1684 	if (l1 == l2)
1685 		goto return_false;
1686 
1687 	/* Master files should be case preserving. */
1688 	dns_name_getlabelsequence(name, l1 - l2, l2, target);
1689 	if (!dns_name_caseequal(origin, target))
1690 		goto return_false;
1691 
1692 	dns_name_getlabelsequence(name, 0, l1 - l2, target);
1693 	return (true);
1694 
1695 return_false:
1696 	*target = *name;
1697 	return (false);
1698 }
1699 
1700 static isc_result_t
1701 str_totext(const char *source, isc_buffer_t *target) {
1702 	unsigned int l;
1703 	isc_region_t region;
1704 
1705 	isc_buffer_availableregion(target, &region);
1706 	l = strlen(source);
1707 
1708 	if (l > region.length)
1709 		return (ISC_R_NOSPACE);
1710 
1711 	memmove(region.base, source, l);
1712 	isc_buffer_add(target, l);
1713 	return (ISC_R_SUCCESS);
1714 }
1715 
1716 static isc_result_t
1717 inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
1718 	char tmpbuf[64];
1719 
1720 	/* Note - inet_ntop doesn't do size checking on its input. */
1721 	if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
1722 		return (ISC_R_NOSPACE);
1723 	if (strlen(tmpbuf) > isc_buffer_availablelength(target))
1724 		return (ISC_R_NOSPACE);
1725 	isc_buffer_putstr(target, tmpbuf);
1726 	return (ISC_R_SUCCESS);
1727 }
1728 
1729 static bool
1730 buffer_empty(isc_buffer_t *source) {
1731 	return((source->current == source->active) ? true : false);
1732 }
1733 
1734 static void
1735 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
1736 	isc_buffer_init(buffer, region->base, region->length);
1737 	isc_buffer_add(buffer, region->length);
1738 	isc_buffer_setactive(buffer, region->length);
1739 }
1740 
1741 static isc_result_t
1742 uint32_tobuffer(uint32_t value, isc_buffer_t *target) {
1743 	isc_region_t region;
1744 
1745 	isc_buffer_availableregion(target, &region);
1746 	if (region.length < 4)
1747 		return (ISC_R_NOSPACE);
1748 	isc_buffer_putuint32(target, value);
1749 	return (ISC_R_SUCCESS);
1750 }
1751 
1752 static isc_result_t
1753 uint16_tobuffer(uint32_t value, isc_buffer_t *target) {
1754 	isc_region_t region;
1755 
1756 	if (value > 0xffff)
1757 		return (ISC_R_RANGE);
1758 	isc_buffer_availableregion(target, &region);
1759 	if (region.length < 2)
1760 		return (ISC_R_NOSPACE);
1761 	isc_buffer_putuint16(target, (uint16_t)value);
1762 	return (ISC_R_SUCCESS);
1763 }
1764 
1765 static isc_result_t
1766 uint8_tobuffer(uint32_t value, isc_buffer_t *target) {
1767 	isc_region_t region;
1768 
1769 	if (value > 0xff)
1770 		return (ISC_R_RANGE);
1771 	isc_buffer_availableregion(target, &region);
1772 	if (region.length < 1)
1773 		return (ISC_R_NOSPACE);
1774 	isc_buffer_putuint8(target, (uint8_t)value);
1775 	return (ISC_R_SUCCESS);
1776 }
1777 
1778 static isc_result_t
1779 name_tobuffer(const dns_name_t *name, isc_buffer_t *target) {
1780 	isc_region_t r;
1781 	dns_name_toregion(name, &r);
1782 	return (isc_buffer_copyregion(target, &r));
1783 }
1784 
1785 static uint32_t
1786 uint32_fromregion(isc_region_t *region) {
1787 	uint32_t value;
1788 
1789 	REQUIRE(region->length >= 4);
1790 	value = (uint32_t)region->base[0] << 24;
1791 	value |= (uint32_t)region->base[1] << 16;
1792 	value |= (uint32_t)region->base[2] << 8;
1793 	value |= (uint32_t)region->base[3];
1794 	return(value);
1795 }
1796 
1797 static uint16_t
1798 uint16_consume_fromregion(isc_region_t *region) {
1799 	uint16_t r = uint16_fromregion(region);
1800 
1801 	isc_region_consume(region, 2);
1802 	return r;
1803 }
1804 
1805 static uint16_t
1806 uint16_fromregion(isc_region_t *region) {
1807 
1808 	REQUIRE(region->length >= 2);
1809 
1810 	return ((region->base[0] << 8) | region->base[1]);
1811 }
1812 
1813 static uint8_t
1814 uint8_fromregion(isc_region_t *region) {
1815 
1816 	REQUIRE(region->length >= 1);
1817 
1818 	return (region->base[0]);
1819 }
1820 
1821 static uint8_t
1822 uint8_consume_fromregion(isc_region_t *region) {
1823 	uint8_t r = uint8_fromregion(region);
1824 
1825 	isc_region_consume(region, 1);
1826 	return r;
1827 }
1828 
1829 static isc_result_t
1830 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
1831 	isc_region_t tr;
1832 
1833 	if (length == 0U)
1834 		return (ISC_R_SUCCESS);
1835 
1836 	isc_buffer_availableregion(target, &tr);
1837 	if (length > tr.length)
1838 		return (ISC_R_NOSPACE);
1839 	if (tr.base != base)
1840 		memmove(tr.base, base, length);
1841 	isc_buffer_add(target, length);
1842 	return (ISC_R_SUCCESS);
1843 }
1844 
1845 static int
1846 hexvalue(char value) {
1847 	const char *s;
1848 	unsigned char c;
1849 
1850 	c = (unsigned char)value;
1851 
1852 	if (!isascii(c))
1853 		return (-1);
1854 	if (isupper(c))
1855 		c = tolower(c);
1856 	if ((s = strchr(hexdigits, c)) == NULL)
1857 		return (-1);
1858 	return (int)(s - hexdigits);
1859 }
1860 
1861 static int
1862 decvalue(char value) {
1863 	const char *s;
1864 
1865 	/*
1866 	 * isascii() is valid for full range of int values, no need to
1867 	 * mask or cast.
1868 	 */
1869 	if (!isascii(value))
1870 		return (-1);
1871 	if ((s = strchr(decdigits, value)) == NULL)
1872 		return (-1);
1873 	return (int)(s - decdigits);
1874 }
1875 
1876 static const char atob_digits[86] =
1877 	"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
1878 	"abcdefghijklmnopqrstu";
1879 /*
1880  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
1881  * Computes the number of bytes, and three kinds of simple checksums.
1882  * Incoming bytes are collected into 32-bit words, then printed in base 85:
1883  *	exp(85,5) > exp(2,32)
1884  * The ASCII characters used are between '!' and 'u';
1885  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
1886  *
1887  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
1888  * the atob/btoa programs, released with the compress program, in mod.sources.
1889  * Modified by Mike Schwartz 8/19/86 for use in BIND.
1890  * Modified to be re-entrant 3/2/99.
1891  */
1892 
1893 
1894 struct state {
1895 	int32_t Ceor;
1896 	int32_t Csum;
1897 	int32_t Crot;
1898 	int32_t word;
1899 	int32_t bcount;
1900 };
1901 
1902 #define Ceor state->Ceor
1903 #define Csum state->Csum
1904 #define Crot state->Crot
1905 #define word state->word
1906 #define bcount state->bcount
1907 
1908 #define times85(x)	((((((x<<2)+x)<<2)+x)<<2)+x)
1909 
1910 static isc_result_t	byte_atob(int c, isc_buffer_t *target,
1911 				  struct state *state);
1912 static isc_result_t	putbyte(int c, isc_buffer_t *, struct state *state);
1913 static isc_result_t	byte_btoa(int c, isc_buffer_t *, struct state *state);
1914 
1915 /*
1916  * Decode ASCII-encoded byte c into binary representation and
1917  * place into *bufp, advancing bufp.
1918  */
1919 static isc_result_t
1920 byte_atob(int c, isc_buffer_t *target, struct state *state) {
1921 	const char *s;
1922 	if (c == 'z') {
1923 		if (bcount != 0)
1924 			return(DNS_R_SYNTAX);
1925 		else {
1926 			RETERR(putbyte(0, target, state));
1927 			RETERR(putbyte(0, target, state));
1928 			RETERR(putbyte(0, target, state));
1929 			RETERR(putbyte(0, target, state));
1930 		}
1931 	} else if ((s = strchr(atob_digits, c)) != NULL) {
1932 		if (bcount == 0) {
1933 			word = (int32_t)(s - atob_digits);
1934 			++bcount;
1935 		} else if (bcount < 4) {
1936 			word = times85(word);
1937 			word += (int32_t)(s - atob_digits);
1938 			++bcount;
1939 		} else {
1940 			word = times85(word);
1941 			word += (int32_t)(s - atob_digits);
1942 			RETERR(putbyte((word >> 24) & 0xff, target, state));
1943 			RETERR(putbyte((word >> 16) & 0xff, target, state));
1944 			RETERR(putbyte((word >> 8) & 0xff, target, state));
1945 			RETERR(putbyte(word & 0xff, target, state));
1946 			word = 0;
1947 			bcount = 0;
1948 		}
1949 	} else
1950 		return(DNS_R_SYNTAX);
1951 	return(ISC_R_SUCCESS);
1952 }
1953 
1954 /*
1955  * Compute checksum info and place c into target.
1956  */
1957 static isc_result_t
1958 putbyte(int c, isc_buffer_t *target, struct state *state) {
1959 	isc_region_t tr;
1960 
1961 	Ceor ^= c;
1962 	Csum += c;
1963 	Csum += 1;
1964 	if ((Crot & 0x80000000)) {
1965 		Crot <<= 1;
1966 		Crot += 1;
1967 	} else {
1968 		Crot <<= 1;
1969 	}
1970 	Crot += c;
1971 	isc_buffer_availableregion(target, &tr);
1972 	if (tr.length < 1)
1973 		return (ISC_R_NOSPACE);
1974 	tr.base[0] = c;
1975 	isc_buffer_add(target, 1);
1976 	return (ISC_R_SUCCESS);
1977 }
1978 
1979 /*
1980  * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
1981  * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
1982  * outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
1983  * in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
1984  * boundary, there will be no problem...it will be padded with 0 bytes, and
1985  * numbytes will indicate the correct number of bytes.  The main point is
1986  * that since the buffer is filled in 4 bytes at a time, even if there is
1987  * not a full 4 bytes of data at the end, there has to be room to 0-pad the
1988  * data, so the buffer must be of size divisible by 4).  Place the number of
1989  * output bytes in numbytes, and return a failure/success status.
1990  */
1991 
1992 static isc_result_t
1993 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
1994 	long oeor, osum, orot;
1995 	struct state statebuf, *state= &statebuf;
1996 	isc_token_t token;
1997 	char c;
1998 	char *e;
1999 
2000 	Ceor = Csum = Crot = word = bcount = 0;
2001 
2002 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
2003 				      false));
2004 	while (token.value.as_textregion.length != 0) {
2005 		if ((c = token.value.as_textregion.base[0]) == 'x') {
2006 			break;
2007 		} else
2008 			RETERR(byte_atob(c, target, state));
2009 		isc_textregion_consume(&token.value.as_textregion, 1);
2010 	}
2011 
2012 	/*
2013 	 * Number of bytes.
2014 	 */
2015 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
2016 				      false));
2017 	if ((token.value.as_ulong % 4) != 0U) {
2018 		unsigned long padding = 4 - (token.value.as_ulong % 4);
2019 		if (isc_buffer_usedlength(target) < padding)
2020 			return (DNS_R_SYNTAX);
2021 		isc_buffer_subtract(target, padding);
2022 	}
2023 
2024 	/*
2025 	 * Checksum.
2026 	 */
2027 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
2028 				      false));
2029 	oeor = strtol(DNS_AS_STR(token), &e, 16);
2030 	if (*e != 0)
2031 		return (DNS_R_SYNTAX);
2032 
2033 	/*
2034 	 * Checksum.
2035 	 */
2036 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
2037 				      false));
2038 	osum = strtol(DNS_AS_STR(token), &e, 16);
2039 	if (*e != 0)
2040 		return (DNS_R_SYNTAX);
2041 
2042 	/*
2043 	 * Checksum.
2044 	 */
2045 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
2046 				      false));
2047 	orot = strtol(DNS_AS_STR(token), &e, 16);
2048 	if (*e != 0)
2049 		return (DNS_R_SYNTAX);
2050 
2051 	if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
2052 		return(DNS_R_BADCKSUM);
2053 	return (ISC_R_SUCCESS);
2054 }
2055 
2056 /*
2057  * Encode binary byte c into ASCII representation and place into *bufp,
2058  * advancing bufp.
2059  */
2060 static isc_result_t
2061 byte_btoa(int c, isc_buffer_t *target, struct state *state) {
2062 	isc_region_t tr;
2063 
2064 	isc_buffer_availableregion(target, &tr);
2065 	Ceor ^= c;
2066 	Csum += c;
2067 	Csum += 1;
2068 	if ((Crot & 0x80000000)) {
2069 		Crot <<= 1;
2070 		Crot += 1;
2071 	} else {
2072 		Crot <<= 1;
2073 	}
2074 	Crot += c;
2075 
2076 	word <<= 8;
2077 	word |= c;
2078 	if (bcount == 3) {
2079 		if (word == 0) {
2080 			if (tr.length < 1)
2081 				return (ISC_R_NOSPACE);
2082 			tr.base[0] = 'z';
2083 			isc_buffer_add(target, 1);
2084 		} else {
2085 		    register int tmp = 0;
2086 		    register int32_t tmpword = word;
2087 
2088 		    if (tmpword < 0) {
2089 			   /*
2090 			    * Because some don't support u_long.
2091 			    */
2092 			tmp = 32;
2093 			tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
2094 		    }
2095 		    if (tmpword < 0) {
2096 			tmp = 64;
2097 			tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
2098 		    }
2099 			if (tr.length < 5)
2100 				return (ISC_R_NOSPACE);
2101 			tr.base[0] = atob_digits[(tmpword /
2102 					      (int32_t)(85 * 85 * 85 * 85))
2103 						+ tmp];
2104 			tmpword %= (int32_t)(85 * 85 * 85 * 85);
2105 			tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
2106 			tmpword %= (85 * 85 * 85);
2107 			tr.base[2] = atob_digits[tmpword / (85 * 85)];
2108 			tmpword %= (85 * 85);
2109 			tr.base[3] = atob_digits[tmpword / 85];
2110 			tmpword %= 85;
2111 			tr.base[4] = atob_digits[tmpword];
2112 			isc_buffer_add(target, 5);
2113 		}
2114 		bcount = 0;
2115 	} else {
2116 		bcount += 1;
2117 	}
2118 	return (ISC_R_SUCCESS);
2119 }
2120 
2121 
2122 /*
2123  * Encode the binary data from inbuf, of length inbuflen, into a
2124  * target.  Return success/failure status
2125  */
2126 static isc_result_t
2127 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
2128 	int inc;
2129 	struct state statebuf, *state = &statebuf;
2130 	char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
2131 
2132 	Ceor = Csum = Crot = word = bcount = 0;
2133 	for (inc = 0; inc < inbuflen; inbuf++, inc++)
2134 		RETERR(byte_btoa(*inbuf, target, state));
2135 
2136 	while (bcount != 0)
2137 		RETERR(byte_btoa(0, target, state));
2138 
2139 	/*
2140 	 * Put byte count and checksum information at end of buffer,
2141 	 * delimited by 'x'
2142 	 */
2143 	snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
2144 	return (str_totext(buf, target));
2145 }
2146 
2147 
2148 static void
2149 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
2150 			  ...)
2151 {
2152 	va_list ap;
2153 
2154 	UNUSED(callbacks);
2155 
2156 	va_start(ap, fmt);
2157 	vfprintf(stderr, fmt, ap);
2158 	va_end(ap);
2159 	fprintf(stderr, "\n");
2160 }
2161 
2162 static void
2163 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
2164 	if (isc_lex_isfile(lexer) && callbacks != NULL) {
2165 		const char *name = isc_lex_getsourcename(lexer);
2166 		if (name == NULL)
2167 			name = "UNKNOWN";
2168 		(*callbacks->warn)(callbacks,
2169 				   "%s:%lu: file does not end with newline",
2170 				   name, isc_lex_getsourceline(lexer));
2171 	}
2172 }
2173 
2174 static void
2175 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
2176 	   dns_rdatacallbacks_t *callbacks)
2177 {
2178 	const char *file;
2179 	unsigned long line;
2180 
2181 	if (lexer != NULL) {
2182 		file = isc_lex_getsourcename(lexer);
2183 		line = isc_lex_getsourceline(lexer);
2184 		(*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
2185 				   file, line, DNS_AS_STR(*token),
2186 				   dns_result_totext(DNS_R_MXISADDRESS));
2187 	}
2188 }
2189 
2190 static void
2191 warn_badname(const dns_name_t *name, isc_lex_t *lexer,
2192 	     dns_rdatacallbacks_t *callbacks)
2193 {
2194 	const char *file;
2195 	unsigned long line;
2196 	char namebuf[DNS_NAME_FORMATSIZE];
2197 
2198 	if (lexer != NULL) {
2199 		file = isc_lex_getsourcename(lexer);
2200 		line = isc_lex_getsourceline(lexer);
2201 		dns_name_format(name, namebuf, sizeof(namebuf));
2202 		(*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
2203 				   file, line, namebuf,
2204 				   dns_result_totext(DNS_R_BADNAME));
2205 	}
2206 }
2207 
2208 static void
2209 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
2210 	       dns_rdatacallbacks_t *callbacks, const char *name,
2211 	       unsigned long line, isc_token_t *token, isc_result_t result)
2212 {
2213 	if (name == NULL)
2214 		name = "UNKNOWN";
2215 
2216 	if (token != NULL) {
2217 		switch (token->type) {
2218 		case isc_tokentype_eol:
2219 			(*callback)(callbacks, "%s: %s:%lu: near eol: %s",
2220 				    "dns_rdata_fromtext", name, line,
2221 				    dns_result_totext(result));
2222 			break;
2223 		case isc_tokentype_eof:
2224 			(*callback)(callbacks, "%s: %s:%lu: near eof: %s",
2225 				    "dns_rdata_fromtext", name, line,
2226 				    dns_result_totext(result));
2227 			break;
2228 		case isc_tokentype_number:
2229 			(*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
2230 				    "dns_rdata_fromtext", name, line,
2231 				    token->value.as_ulong,
2232 				    dns_result_totext(result));
2233 			break;
2234 		case isc_tokentype_string:
2235 		case isc_tokentype_qstring:
2236 			(*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
2237 				    "dns_rdata_fromtext", name, line,
2238 				    DNS_AS_STR(*token),
2239 				    dns_result_totext(result));
2240 			break;
2241 		default:
2242 			(*callback)(callbacks, "%s: %s:%lu: %s",
2243 				    "dns_rdata_fromtext", name, line,
2244 				    dns_result_totext(result));
2245 			break;
2246 		}
2247 	} else {
2248 		(*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
2249 			    name, line, dns_result_totext(result));
2250 	}
2251 }
2252 
2253 dns_rdatatype_t
2254 dns_rdata_covers(dns_rdata_t *rdata) {
2255 	if (rdata->type == dns_rdatatype_rrsig)
2256 		return (covers_rrsig(rdata));
2257 	return (covers_sig(rdata));
2258 }
2259 
2260 bool
2261 dns_rdatatype_ismeta(dns_rdatatype_t type) {
2262 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
2263 		return (true);
2264 	return (false);
2265 }
2266 
2267 bool
2268 dns_rdatatype_issingleton(dns_rdatatype_t type) {
2269 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
2270 	    != 0)
2271 		return (true);
2272 	return (false);
2273 }
2274 
2275 bool
2276 dns_rdatatype_notquestion(dns_rdatatype_t type) {
2277 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
2278 	    != 0)
2279 		return (true);
2280 	return (false);
2281 }
2282 
2283 bool
2284 dns_rdatatype_questiononly(dns_rdatatype_t type) {
2285 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
2286 	    != 0)
2287 		return (true);
2288 	return (false);
2289 }
2290 
2291 bool
2292 dns_rdatatype_atcname(dns_rdatatype_t type) {
2293 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATCNAME) != 0) {
2294 		return (true);
2295 	}
2296 	return (false);
2297 }
2298 
2299 bool
2300 dns_rdatatype_atparent(dns_rdatatype_t type) {
2301 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
2302 		return (true);
2303 	return (false);
2304 }
2305 
2306 bool
2307 dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
2308 
2309 	if (rdclass == dns_rdataclass_reserved0
2310 	    || rdclass == dns_rdataclass_none
2311 	    || rdclass == dns_rdataclass_any)
2312 		return (true);
2313 
2314 	return (false);  /* Assume it is not a meta class. */
2315 }
2316 
2317 bool
2318 dns_rdatatype_isdnssec(dns_rdatatype_t type) {
2319 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
2320 		return (true);
2321 	return (false);
2322 }
2323 
2324 bool
2325 dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
2326 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ZONECUTAUTH)
2327 	    != 0)
2328 	{
2329 		return (true);
2330 	}
2331 	return (false);
2332 }
2333 
2334 bool
2335 dns_rdatatype_isknown(dns_rdatatype_t type) {
2336 	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
2337 	    == 0)
2338 		return (true);
2339 	return (false);
2340 }
2341 
2342 void
2343 dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) {
2344 
2345 	REQUIRE(rdata != NULL);
2346 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2347 
2348 	rdata->data = NULL;
2349 	rdata->length = 0;
2350 	rdata->flags = DNS_RDATA_UPDATE;
2351 	rdata->type = type;
2352 	rdata->rdclass = dns_rdataclass_any;
2353 }
2354 
2355 void
2356 dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) {
2357 
2358 	REQUIRE(rdata != NULL);
2359 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2360 
2361 	rdata->data = NULL;
2362 	rdata->length = 0;
2363 	rdata->flags = DNS_RDATA_UPDATE;
2364 	rdata->type = type;
2365 	rdata->rdclass = dns_rdataclass_none;
2366 }
2367 
2368 void
2369 dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) {
2370 
2371 	REQUIRE(rdata != NULL);
2372 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2373 
2374 	rdata->data = NULL;
2375 	rdata->length = 0;
2376 	rdata->flags = DNS_RDATA_UPDATE;
2377 	rdata->type = type;
2378 	rdata->rdclass = dns_rdataclass_any;
2379 }
2380 
2381 void
2382 dns_rdata_makedelete(dns_rdata_t *rdata) {
2383 	REQUIRE(rdata != NULL);
2384 
2385 	rdata->rdclass = dns_rdataclass_none;
2386 }
2387 
2388 const char *
2389 dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) {
2390 
2391 	REQUIRE(rdata != NULL);
2392 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2393 
2394 	switch (section) {
2395 	case DNS_SECTION_PREREQUISITE:
2396 		switch (rdata->rdclass) {
2397 		case dns_rdataclass_none:
2398 			switch (rdata->type) {
2399 			case dns_rdatatype_any:
2400 				return ("domain doesn't exist");
2401 			default:
2402 				return ("rrset doesn't exist");
2403 			}
2404 		case dns_rdataclass_any:
2405 			switch (rdata->type) {
2406 			case dns_rdatatype_any:
2407 				return ("domain exists");
2408 			default:
2409 				return ("rrset exists (value independent)");
2410 			}
2411 		default:
2412 			return ("rrset exists (value dependent)");
2413 		}
2414 	case DNS_SECTION_UPDATE:
2415 		switch (rdata->rdclass) {
2416 		case dns_rdataclass_none:
2417 			return ("delete");
2418 		case dns_rdataclass_any:
2419 			switch (rdata->type) {
2420 			case dns_rdatatype_any:
2421 				return ("delete all rrsets");
2422 			default:
2423 				return ("delete rrset");
2424 			}
2425 		default:
2426 			return ("add");
2427 		}
2428 	}
2429 	return ("invalid");
2430 }
2431