xref: /openbsd/usr.bin/dig/lib/dns/rdata.c (revision e6c7c102)
15185a700Sflorian /*
25185a700Sflorian  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian  *
45185a700Sflorian  * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian  * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian  * copyright notice and this permission notice appear in all copies.
75185a700Sflorian  *
85185a700Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian  * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian  */
165185a700Sflorian 
17*e6c7c102Sjsg /* $Id: rdata.c,v 1.36 2024/04/23 13:34:50 jsg Exp $ */
185185a700Sflorian 
195185a700Sflorian /*! \file */
205185a700Sflorian 
211bf56eb0Sflorian #include <arpa/inet.h>
221bf56eb0Sflorian 
235185a700Sflorian #include <stdlib.h>
2479d70287Sflorian #include <string.h>
255185a700Sflorian 
265185a700Sflorian #include <isc/base64.h>
275185a700Sflorian #include <isc/hex.h>
285185a700Sflorian #include <isc/util.h>
294465bcfbSjsg #include <isc/buffer.h>
305185a700Sflorian 
315185a700Sflorian #include <dns/cert.h>
325185a700Sflorian #include <dns/compress.h>
335185a700Sflorian #include <dns/keyvalues.h>
345185a700Sflorian #include <dns/rcode.h>
355185a700Sflorian #include <dns/rdata.h>
365185a700Sflorian #include <dns/rdatatype.h>
375185a700Sflorian #include <dns/result.h>
385185a700Sflorian #include <dns/time.h>
395185a700Sflorian #include <dns/ttl.h>
405185a700Sflorian 
415185a700Sflorian #define RETERR(x) \
425185a700Sflorian 	do { \
435185a700Sflorian 		isc_result_t _r = (x); \
445185a700Sflorian 		if (_r != ISC_R_SUCCESS) \
455185a700Sflorian 			return (_r); \
465185a700Sflorian 	} while (0)
475185a700Sflorian 
485185a700Sflorian #define ARGS_TOTEXT	dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
495185a700Sflorian 			isc_buffer_t *target
505185a700Sflorian 
515185a700Sflorian #define ARGS_FROMWIRE	int rdclass, dns_rdatatype_t type, \
525185a700Sflorian 			isc_buffer_t *source, dns_decompress_t *dctx, \
535185a700Sflorian 			unsigned int options, isc_buffer_t *target
545185a700Sflorian 
555185a700Sflorian #define ARGS_TOWIRE	dns_rdata_t *rdata, dns_compress_t *cctx, \
565185a700Sflorian 			isc_buffer_t *target
575185a700Sflorian 
585185a700Sflorian #define ARGS_FROMSTRUCT	int rdclass, dns_rdatatype_t type, \
595185a700Sflorian 			void *source, isc_buffer_t *target
605185a700Sflorian 
615185a700Sflorian #define ARGS_TOSTRUCT	const dns_rdata_t *rdata, void *target
625185a700Sflorian 
635185a700Sflorian #define ARGS_FREESTRUCT void *source
645185a700Sflorian 
655185a700Sflorian #define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
661fb015a8Sflorian 			dns_rdatatype_t type, int wildcard
675185a700Sflorian 
685185a700Sflorian /*%
695185a700Sflorian  * Context structure for the totext_ functions.
705185a700Sflorian  * Contains formatting options for rdata-to-text
715185a700Sflorian  * conversion.
725185a700Sflorian  */
735185a700Sflorian typedef struct dns_rdata_textctx {
745185a700Sflorian 	dns_name_t *origin;	/*%< Current origin, or NULL. */
755185a700Sflorian 	unsigned int flags;	/*%< DNS_STYLEFLAG_*  */
765185a700Sflorian 	unsigned int width;	/*%< Width of rdata column. */
775185a700Sflorian 	const char *linebreak;	/*%< Line break string. */
785185a700Sflorian } dns_rdata_textctx_t;
795185a700Sflorian 
809e6f49f3Sflorian typedef struct dns_rdata_type_lookup {
819e6f49f3Sflorian 	const char	*type;
829e6f49f3Sflorian 	int		 val;
839e6f49f3Sflorian } dns_rdata_type_lookup_t;
849e6f49f3Sflorian 
855185a700Sflorian static isc_result_t
861fb015a8Sflorian txt_totext(isc_region_t *source, int quote, isc_buffer_t *target);
875185a700Sflorian 
885185a700Sflorian static isc_result_t
895185a700Sflorian txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
905185a700Sflorian 
915185a700Sflorian static isc_result_t
925185a700Sflorian multitxt_totext(isc_region_t *source, isc_buffer_t *target);
935185a700Sflorian 
941fb015a8Sflorian static int
955185a700Sflorian name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
965185a700Sflorian 
975185a700Sflorian static unsigned int
985185a700Sflorian name_length(dns_name_t *name);
995185a700Sflorian 
1005185a700Sflorian static isc_result_t
1015185a700Sflorian inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
1025185a700Sflorian 
1031fb015a8Sflorian static int
1045185a700Sflorian buffer_empty(isc_buffer_t *source);
1055185a700Sflorian 
1065185a700Sflorian static isc_result_t
1075185a700Sflorian uint32_tobuffer(uint32_t, isc_buffer_t *target);
1085185a700Sflorian 
1095185a700Sflorian static isc_result_t
1105185a700Sflorian uint16_tobuffer(uint32_t, isc_buffer_t *target);
1115185a700Sflorian 
1125185a700Sflorian static isc_result_t
1135185a700Sflorian name_tobuffer(dns_name_t *name, isc_buffer_t *target);
1145185a700Sflorian 
1155185a700Sflorian static uint32_t
1165185a700Sflorian uint32_fromregion(isc_region_t *region);
1175185a700Sflorian 
1185185a700Sflorian static uint16_t
1195185a700Sflorian uint16_fromregion(isc_region_t *region);
1205185a700Sflorian 
1215185a700Sflorian static uint8_t
1225185a700Sflorian uint8_fromregion(isc_region_t *region);
1235185a700Sflorian 
1245185a700Sflorian static uint8_t
1255185a700Sflorian uint8_consume_fromregion(isc_region_t *region);
1265185a700Sflorian 
1275185a700Sflorian static isc_result_t
1285185a700Sflorian btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
1295185a700Sflorian 
1305185a700Sflorian static isc_result_t
1315185a700Sflorian rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
1325185a700Sflorian 	     isc_buffer_t *target);
1335185a700Sflorian 
1345185a700Sflorian static isc_result_t
1355185a700Sflorian unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
1365185a700Sflorian 	       isc_buffer_t *target);
1375185a700Sflorian 
1385185a700Sflorian static inline isc_result_t
1395185a700Sflorian generic_totext_key(ARGS_TOTEXT);
1405185a700Sflorian 
1415185a700Sflorian static inline isc_result_t
1425185a700Sflorian generic_fromwire_key(ARGS_FROMWIRE);
1435185a700Sflorian 
1445185a700Sflorian static isc_result_t
1455185a700Sflorian generic_totext_txt(ARGS_TOTEXT);
1465185a700Sflorian 
1475185a700Sflorian static isc_result_t
1485185a700Sflorian generic_fromwire_txt(ARGS_FROMWIRE);
1495185a700Sflorian 
1505185a700Sflorian static isc_result_t
1515185a700Sflorian generic_totext_ds(ARGS_TOTEXT);
1525185a700Sflorian 
1535185a700Sflorian static isc_result_t
1545185a700Sflorian generic_fromwire_ds(ARGS_FROMWIRE);
1555185a700Sflorian 
1565185a700Sflorian static isc_result_t
1575185a700Sflorian generic_totext_tlsa(ARGS_TOTEXT);
1585185a700Sflorian 
1595185a700Sflorian static isc_result_t
1605185a700Sflorian generic_fromwire_tlsa(ARGS_FROMWIRE);
1615185a700Sflorian 
1625185a700Sflorian static inline isc_result_t
name_duporclone(dns_name_t * source,dns_name_t * target)1635185a700Sflorian name_duporclone(dns_name_t *source, dns_name_t *target) {
1645185a700Sflorian 
1655185a700Sflorian 	return (dns_name_dup(source, target));
1665185a700Sflorian }
1675185a700Sflorian 
1685185a700Sflorian static inline void *
mem_maybedup(void * source,size_t length)1695185a700Sflorian mem_maybedup(void *source, size_t length) {
1705185a700Sflorian 	void *copy;
1715185a700Sflorian 
1725185a700Sflorian 	copy = malloc(length);
1735185a700Sflorian 	if (copy != NULL)
1745185a700Sflorian 		memmove(copy, source, length);
1755185a700Sflorian 
1765185a700Sflorian 	return (copy);
1775185a700Sflorian }
1785185a700Sflorian 
1795185a700Sflorian static inline isc_result_t
typemap_totext(isc_region_t * sr,dns_rdata_textctx_t * tctx,isc_buffer_t * target)1805185a700Sflorian typemap_totext(isc_region_t *sr, dns_rdata_textctx_t *tctx,
1815185a700Sflorian 	       isc_buffer_t *target)
1825185a700Sflorian {
1835185a700Sflorian 	unsigned int i, j, k;
1845185a700Sflorian 	unsigned int window, len;
1851fb015a8Sflorian 	int first = 1;
1865185a700Sflorian 
1875185a700Sflorian 	for (i = 0; i < sr->length; i += len) {
1885185a700Sflorian 		if (tctx != NULL &&
1895185a700Sflorian 		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
190873f12b9Sflorian 			RETERR(isc_str_tobuffer(tctx->linebreak, target));
1911fb015a8Sflorian 			first = 1;
1925185a700Sflorian 		}
1935185a700Sflorian 		INSIST(i + 2 <= sr->length);
1945185a700Sflorian 		window = sr->base[i];
1955185a700Sflorian 		len = sr->base[i + 1];
1965185a700Sflorian 		INSIST(len > 0 && len <= 32);
1975185a700Sflorian 		i += 2;
1985185a700Sflorian 		INSIST(i + len <= sr->length);
1995185a700Sflorian 		for (j = 0; j < len; j++) {
2005185a700Sflorian 			dns_rdatatype_t t;
2015185a700Sflorian 			if (sr->base[i + j] == 0)
2025185a700Sflorian 				continue;
2035185a700Sflorian 			for (k = 0; k < 8; k++) {
2045185a700Sflorian 				if ((sr->base[i + j] & (0x80 >> k)) == 0)
2055185a700Sflorian 					continue;
2065185a700Sflorian 				t = window * 256 + j * 8 + k;
2075185a700Sflorian 				if (!first)
208873f12b9Sflorian 					RETERR(isc_str_tobuffer(" ", target));
2091fb015a8Sflorian 				first = 0;
2105185a700Sflorian 				RETERR(dns_rdatatype_totext(t, target));
2115185a700Sflorian 			}
2125185a700Sflorian 		}
2135185a700Sflorian 	}
2145185a700Sflorian 	return (ISC_R_SUCCESS);
2155185a700Sflorian }
2165185a700Sflorian 
2175185a700Sflorian static isc_result_t
typemap_test(isc_region_t * sr,int allow_empty)2181fb015a8Sflorian typemap_test(isc_region_t *sr, int allow_empty) {
2195185a700Sflorian 	unsigned int window, lastwindow = 0;
2205185a700Sflorian 	unsigned int len;
2211fb015a8Sflorian 	int first = 1;
2225185a700Sflorian 	unsigned int i;
2235185a700Sflorian 
2245185a700Sflorian 	for (i = 0; i < sr->length; i += len) {
2255185a700Sflorian 		/*
2265185a700Sflorian 		 * Check for overflow.
2275185a700Sflorian 		 */
2285185a700Sflorian 		if (i + 2 > sr->length)
229fbc1dec8Sflorian 			return (DNS_R_FORMERR);
2305185a700Sflorian 		window = sr->base[i];
2315185a700Sflorian 		len = sr->base[i + 1];
2325185a700Sflorian 		i += 2;
2335185a700Sflorian 		/*
2345185a700Sflorian 		 * Check that bitmap windows are in the correct order.
2355185a700Sflorian 		 */
2365185a700Sflorian 		if (!first && window <= lastwindow)
237fbc1dec8Sflorian 			return (DNS_R_FORMERR);
2385185a700Sflorian 		/*
2395185a700Sflorian 		 * Check for legal lengths.
2405185a700Sflorian 		 */
2415185a700Sflorian 		if (len < 1 || len > 32)
242fbc1dec8Sflorian 			return (DNS_R_FORMERR);
2435185a700Sflorian 		/*
2445185a700Sflorian 		 * Check for overflow.
2455185a700Sflorian 		 */
2465185a700Sflorian 		if (i + len > sr->length)
247fbc1dec8Sflorian 			return (DNS_R_FORMERR);
2485185a700Sflorian 		/*
2495185a700Sflorian 		 * The last octet of the bitmap must be non zero.
2505185a700Sflorian 		 */
2515185a700Sflorian 		if (sr->base[i + len - 1] == 0)
252fbc1dec8Sflorian 			return (DNS_R_FORMERR);
2535185a700Sflorian 		lastwindow = window;
2541fb015a8Sflorian 		first = 0;
2555185a700Sflorian 	}
2565185a700Sflorian 	if (i != sr->length)
2575185a700Sflorian 		return (DNS_R_EXTRADATA);
2585185a700Sflorian 	if (!allow_empty && first)
259fbc1dec8Sflorian 		return (DNS_R_FORMERR);
2605185a700Sflorian 	return (ISC_R_SUCCESS);
2615185a700Sflorian }
2625185a700Sflorian 
2635185a700Sflorian static const char decdigits[] = "0123456789";
2645185a700Sflorian 
2655185a700Sflorian #include "code.h"
2665185a700Sflorian 
2675185a700Sflorian /***
2685185a700Sflorian  *** Initialization
2695185a700Sflorian  ***/
2705185a700Sflorian 
2715185a700Sflorian void
dns_rdata_init(dns_rdata_t * rdata)2725185a700Sflorian dns_rdata_init(dns_rdata_t *rdata) {
2735185a700Sflorian 
2745185a700Sflorian 	REQUIRE(rdata != NULL);
2755185a700Sflorian 
2765185a700Sflorian 	rdata->data = NULL;
2775185a700Sflorian 	rdata->length = 0;
2785185a700Sflorian 	rdata->rdclass = 0;
2795185a700Sflorian 	rdata->type = 0;
2805185a700Sflorian 	rdata->flags = 0;
2815185a700Sflorian 	ISC_LINK_INIT(rdata, link);
2825185a700Sflorian 	/* ISC_LIST_INIT(rdata->list); */
2835185a700Sflorian }
2845185a700Sflorian 
2855185a700Sflorian void
dns_rdata_reset(dns_rdata_t * rdata)2865185a700Sflorian dns_rdata_reset(dns_rdata_t *rdata) {
2875185a700Sflorian 
2885185a700Sflorian 	REQUIRE(rdata != NULL);
2895185a700Sflorian 
2905185a700Sflorian 	REQUIRE(!ISC_LINK_LINKED(rdata, link));
2915185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
2925185a700Sflorian 
2935185a700Sflorian 	rdata->data = NULL;
2945185a700Sflorian 	rdata->length = 0;
2955185a700Sflorian 	rdata->rdclass = 0;
2965185a700Sflorian 	rdata->type = 0;
2975185a700Sflorian 	rdata->flags = 0;
2985185a700Sflorian }
2995185a700Sflorian 
3005185a700Sflorian /***
3015185a700Sflorian  ***
3025185a700Sflorian  ***/
3035185a700Sflorian 
3045185a700Sflorian void
dns_rdata_clone(const dns_rdata_t * src,dns_rdata_t * target)3055185a700Sflorian dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
3065185a700Sflorian 
3075185a700Sflorian 	REQUIRE(src != NULL);
3085185a700Sflorian 	REQUIRE(target != NULL);
3095185a700Sflorian 
3105185a700Sflorian 	REQUIRE(DNS_RDATA_INITIALIZED(target));
3115185a700Sflorian 
3125185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(src));
3135185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(target));
3145185a700Sflorian 
3155185a700Sflorian 	target->data = src->data;
3165185a700Sflorian 	target->length = src->length;
3175185a700Sflorian 	target->rdclass = src->rdclass;
3185185a700Sflorian 	target->type = src->type;
3195185a700Sflorian 	target->flags = src->flags;
3205185a700Sflorian }
3215185a700Sflorian 
3225185a700Sflorian /***
3235185a700Sflorian  *** Conversions
3245185a700Sflorian  ***/
3255185a700Sflorian 
3265185a700Sflorian void
dns_rdata_fromregion(dns_rdata_t * rdata,dns_rdataclass_t rdclass,dns_rdatatype_t type,isc_region_t * r)3275185a700Sflorian dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
3285185a700Sflorian 		     dns_rdatatype_t type, isc_region_t *r)
3295185a700Sflorian {
3305185a700Sflorian 
3315185a700Sflorian 	REQUIRE(rdata != NULL);
3325185a700Sflorian 	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
3335185a700Sflorian 	REQUIRE(r != NULL);
3345185a700Sflorian 
3355185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
3365185a700Sflorian 
3375185a700Sflorian 	rdata->data = r->base;
3385185a700Sflorian 	rdata->length = r->length;
3395185a700Sflorian 	rdata->rdclass = rdclass;
3405185a700Sflorian 	rdata->type = type;
3415185a700Sflorian 	rdata->flags = 0;
3425185a700Sflorian }
3435185a700Sflorian 
3445185a700Sflorian void
dns_rdata_toregion(const dns_rdata_t * rdata,isc_region_t * r)3455185a700Sflorian dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
3465185a700Sflorian 
3475185a700Sflorian 	REQUIRE(rdata != NULL);
3485185a700Sflorian 	REQUIRE(r != NULL);
3495185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
3505185a700Sflorian 
3515185a700Sflorian 	r->base = rdata->data;
3525185a700Sflorian 	r->length = rdata->length;
3535185a700Sflorian }
3545185a700Sflorian 
3555185a700Sflorian isc_result_t
dns_rdata_fromwire(dns_rdata_t * rdata,dns_rdataclass_t rdclass,dns_rdatatype_t type,isc_buffer_t * source,dns_decompress_t * dctx,unsigned int options,isc_buffer_t * target)3565185a700Sflorian dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
3575185a700Sflorian 		   dns_rdatatype_t type, isc_buffer_t *source,
3585185a700Sflorian 		   dns_decompress_t *dctx, unsigned int options,
3595185a700Sflorian 		   isc_buffer_t *target)
3605185a700Sflorian {
3615185a700Sflorian 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
3625185a700Sflorian 	isc_region_t region;
3635185a700Sflorian 	isc_buffer_t ss;
3645185a700Sflorian 	isc_buffer_t st;
3651fb015a8Sflorian 	int use_default = 0;
3665185a700Sflorian 	uint32_t activelength;
3675185a700Sflorian 	unsigned int length;
3685185a700Sflorian 
3695185a700Sflorian 	REQUIRE(dctx != NULL);
3705185a700Sflorian 	if (rdata != NULL) {
3715185a700Sflorian 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
3725185a700Sflorian 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
3735185a700Sflorian 	}
3745185a700Sflorian 	REQUIRE(source != NULL);
3755185a700Sflorian 	REQUIRE(target != NULL);
3765185a700Sflorian 
3775185a700Sflorian 	if (type == 0)
3785185a700Sflorian 		return (DNS_R_FORMERR);
3795185a700Sflorian 
3805185a700Sflorian 	ss = *source;
3815185a700Sflorian 	st = *target;
3825185a700Sflorian 
3835185a700Sflorian 	activelength = isc_buffer_activelength(source);
3845185a700Sflorian 	INSIST(activelength < 65536);
3855185a700Sflorian 
3865185a700Sflorian 	FROMWIRESWITCH
3875185a700Sflorian 
3885185a700Sflorian 	if (use_default) {
3895185a700Sflorian 		if (activelength > isc_buffer_availablelength(target))
3905185a700Sflorian 			result = ISC_R_NOSPACE;
3915185a700Sflorian 		else {
3925185a700Sflorian 			isc_buffer_putmem(target, isc_buffer_current(source),
3935185a700Sflorian 					  activelength);
3945185a700Sflorian 			isc_buffer_forward(source, activelength);
3955185a700Sflorian 			result = ISC_R_SUCCESS;
3965185a700Sflorian 		}
3975185a700Sflorian 	}
3985185a700Sflorian 
3995185a700Sflorian 	/*
4005185a700Sflorian 	 * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH
4015185a700Sflorian 	 * as we cannot transmit it.
4025185a700Sflorian 	 */
4035185a700Sflorian 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
4045185a700Sflorian 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
4055185a700Sflorian 		result = DNS_R_FORMERR;
4065185a700Sflorian 
4075185a700Sflorian 	/*
4085185a700Sflorian 	 * We should have consumed all of our buffer.
4095185a700Sflorian 	 */
4105185a700Sflorian 	if (result == ISC_R_SUCCESS && !buffer_empty(source))
4115185a700Sflorian 		result = DNS_R_EXTRADATA;
4125185a700Sflorian 
4135185a700Sflorian 	if (rdata != NULL && result == ISC_R_SUCCESS) {
4145185a700Sflorian 		region.base = isc_buffer_used(&st);
4155185a700Sflorian 		region.length = length;
4165185a700Sflorian 		dns_rdata_fromregion(rdata, rdclass, type, &region);
4175185a700Sflorian 	}
4185185a700Sflorian 
4195185a700Sflorian 	if (result != ISC_R_SUCCESS) {
4205185a700Sflorian 		*source = ss;
4215185a700Sflorian 		*target = st;
4225185a700Sflorian 	}
4235185a700Sflorian 	return (result);
4245185a700Sflorian }
4255185a700Sflorian 
4265185a700Sflorian isc_result_t
dns_rdata_towire(dns_rdata_t * rdata,dns_compress_t * cctx,isc_buffer_t * target)4275185a700Sflorian dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
4285185a700Sflorian 		 isc_buffer_t *target)
4295185a700Sflorian {
4305185a700Sflorian 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
4311fb015a8Sflorian 	int use_default = 0;
4325185a700Sflorian 	isc_region_t tr;
4335185a700Sflorian 	isc_buffer_t st;
4345185a700Sflorian 
4355185a700Sflorian 	REQUIRE(rdata != NULL);
4365185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
4375185a700Sflorian 
4385185a700Sflorian 	/*
4395185a700Sflorian 	 * Some DynDNS meta-RRs have empty rdata.
4405185a700Sflorian 	 */
4415185a700Sflorian 	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
4425185a700Sflorian 		INSIST(rdata->length == 0);
4435185a700Sflorian 		return (ISC_R_SUCCESS);
4445185a700Sflorian 	}
4455185a700Sflorian 
4465185a700Sflorian 	st = *target;
4475185a700Sflorian 
4485185a700Sflorian 	TOWIRESWITCH
4495185a700Sflorian 
4505185a700Sflorian 	if (use_default) {
4515185a700Sflorian 		isc_buffer_availableregion(target, &tr);
4525185a700Sflorian 		if (tr.length < rdata->length)
4535185a700Sflorian 			return (ISC_R_NOSPACE);
4545185a700Sflorian 		memmove(tr.base, rdata->data, rdata->length);
4555185a700Sflorian 		isc_buffer_add(target, rdata->length);
4565185a700Sflorian 		return (ISC_R_SUCCESS);
4575185a700Sflorian 	}
4585185a700Sflorian 	if (result != ISC_R_SUCCESS) {
4595185a700Sflorian 		*target = st;
4605185a700Sflorian 		INSIST(target->used < 65536);
4615185a700Sflorian 		dns_compress_rollback(cctx, (uint16_t)target->used);
4625185a700Sflorian 	}
4635185a700Sflorian 	return (result);
4645185a700Sflorian }
4655185a700Sflorian 
4665185a700Sflorian static isc_result_t
unknown_totext(dns_rdata_t * rdata,dns_rdata_textctx_t * tctx,isc_buffer_t * target)4675185a700Sflorian unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
4685185a700Sflorian 	       isc_buffer_t *target)
4695185a700Sflorian {
4705185a700Sflorian 	isc_result_t result;
4715185a700Sflorian 	char buf[sizeof("65535")];
4725185a700Sflorian 	isc_region_t sr;
4735185a700Sflorian 
4745185a700Sflorian 	strlcpy(buf, "\\# ", sizeof(buf));
475873f12b9Sflorian 	result = isc_str_tobuffer(buf, target);
4765185a700Sflorian 	if (result != ISC_R_SUCCESS)
4775185a700Sflorian 		return (result);
4785185a700Sflorian 
4795185a700Sflorian 	dns_rdata_toregion(rdata, &sr);
4805185a700Sflorian 	INSIST(sr.length < 65536);
4815185a700Sflorian 	snprintf(buf, sizeof(buf), "%u", sr.length);
482873f12b9Sflorian 	result = isc_str_tobuffer(buf, target);
4835185a700Sflorian 	if (result != ISC_R_SUCCESS)
4845185a700Sflorian 		return (result);
4855185a700Sflorian 
4865185a700Sflorian 	if (sr.length != 0U) {
4875185a700Sflorian 		if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
488873f12b9Sflorian 			result = isc_str_tobuffer(" ( ", target);
4895185a700Sflorian 		else
490873f12b9Sflorian 			result = isc_str_tobuffer(" ", target);
4915185a700Sflorian 
4925185a700Sflorian 		if (result != ISC_R_SUCCESS)
4935185a700Sflorian 			return (result);
4945185a700Sflorian 
4955185a700Sflorian 		if (tctx->width == 0) /* No splitting */
4965185a700Sflorian 			result = isc_hex_totext(&sr, 0, "", target);
4975185a700Sflorian 		else
4985185a700Sflorian 			result = isc_hex_totext(&sr, tctx->width - 2,
4995185a700Sflorian 						tctx->linebreak,
5005185a700Sflorian 						target);
5015185a700Sflorian 		if (result == ISC_R_SUCCESS &&
5025185a700Sflorian 		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
503873f12b9Sflorian 			result = isc_str_tobuffer(" )", target);
5045185a700Sflorian 	}
5055185a700Sflorian 	return (result);
5065185a700Sflorian }
5075185a700Sflorian 
5085185a700Sflorian static isc_result_t
rdata_totext(dns_rdata_t * rdata,dns_rdata_textctx_t * tctx,isc_buffer_t * target)5095185a700Sflorian rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
5105185a700Sflorian 	     isc_buffer_t *target)
5115185a700Sflorian {
5125185a700Sflorian 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
5131fb015a8Sflorian 	int use_default = 0;
5145185a700Sflorian 	unsigned int cur;
5155185a700Sflorian 
5165185a700Sflorian 	REQUIRE(rdata != NULL);
5171fb015a8Sflorian 	REQUIRE(tctx->origin == NULL ||	dns_name_isabsolute(tctx->origin));
5185185a700Sflorian 
5195185a700Sflorian 	/*
5205185a700Sflorian 	 * Some DynDNS meta-RRs have empty rdata.
5215185a700Sflorian 	 */
5225185a700Sflorian 	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
5235185a700Sflorian 		INSIST(rdata->length == 0);
5245185a700Sflorian 		return (ISC_R_SUCCESS);
5255185a700Sflorian 	}
5265185a700Sflorian 
5275185a700Sflorian 	cur = isc_buffer_usedlength(target);
5285185a700Sflorian 
5295185a700Sflorian 	TOTEXTSWITCH
5305185a700Sflorian 
5315185a700Sflorian 	if (use_default || (result == ISC_R_NOTIMPLEMENTED)) {
5325185a700Sflorian 		unsigned int u = isc_buffer_usedlength(target);
5335185a700Sflorian 
5345185a700Sflorian 		INSIST(u >= cur);
5355185a700Sflorian 		isc_buffer_subtract(target, u - cur);
5365185a700Sflorian 		result = unknown_totext(rdata, tctx, target);
5375185a700Sflorian 	}
5385185a700Sflorian 
5395185a700Sflorian 	return (result);
5405185a700Sflorian }
5415185a700Sflorian 
5425185a700Sflorian isc_result_t
dns_rdata_totext(dns_rdata_t * rdata,dns_name_t * origin,isc_buffer_t * target)5435185a700Sflorian dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
5445185a700Sflorian {
5455185a700Sflorian 	dns_rdata_textctx_t tctx;
5465185a700Sflorian 
5475185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
5485185a700Sflorian 
5495185a700Sflorian 	/*
5505185a700Sflorian 	 * Set up formatting options for single-line output.
5515185a700Sflorian 	 */
5525185a700Sflorian 	tctx.origin = origin;
5535185a700Sflorian 	tctx.flags = 0;
5545185a700Sflorian 	tctx.width = 60;
5555185a700Sflorian 	tctx.linebreak = " ";
5565185a700Sflorian 	return (rdata_totext(rdata, &tctx, target));
5575185a700Sflorian }
5585185a700Sflorian 
5595185a700Sflorian isc_result_t
dns_rdata_tofmttext(dns_rdata_t * rdata,dns_name_t * origin,unsigned int flags,unsigned int width,unsigned int split_width,const char * linebreak,isc_buffer_t * target)5605185a700Sflorian dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
5615185a700Sflorian 		    unsigned int flags, unsigned int width,
5625185a700Sflorian 		    unsigned int split_width, const char *linebreak,
5635185a700Sflorian 		    isc_buffer_t *target)
5645185a700Sflorian {
5655185a700Sflorian 	dns_rdata_textctx_t tctx;
5665185a700Sflorian 
5675185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
5685185a700Sflorian 
5695185a700Sflorian 	/*
5705185a700Sflorian 	 * Set up formatting options for formatted output.
5715185a700Sflorian 	 */
5725185a700Sflorian 	tctx.origin = origin;
5735185a700Sflorian 	tctx.flags = flags;
5745185a700Sflorian 	if (split_width == 0xffffffff)
5755185a700Sflorian 		tctx.width = width;
5765185a700Sflorian 	else
5775185a700Sflorian 		tctx.width = split_width;
5785185a700Sflorian 
5795185a700Sflorian 	if ((flags & DNS_STYLEFLAG_MULTILINE) != 0)
5805185a700Sflorian 		tctx.linebreak = linebreak;
5815185a700Sflorian 	else {
5825185a700Sflorian 		if (split_width == 0xffffffff)
5835185a700Sflorian 			tctx.width = 60; /* Used for hex word length only. */
5845185a700Sflorian 		tctx.linebreak = " ";
5855185a700Sflorian 	}
5865185a700Sflorian 	return (rdata_totext(rdata, &tctx, target));
5875185a700Sflorian }
5885185a700Sflorian 
5895185a700Sflorian isc_result_t
dns_rdata_fromstruct_soa(dns_rdata_t * rdata,dns_rdataclass_t rdclass,dns_rdatatype_t type,dns_rdata_soa_t * soa,isc_buffer_t * target)590a5525167Sflorian dns_rdata_fromstruct_soa(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
591a5525167Sflorian 		     dns_rdatatype_t type, dns_rdata_soa_t *soa,
5925185a700Sflorian 		     isc_buffer_t *target)
5935185a700Sflorian {
5945185a700Sflorian 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
5955185a700Sflorian 	isc_buffer_t st;
5965185a700Sflorian 	isc_region_t region;
5975185a700Sflorian 	unsigned int length;
5985185a700Sflorian 
599a5525167Sflorian 	REQUIRE(soa != NULL);
6005185a700Sflorian 	if (rdata != NULL) {
6015185a700Sflorian 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
6025185a700Sflorian 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
6035185a700Sflorian 	}
6045185a700Sflorian 
6055185a700Sflorian 	st = *target;
606a5525167Sflorian 	result = fromstruct_soa(rdclass, type, soa, target);
6075185a700Sflorian 
608a5525167Sflorian 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
609a5525167Sflorian 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
610a5525167Sflorian 		result = ISC_R_NOSPACE;
6115185a700Sflorian 
612a5525167Sflorian 	if (rdata != NULL && result == ISC_R_SUCCESS) {
613a5525167Sflorian 		region.base = isc_buffer_used(&st);
614a5525167Sflorian 		region.length = length;
615a5525167Sflorian 		dns_rdata_fromregion(rdata, rdclass, type, &region);
616a5525167Sflorian 	}
617a5525167Sflorian 	if (result != ISC_R_SUCCESS)
618a5525167Sflorian 		*target = st;
619a5525167Sflorian 	return (result);
620a5525167Sflorian }
621a5525167Sflorian 
622a5525167Sflorian isc_result_t
dns_rdata_fromstruct_tsig(dns_rdata_t * rdata,dns_rdataclass_t rdclass,dns_rdatatype_t type,dns_rdata_any_tsig_t * tsig,isc_buffer_t * target)623a5525167Sflorian dns_rdata_fromstruct_tsig(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
624a5525167Sflorian 		     dns_rdatatype_t type, dns_rdata_any_tsig_t *tsig,
625a5525167Sflorian 		     isc_buffer_t *target)
626a5525167Sflorian {
627a5525167Sflorian 	isc_result_t result = ISC_R_NOTIMPLEMENTED;
628a5525167Sflorian 	isc_buffer_t st;
629a5525167Sflorian 	isc_region_t region;
630a5525167Sflorian 	unsigned int length;
631a5525167Sflorian 
632a5525167Sflorian 	REQUIRE(tsig != NULL);
633a5525167Sflorian 	if (rdata != NULL) {
634a5525167Sflorian 		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
635a5525167Sflorian 		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
636a5525167Sflorian 	}
637a5525167Sflorian 
638a5525167Sflorian 	st = *target;
639a5525167Sflorian 	result = fromstruct_any_tsig(rdclass, type, tsig, target);
6405185a700Sflorian 
6415185a700Sflorian 	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
6425185a700Sflorian 	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
6435185a700Sflorian 		result = ISC_R_NOSPACE;
6445185a700Sflorian 
6455185a700Sflorian 	if (rdata != NULL && result == ISC_R_SUCCESS) {
6465185a700Sflorian 		region.base = isc_buffer_used(&st);
6475185a700Sflorian 		region.length = length;
6485185a700Sflorian 		dns_rdata_fromregion(rdata, rdclass, type, &region);
6495185a700Sflorian 	}
6505185a700Sflorian 	if (result != ISC_R_SUCCESS)
6515185a700Sflorian 		*target = st;
6525185a700Sflorian 	return (result);
6535185a700Sflorian }
6545185a700Sflorian 
6555185a700Sflorian isc_result_t
dns_rdata_tostruct_cname(const dns_rdata_t * rdata,dns_rdata_cname_t * cname)656ee21177aSflorian dns_rdata_tostruct_cname(const dns_rdata_t *rdata, dns_rdata_cname_t *cname) {
6575185a700Sflorian 	REQUIRE(rdata != NULL);
6585185a700Sflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
6595185a700Sflorian 
660ee21177aSflorian 	return (tostruct_cname(rdata, cname));
661ee21177aSflorian }
6625185a700Sflorian 
663ee21177aSflorian isc_result_t
dns_rdata_tostruct_ns(const dns_rdata_t * rdata,dns_rdata_ns_t * ns)664ee21177aSflorian dns_rdata_tostruct_ns(const dns_rdata_t *rdata, dns_rdata_ns_t *ns) {
665ee21177aSflorian 	REQUIRE(rdata != NULL);
666ee21177aSflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
6675185a700Sflorian 
668ee21177aSflorian 	return (tostruct_ns(rdata, ns));
669ee21177aSflorian }
670ee21177aSflorian 
671ee21177aSflorian isc_result_t
dns_rdata_tostruct_soa(const dns_rdata_t * rdata,dns_rdata_soa_t * soa)672ee21177aSflorian dns_rdata_tostruct_soa(const dns_rdata_t *rdata, dns_rdata_soa_t *soa) {
673ee21177aSflorian 	REQUIRE(rdata != NULL);
674ee21177aSflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
675ee21177aSflorian 
676ee21177aSflorian 	return (tostruct_soa(rdata, soa));
677ee21177aSflorian }
678ee21177aSflorian 
679ee21177aSflorian isc_result_t
dns_rdata_tostruct_tsig(const dns_rdata_t * rdata,dns_rdata_any_tsig_t * tsig)680ee21177aSflorian dns_rdata_tostruct_tsig(const dns_rdata_t *rdata, dns_rdata_any_tsig_t *tsig) {
681ee21177aSflorian 	REQUIRE(rdata != NULL);
682ee21177aSflorian 	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
683ee21177aSflorian 
684ee21177aSflorian 	return (tostruct_any_tsig(rdata, tsig));
6855185a700Sflorian }
6865185a700Sflorian 
6875185a700Sflorian void
dns_rdata_freestruct_cname(dns_rdata_cname_t * cname)688a0b66ce4Sflorian dns_rdata_freestruct_cname(dns_rdata_cname_t *cname) {
689a0b66ce4Sflorian 	REQUIRE(cname != NULL);
6905185a700Sflorian 
691a0b66ce4Sflorian 	freestruct_cname(cname);
692a0b66ce4Sflorian }
693a0b66ce4Sflorian 
694a0b66ce4Sflorian void
dns_rdata_freestruct_ns(dns_rdata_ns_t * ns)695a0b66ce4Sflorian dns_rdata_freestruct_ns(dns_rdata_ns_t *ns) {
696a0b66ce4Sflorian 	REQUIRE(ns != NULL);
697a0b66ce4Sflorian 
698a0b66ce4Sflorian 	freestruct_ns(ns);
699a0b66ce4Sflorian }
700a0b66ce4Sflorian 
701a0b66ce4Sflorian void
dns_rdata_freestruct_soa(dns_rdata_soa_t * soa)702a0b66ce4Sflorian dns_rdata_freestruct_soa(dns_rdata_soa_t *soa) {
703a0b66ce4Sflorian 	REQUIRE(soa != NULL);
704a0b66ce4Sflorian 
705a0b66ce4Sflorian 	freestruct_soa(soa);
706a0b66ce4Sflorian }
707a0b66ce4Sflorian 
708a0b66ce4Sflorian void
dns_rdata_freestruct_tsig(dns_rdata_any_tsig_t * tsig)709a0b66ce4Sflorian dns_rdata_freestruct_tsig(dns_rdata_any_tsig_t *tsig) {
710a0b66ce4Sflorian 	REQUIRE(tsig != NULL);
711a0b66ce4Sflorian 
712a0b66ce4Sflorian 	freestruct_any_tsig(tsig);
7135185a700Sflorian }
7145185a700Sflorian 
7151fb015a8Sflorian int
dns_rdata_checkowner_nsec3(dns_name_t * name,dns_rdataclass_t rdclass,dns_rdatatype_t type,int wildcard)71666d1673bSflorian dns_rdata_checkowner_nsec3(dns_name_t *name, dns_rdataclass_t rdclass,
7171fb015a8Sflorian 		     dns_rdatatype_t type, int wildcard)
7185185a700Sflorian {
71966d1673bSflorian 	return checkowner_nsec3(name, rdclass, type, wildcard);
7205185a700Sflorian }
7215185a700Sflorian 
7225185a700Sflorian unsigned int
dns_rdatatype_attributes(dns_rdatatype_t type)7235185a700Sflorian dns_rdatatype_attributes(dns_rdatatype_t type)
7245185a700Sflorian {
725a6fa6f7aSflorian 	switch (type) {
726a6fa6f7aSflorian 	case 0:
727a6fa6f7aSflorian 	case 31:
728a6fa6f7aSflorian 	case 32:
729a6fa6f7aSflorian 	case 34:
730a6fa6f7aSflorian 	case 100:
731a6fa6f7aSflorian 	case 101:
732a6fa6f7aSflorian 	case 102:
733a6fa6f7aSflorian 		return (DNS_RDATATYPEATTR_RESERVED);
734abb8b8a3Sflorian 	default:
735abb8b8a3Sflorian 		return (0);
736a6fa6f7aSflorian 	}
7375185a700Sflorian }
7385185a700Sflorian 
7399e6f49f3Sflorian static int
type_cmp(const void * k,const void * e)7409e6f49f3Sflorian type_cmp(const void *k, const void *e)
7419e6f49f3Sflorian {
7429e6f49f3Sflorian 	return (strcasecmp(k, ((const dns_rdata_type_lookup_t *)e)->type));
7439e6f49f3Sflorian }
7449e6f49f3Sflorian 
7455185a700Sflorian isc_result_t
dns_rdatatype_fromtext(dns_rdatatype_t * typep,isc_textregion_t * source)7465185a700Sflorian dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
7479e6f49f3Sflorian 	/* This has to be sorted always. */
7489e6f49f3Sflorian 	static const dns_rdata_type_lookup_t type_lookup[] = {
7499e6f49f3Sflorian 		{"a",		1},
7509e6f49f3Sflorian 		{"a6",		38},
7519e6f49f3Sflorian 		{"aaaa",	28},
7529e6f49f3Sflorian 		{"afsdb",	18},
7539e6f49f3Sflorian 		{"any",		255},
7549e6f49f3Sflorian 		{"apl",		42},
7559e6f49f3Sflorian 		{"atma",	34},
7569e6f49f3Sflorian 		{"avc",		258},
7579e6f49f3Sflorian 		{"axfr",	252},
7589e6f49f3Sflorian 		{"caa",		257},
7599e6f49f3Sflorian 		{"cdnskey",	60},
7609e6f49f3Sflorian 		{"cds",		59},
7619e6f49f3Sflorian 		{"cert",	37},
7629e6f49f3Sflorian 		{"cname",	5},
7639e6f49f3Sflorian 		{"csync",	62},
7649e6f49f3Sflorian 		{"dhcid",	49},
7659e6f49f3Sflorian 		{"dlv",		32769},
7669e6f49f3Sflorian 		{"dname",	39},
7679e6f49f3Sflorian 		{"dnskey",	48},
7689e6f49f3Sflorian 		{"doa",		259},
7699e6f49f3Sflorian 		{"ds",		43},
7709e6f49f3Sflorian 		{"eid",		31},
7719e6f49f3Sflorian 		{"eui48",	108},
7729e6f49f3Sflorian 		{"eui64",	109},
7739e6f49f3Sflorian 		{"gid",		102},
7749e6f49f3Sflorian 		{"gpos",	27},
7759e6f49f3Sflorian 		{"hinfo",	13},
7769e6f49f3Sflorian 		{"hip",		55},
77738bad3e5Sflorian 		{"https",	65},
7789e6f49f3Sflorian 		{"ipseckey",	45},
7799e6f49f3Sflorian 		{"isdn",	20},
7809e6f49f3Sflorian 		{"ixfr",	251},
7819e6f49f3Sflorian 		{"key",		25},
7829e6f49f3Sflorian 		{"keydata",	65533},
7839e6f49f3Sflorian 		{"kx",		36},
7849e6f49f3Sflorian 		{"l32",		105},
7859e6f49f3Sflorian 		{"l64",		106},
7869e6f49f3Sflorian 		{"loc",		29},
7879e6f49f3Sflorian 		{"lp",		107},
7889e6f49f3Sflorian 		{"maila",	254},
7899e6f49f3Sflorian 		{"mailb",	253},
7909e6f49f3Sflorian 		{"mb",		7},
7919e6f49f3Sflorian 		{"md",		3},
7929e6f49f3Sflorian 		{"mf",		4},
7939e6f49f3Sflorian 		{"mg",		8},
7949e6f49f3Sflorian 		{"minfo",	14},
7959e6f49f3Sflorian 		{"mr",		9},
7969e6f49f3Sflorian 		{"mx",		15},
7979e6f49f3Sflorian 		{"naptr",	35},
7989e6f49f3Sflorian 		{"nid",		104},
7999e6f49f3Sflorian 		{"nimloc",	32},
8009e6f49f3Sflorian 		{"ninfo",	56},
8019e6f49f3Sflorian 		{"ns",		2},
8029e6f49f3Sflorian 		{"nsap",	22},
8039e6f49f3Sflorian 		{"nsap-ptr",	23},
8049e6f49f3Sflorian 		{"nsec",	47},
8059e6f49f3Sflorian 		{"nsec3",	50},
8069e6f49f3Sflorian 		{"nsec3param",	51},
8079e6f49f3Sflorian 		{"null",	10},
8089e6f49f3Sflorian 		{"nxt",		30},
8099e6f49f3Sflorian 		{"openpgpkey",	61},
8109e6f49f3Sflorian 		{"opt",		41},
8119e6f49f3Sflorian 		{"ptr",		12},
8129e6f49f3Sflorian 		{"px",		26},
8139e6f49f3Sflorian 		{"reserved0",	0},
8149e6f49f3Sflorian 		{"rkey",	57},
8159e6f49f3Sflorian 		{"rp",		17},
8169e6f49f3Sflorian 		{"rrsig",	46},
8179e6f49f3Sflorian 		{"rt",		21},
8189e6f49f3Sflorian 		{"sig",		24},
8199e6f49f3Sflorian 		{"sink",	40},
8209e6f49f3Sflorian 		{"smimea",	53},
8219e6f49f3Sflorian 		{"soa",		6},
8229e6f49f3Sflorian 		{"spf",		99},
8239e6f49f3Sflorian 		{"srv",		33},
8249e6f49f3Sflorian 		{"sshfp",	44},
82538bad3e5Sflorian 		{"svcb",	64},
8269e6f49f3Sflorian 		{"ta",		32768},
8279e6f49f3Sflorian 		{"talink",	58},
8289e6f49f3Sflorian 		{"tkey",	249},
8299e6f49f3Sflorian 		{"tlsa",	52},
8309e6f49f3Sflorian 		{"tsig",	250},
8319e6f49f3Sflorian 		{"txt",		16},
8329e6f49f3Sflorian 		{"uid",		101},
8339e6f49f3Sflorian 		{"uinfo",	100},
8349e6f49f3Sflorian 		{"unspec",	103},
8359e6f49f3Sflorian 		{"uri",		256},
8369e6f49f3Sflorian 		{"wks",		11},
837a944512fSflorian 		{"x25",		19},
838a944512fSflorian 		{"zonemd",	63},
8399e6f49f3Sflorian 	};
8409e6f49f3Sflorian 	const dns_rdata_type_lookup_t *p;
8415185a700Sflorian 	unsigned int n;
8429e6f49f3Sflorian 	char lookup[sizeof("nsec3param")];
8435185a700Sflorian 
8445185a700Sflorian 	n = source->length;
8455185a700Sflorian 
8465185a700Sflorian 	if (n == 0)
8475185a700Sflorian 		return (DNS_R_UNKNOWN);
8485185a700Sflorian 
8499e6f49f3Sflorian 	/* source->base is not required to be NUL terminated. */
8509e6f49f3Sflorian 	if ((size_t)snprintf(lookup, sizeof(lookup), "%.*s", n, source->base)
8519e6f49f3Sflorian 	    >= sizeof(lookup))
8529e6f49f3Sflorian 		return (DNS_R_UNKNOWN);
8535185a700Sflorian 
8549e6f49f3Sflorian 	p = bsearch(lookup, type_lookup,
8559e6f49f3Sflorian 	    sizeof(type_lookup)/sizeof(type_lookup[0]), sizeof(type_lookup[0]),
8569e6f49f3Sflorian 	    type_cmp);
8575185a700Sflorian 
8589e6f49f3Sflorian 	if (p) {
8599e6f49f3Sflorian 		if ((dns_rdatatype_attributes(p->val) &
8609e6f49f3Sflorian 		    DNS_RDATATYPEATTR_RESERVED) != 0)
8619e6f49f3Sflorian 			return (ISC_R_NOTIMPLEMENTED);
8629e6f49f3Sflorian 		*typep = p->val;
8639e6f49f3Sflorian 		return (ISC_R_SUCCESS);
8649e6f49f3Sflorian 	}
8655185a700Sflorian 
8669e6f49f3Sflorian 	if (n > 4 && strncasecmp("type", lookup, 4) == 0) {
8679e6f49f3Sflorian 		int val;
8689e6f49f3Sflorian 		const char *errstr;
8699e6f49f3Sflorian 		val = strtonum(lookup + 4, 0, UINT16_MAX, &errstr);
8709e6f49f3Sflorian 		if (errstr == NULL) {
8719e6f49f3Sflorian 			*typep = val;
8725185a700Sflorian 			return (ISC_R_SUCCESS);
8735185a700Sflorian 		}
8745185a700Sflorian 	}
8755185a700Sflorian 
8765185a700Sflorian 	return (DNS_R_UNKNOWN);
8775185a700Sflorian }
8785185a700Sflorian 
8795185a700Sflorian isc_result_t
dns_rdatatype_totext(dns_rdatatype_t type,isc_buffer_t * target)8805185a700Sflorian dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
8815185a700Sflorian 	char buf[sizeof("TYPE65535")];
8825185a700Sflorian 
883a6fa6f7aSflorian 	switch (type) {
884a6fa6f7aSflorian 	case 0:
885873f12b9Sflorian 		return (isc_str_tobuffer("RESERVED0", target));
886a6fa6f7aSflorian 	case 1:
887873f12b9Sflorian 		return (isc_str_tobuffer("A", target));
888a6fa6f7aSflorian 	case 2:
889873f12b9Sflorian 		return (isc_str_tobuffer("NS", target));
890a6fa6f7aSflorian 	case 3:
891873f12b9Sflorian 		return (isc_str_tobuffer("MD", target));
892a6fa6f7aSflorian 	case 4:
893873f12b9Sflorian 		return (isc_str_tobuffer("MF", target));
894a6fa6f7aSflorian 	case 5:
895873f12b9Sflorian 		return (isc_str_tobuffer("CNAME", target));
896a6fa6f7aSflorian 	case 6:
897873f12b9Sflorian 		return (isc_str_tobuffer("SOA", target));
898a6fa6f7aSflorian 	case 7:
899873f12b9Sflorian 		return (isc_str_tobuffer("MB", target));
900a6fa6f7aSflorian 	case 8:
901873f12b9Sflorian 		return (isc_str_tobuffer("MG", target));
902a6fa6f7aSflorian 	case 9:
903873f12b9Sflorian 		return (isc_str_tobuffer("MR", target));
904a6fa6f7aSflorian 	case 10:
905873f12b9Sflorian 		return (isc_str_tobuffer("NULL", target));
906a6fa6f7aSflorian 	case 11:
907873f12b9Sflorian 		return (isc_str_tobuffer("WKS", target));
908a6fa6f7aSflorian 	case 12:
909873f12b9Sflorian 		return (isc_str_tobuffer("PTR", target));
910a6fa6f7aSflorian 	case 13:
911873f12b9Sflorian 		return (isc_str_tobuffer("HINFO", target));
912a6fa6f7aSflorian 	case 14:
913873f12b9Sflorian 		return (isc_str_tobuffer("MINFO", target));
914a6fa6f7aSflorian 	case 15:
915873f12b9Sflorian 		return (isc_str_tobuffer("MX", target));
916a6fa6f7aSflorian 	case 16:
917873f12b9Sflorian 		return (isc_str_tobuffer("TXT", target));
918a6fa6f7aSflorian 	case 17:
919873f12b9Sflorian 		return (isc_str_tobuffer("RP", target));
920a6fa6f7aSflorian 	case 18:
921873f12b9Sflorian 		return (isc_str_tobuffer("AFSDB", target));
922a6fa6f7aSflorian 	case 19:
923873f12b9Sflorian 		return (isc_str_tobuffer("X25", target));
924a6fa6f7aSflorian 	case 20:
925873f12b9Sflorian 		return (isc_str_tobuffer("ISDN", target));
926a6fa6f7aSflorian 	case 21:
927873f12b9Sflorian 		return (isc_str_tobuffer("RT", target));
928a6fa6f7aSflorian 	case 22:
929873f12b9Sflorian 		return (isc_str_tobuffer("NSAP", target));
930a6fa6f7aSflorian 	case 23:
931873f12b9Sflorian 		return (isc_str_tobuffer("NSAP-PTR", target));
932a6fa6f7aSflorian 	case 24:
933873f12b9Sflorian 		return (isc_str_tobuffer("SIG", target));
934a6fa6f7aSflorian 	case 25:
935873f12b9Sflorian 		return (isc_str_tobuffer("KEY", target));
936a6fa6f7aSflorian 	case 26:
937873f12b9Sflorian 		return (isc_str_tobuffer("PX", target));
938a6fa6f7aSflorian 	case 27:
939873f12b9Sflorian 		return (isc_str_tobuffer("GPOS", target));
940a6fa6f7aSflorian 	case 28:
941873f12b9Sflorian 		return (isc_str_tobuffer("AAAA", target));
942a6fa6f7aSflorian 	case 29:
943873f12b9Sflorian 		return (isc_str_tobuffer("LOC", target));
944a6fa6f7aSflorian 	case 30:
945873f12b9Sflorian 		return (isc_str_tobuffer("NXT", target));
946a6fa6f7aSflorian 	case 31:
947873f12b9Sflorian 		return (isc_str_tobuffer("EID", target));
948a6fa6f7aSflorian 	case 32:
949873f12b9Sflorian 		return (isc_str_tobuffer("NIMLOC", target));
950a6fa6f7aSflorian 	case 33:
951873f12b9Sflorian 		return (isc_str_tobuffer("SRV", target));
952a6fa6f7aSflorian 	case 34:
953873f12b9Sflorian 		return (isc_str_tobuffer("ATMA", target));
954a6fa6f7aSflorian 	case 35:
955873f12b9Sflorian 		return (isc_str_tobuffer("NAPTR", target));
956a6fa6f7aSflorian 	case 36:
957873f12b9Sflorian 		return (isc_str_tobuffer("KX", target));
958a6fa6f7aSflorian 	case 37:
959873f12b9Sflorian 		return (isc_str_tobuffer("CERT", target));
960a6fa6f7aSflorian 	case 38:
961873f12b9Sflorian 		return (isc_str_tobuffer("A6", target));
962a6fa6f7aSflorian 	case 39:
963873f12b9Sflorian 		return (isc_str_tobuffer("DNAME", target));
964a6fa6f7aSflorian 	case 40:
965873f12b9Sflorian 		return (isc_str_tobuffer("SINK", target));
966a6fa6f7aSflorian 	case 41:
967873f12b9Sflorian 		return (isc_str_tobuffer("OPT", target));
968a6fa6f7aSflorian 	case 42:
969873f12b9Sflorian 		return (isc_str_tobuffer("APL", target));
970a6fa6f7aSflorian 	case 43:
971873f12b9Sflorian 		return (isc_str_tobuffer("DS", target));
972a6fa6f7aSflorian 	case 44:
973873f12b9Sflorian 		return (isc_str_tobuffer("SSHFP", target));
974a6fa6f7aSflorian 	case 45:
975873f12b9Sflorian 		return (isc_str_tobuffer("IPSECKEY", target));
976a6fa6f7aSflorian 	case 46:
977873f12b9Sflorian 		return (isc_str_tobuffer("RRSIG", target));
978a6fa6f7aSflorian 	case 47:
979873f12b9Sflorian 		return (isc_str_tobuffer("NSEC", target));
980a6fa6f7aSflorian 	case 48:
981873f12b9Sflorian 		return (isc_str_tobuffer("DNSKEY", target));
982a6fa6f7aSflorian 	case 49:
983873f12b9Sflorian 		return (isc_str_tobuffer("DHCID", target));
984a6fa6f7aSflorian 	case 50:
985873f12b9Sflorian 		return (isc_str_tobuffer("NSEC3", target));
986a6fa6f7aSflorian 	case 51:
987873f12b9Sflorian 		return (isc_str_tobuffer("NSEC3PARAM", target));
988a6fa6f7aSflorian 	case 52:
989873f12b9Sflorian 		return (isc_str_tobuffer("TLSA", target));
990a6fa6f7aSflorian 	case 53:
991873f12b9Sflorian 		return (isc_str_tobuffer("SMIMEA", target));
992a6fa6f7aSflorian 	case 55:
993873f12b9Sflorian 		return (isc_str_tobuffer("HIP", target));
994a6fa6f7aSflorian 	case 56:
995873f12b9Sflorian 		return (isc_str_tobuffer("NINFO", target));
996a6fa6f7aSflorian 	case 57:
997873f12b9Sflorian 		return (isc_str_tobuffer("RKEY", target));
998a6fa6f7aSflorian 	case 58:
999873f12b9Sflorian 		return (isc_str_tobuffer("TALINK", target));
1000a6fa6f7aSflorian 	case 59:
1001873f12b9Sflorian 		return (isc_str_tobuffer("CDS", target));
1002a6fa6f7aSflorian 	case 60:
1003873f12b9Sflorian 		return (isc_str_tobuffer("CDNSKEY", target));
1004a6fa6f7aSflorian 	case 61:
1005873f12b9Sflorian 		return (isc_str_tobuffer("OPENPGPKEY", target));
1006a6fa6f7aSflorian 	case 62:
1007873f12b9Sflorian 		return (isc_str_tobuffer("CSYNC", target));
1008a944512fSflorian 	case 63:
1009a944512fSflorian 		return (isc_str_tobuffer("ZONEMD", target));
101038bad3e5Sflorian 	case 64:
101138bad3e5Sflorian 		return (isc_str_tobuffer("SVCB", target));
101238bad3e5Sflorian 	case 65:
101338bad3e5Sflorian 		return (isc_str_tobuffer("HTTPS", target));
1014a6fa6f7aSflorian 	case 99:
1015873f12b9Sflorian 		return (isc_str_tobuffer("SPF", target));
1016a6fa6f7aSflorian 	case 100:
1017873f12b9Sflorian 		return (isc_str_tobuffer("UINFO", target));
1018a6fa6f7aSflorian 	case 101:
1019873f12b9Sflorian 		return (isc_str_tobuffer("UID", target));
1020a6fa6f7aSflorian 	case 102:
1021873f12b9Sflorian 		return (isc_str_tobuffer("GID", target));
1022a6fa6f7aSflorian 	case 103:
1023873f12b9Sflorian 		return (isc_str_tobuffer("UNSPEC", target));
1024a6fa6f7aSflorian 	case 104:
1025873f12b9Sflorian 		return (isc_str_tobuffer("NID", target));
1026a6fa6f7aSflorian 	case 105:
1027873f12b9Sflorian 		return (isc_str_tobuffer("L32", target));
1028a6fa6f7aSflorian 	case 106:
1029873f12b9Sflorian 		return (isc_str_tobuffer("L64", target));
1030a6fa6f7aSflorian 	case 107:
1031873f12b9Sflorian 		return (isc_str_tobuffer("LP", target));
1032a6fa6f7aSflorian 	case 108:
1033873f12b9Sflorian 		return (isc_str_tobuffer("EUI48", target));
1034a6fa6f7aSflorian 	case 109:
1035873f12b9Sflorian 		return (isc_str_tobuffer("EUI64", target));
1036a6fa6f7aSflorian 	case 249:
1037873f12b9Sflorian 		return (isc_str_tobuffer("TKEY", target));
1038a6fa6f7aSflorian 	case 250:
1039873f12b9Sflorian 		return (isc_str_tobuffer("TSIG", target));
1040a6fa6f7aSflorian 	case 251:
1041873f12b9Sflorian 		return (isc_str_tobuffer("IXFR", target));
1042a6fa6f7aSflorian 	case 252:
1043873f12b9Sflorian 		return (isc_str_tobuffer("AXFR", target));
1044a6fa6f7aSflorian 	case 253:
1045873f12b9Sflorian 		return (isc_str_tobuffer("MAILB", target));
1046a6fa6f7aSflorian 	case 254:
1047873f12b9Sflorian 		return (isc_str_tobuffer("MAILA", target));
1048a6fa6f7aSflorian 	case 255:
1049873f12b9Sflorian 		return (isc_str_tobuffer("ANY", target));
1050a6fa6f7aSflorian 	case 256:
1051873f12b9Sflorian 		return (isc_str_tobuffer("URI", target));
1052a6fa6f7aSflorian 	case 257:
1053873f12b9Sflorian 		return (isc_str_tobuffer("CAA", target));
1054a6fa6f7aSflorian 	case 258:
1055873f12b9Sflorian 		return (isc_str_tobuffer("AVC", target));
1056a6fa6f7aSflorian 	case 259:
1057873f12b9Sflorian 		return (isc_str_tobuffer("DOA", target));
1058a6fa6f7aSflorian 	case 32768:
1059873f12b9Sflorian 		return (isc_str_tobuffer("TA", target));
1060a6fa6f7aSflorian 	case 32769:
1061873f12b9Sflorian 		return (isc_str_tobuffer("DLV", target));
1062a6fa6f7aSflorian 	default:
10635185a700Sflorian 		snprintf(buf, sizeof(buf), "TYPE%u", type);
1064873f12b9Sflorian 		return (isc_str_tobuffer(buf, target));
10655185a700Sflorian 	}
1066a6fa6f7aSflorian }
10675185a700Sflorian 
10685185a700Sflorian void
dns_rdatatype_format(dns_rdatatype_t rdtype,char * array,unsigned int size)10695185a700Sflorian dns_rdatatype_format(dns_rdatatype_t rdtype,
10705185a700Sflorian 		     char *array, unsigned int size)
10715185a700Sflorian {
10725185a700Sflorian 	isc_result_t result;
10735185a700Sflorian 	isc_buffer_t buf;
10745185a700Sflorian 
10755185a700Sflorian 	if (size == 0U)
10765185a700Sflorian 		return;
10775185a700Sflorian 
10785185a700Sflorian 	isc_buffer_init(&buf, array, size);
10795185a700Sflorian 	result = dns_rdatatype_totext(rdtype, &buf);
10805185a700Sflorian 	/*
10815185a700Sflorian 	 * Null terminate.
10825185a700Sflorian 	 */
10835185a700Sflorian 	if (result == ISC_R_SUCCESS) {
10845185a700Sflorian 		if (isc_buffer_availablelength(&buf) >= 1)
10855185a700Sflorian 			isc_buffer_putuint8(&buf, 0);
10865185a700Sflorian 		else
10875185a700Sflorian 			result = ISC_R_NOSPACE;
10885185a700Sflorian 	}
10895185a700Sflorian 	if (result != ISC_R_SUCCESS)
10905185a700Sflorian 		strlcpy(array, "<unknown>", size);
10915185a700Sflorian }
10925185a700Sflorian 
10935185a700Sflorian /*
10945185a700Sflorian  * Private function.
10955185a700Sflorian  */
10965185a700Sflorian 
10975185a700Sflorian static unsigned int
name_length(dns_name_t * name)10985185a700Sflorian name_length(dns_name_t *name) {
10995185a700Sflorian 	return (name->length);
11005185a700Sflorian }
11015185a700Sflorian 
11025185a700Sflorian static isc_result_t
txt_totext(isc_region_t * source,int quote,isc_buffer_t * target)11031fb015a8Sflorian txt_totext(isc_region_t *source, int quote, isc_buffer_t *target) {
11045185a700Sflorian 	unsigned int tl;
11055185a700Sflorian 	unsigned int n;
11065185a700Sflorian 	unsigned char *sp;
11075185a700Sflorian 	char *tp;
11085185a700Sflorian 	isc_region_t region;
11095185a700Sflorian 
11105185a700Sflorian 	isc_buffer_availableregion(target, &region);
11115185a700Sflorian 	sp = source->base;
11125185a700Sflorian 	tp = (char *)region.base;
11135185a700Sflorian 	tl = region.length;
11145185a700Sflorian 
11155185a700Sflorian 	n = *sp++;
11165185a700Sflorian 
11175185a700Sflorian 	REQUIRE(n + 1 <= source->length);
11185185a700Sflorian 	if (n == 0U)
11191fb015a8Sflorian 		REQUIRE(quote);
11205185a700Sflorian 
11215185a700Sflorian 	if (quote) {
11225185a700Sflorian 		if (tl < 1)
11235185a700Sflorian 			return (ISC_R_NOSPACE);
11245185a700Sflorian 		*tp++ = '"';
11255185a700Sflorian 		tl--;
11265185a700Sflorian 	}
11275185a700Sflorian 	while (n--) {
11285185a700Sflorian 		/*
11295185a700Sflorian 		 * \DDD space (0x20) if not quoting.
11305185a700Sflorian 		 */
11315185a700Sflorian 		if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) {
11325185a700Sflorian 			if (tl < 4)
11335185a700Sflorian 				return (ISC_R_NOSPACE);
11345185a700Sflorian 			*tp++ = 0x5c;
11355185a700Sflorian 			*tp++ = 0x30 + ((*sp / 100) % 10);
11365185a700Sflorian 			*tp++ = 0x30 + ((*sp / 10) % 10);
11375185a700Sflorian 			*tp++ = 0x30 + (*sp % 10);
11385185a700Sflorian 			sp++;
11395185a700Sflorian 			tl -= 4;
11405185a700Sflorian 			continue;
11415185a700Sflorian 		}
11425185a700Sflorian 		/*
11435185a700Sflorian 		 * Escape double quote and backslash.  If we are not
11445185a700Sflorian 		 * enclosing the string in double quotes also escape
11455185a700Sflorian 		 * at sign and semicolon.
11465185a700Sflorian 		 */
11475185a700Sflorian 		if (*sp == 0x22 || *sp == 0x5c ||
11485185a700Sflorian 		    (!quote && (*sp == 0x40 || *sp == 0x3b))) {
11495185a700Sflorian 			if (tl < 2)
11505185a700Sflorian 				return (ISC_R_NOSPACE);
11515185a700Sflorian 			*tp++ = '\\';
11525185a700Sflorian 			tl--;
11535185a700Sflorian 		}
11545185a700Sflorian 		if (tl < 1)
11555185a700Sflorian 			return (ISC_R_NOSPACE);
11565185a700Sflorian 		*tp++ = *sp++;
11575185a700Sflorian 		tl--;
11585185a700Sflorian 	}
11595185a700Sflorian 	if (quote) {
11605185a700Sflorian 		if (tl < 1)
11615185a700Sflorian 			return (ISC_R_NOSPACE);
11625185a700Sflorian 		*tp++ = '"';
11635185a700Sflorian 		tl--;
11645185a700Sflorian 		POST(tl);
11655185a700Sflorian 	}
11665185a700Sflorian 	isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
11675185a700Sflorian 	isc_region_consume(source, *source->base + 1);
11685185a700Sflorian 	return (ISC_R_SUCCESS);
11695185a700Sflorian }
11705185a700Sflorian 
11715185a700Sflorian static isc_result_t
txt_fromwire(isc_buffer_t * source,isc_buffer_t * target)11725185a700Sflorian txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
11735185a700Sflorian 	unsigned int n;
11745185a700Sflorian 	isc_region_t sregion;
11755185a700Sflorian 	isc_region_t tregion;
11765185a700Sflorian 
11775185a700Sflorian 	isc_buffer_activeregion(source, &sregion);
11785185a700Sflorian 	if (sregion.length == 0)
11795185a700Sflorian 		return (ISC_R_UNEXPECTEDEND);
11805185a700Sflorian 	n = *sregion.base + 1;
11815185a700Sflorian 	if (n > sregion.length)
11825185a700Sflorian 		return (ISC_R_UNEXPECTEDEND);
11835185a700Sflorian 
11845185a700Sflorian 	isc_buffer_availableregion(target, &tregion);
11855185a700Sflorian 	if (n > tregion.length)
11865185a700Sflorian 		return (ISC_R_NOSPACE);
11875185a700Sflorian 
11885185a700Sflorian 	if (tregion.base != sregion.base)
11895185a700Sflorian 		memmove(tregion.base, sregion.base, n);
11905185a700Sflorian 	isc_buffer_forward(source, n);
11915185a700Sflorian 	isc_buffer_add(target, n);
11925185a700Sflorian 	return (ISC_R_SUCCESS);
11935185a700Sflorian }
11945185a700Sflorian 
11955185a700Sflorian /*
11965185a700Sflorian  * Conversion of TXT-like rdata fields without length limits.
11975185a700Sflorian  */
11985185a700Sflorian static isc_result_t
multitxt_totext(isc_region_t * source,isc_buffer_t * target)11995185a700Sflorian multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
12005185a700Sflorian 	unsigned int tl;
12015185a700Sflorian 	unsigned int n0, n;
12025185a700Sflorian 	unsigned char *sp;
12035185a700Sflorian 	char *tp;
12045185a700Sflorian 	isc_region_t region;
12055185a700Sflorian 
12065185a700Sflorian 	isc_buffer_availableregion(target, &region);
12075185a700Sflorian 	sp = source->base;
12085185a700Sflorian 	tp = (char *)region.base;
12095185a700Sflorian 	tl = region.length;
12105185a700Sflorian 
12115185a700Sflorian 	if (tl < 1)
12125185a700Sflorian 		return (ISC_R_NOSPACE);
12135185a700Sflorian 	*tp++ = '"';
12145185a700Sflorian 	tl--;
12155185a700Sflorian 	do {
12165185a700Sflorian 		n = source->length;
12175185a700Sflorian 		n0 = source->length - 1;
12185185a700Sflorian 
12195185a700Sflorian 		while (n--) {
12205185a700Sflorian 			if (*sp < 0x20 || *sp >= 0x7f) {
12215185a700Sflorian 				if (tl < 4)
12225185a700Sflorian 					return (ISC_R_NOSPACE);
12235185a700Sflorian 				*tp++ = 0x5c;
12245185a700Sflorian 				*tp++ = 0x30 + ((*sp / 100) % 10);
12255185a700Sflorian 				*tp++ = 0x30 + ((*sp / 10) % 10);
12265185a700Sflorian 				*tp++ = 0x30 + (*sp % 10);
12275185a700Sflorian 				sp++;
12285185a700Sflorian 				tl -= 4;
12295185a700Sflorian 				continue;
12305185a700Sflorian 			}
12315185a700Sflorian 			/* double quote, backslash */
12325185a700Sflorian 			if (*sp == 0x22 || *sp == 0x5c) {
12335185a700Sflorian 				if (tl < 2)
12345185a700Sflorian 					return (ISC_R_NOSPACE);
12355185a700Sflorian 				*tp++ = '\\';
12365185a700Sflorian 				tl--;
12375185a700Sflorian 			}
12385185a700Sflorian 			if (tl < 1)
12395185a700Sflorian 				return (ISC_R_NOSPACE);
12405185a700Sflorian 			*tp++ = *sp++;
12415185a700Sflorian 			tl--;
12425185a700Sflorian 		}
12435185a700Sflorian 		isc_region_consume(source, n0 + 1);
12445185a700Sflorian 	} while (source->length != 0);
12455185a700Sflorian 	if (tl < 1)
12465185a700Sflorian 		return (ISC_R_NOSPACE);
12475185a700Sflorian 	*tp++ = '"';
12485185a700Sflorian 	tl--;
12495185a700Sflorian 	POST(tl);
12505185a700Sflorian 	isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
12515185a700Sflorian 	return (ISC_R_SUCCESS);
12525185a700Sflorian }
12535185a700Sflorian 
12541fb015a8Sflorian static int
name_prefix(dns_name_t * name,dns_name_t * origin,dns_name_t * target)12555185a700Sflorian name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
12565185a700Sflorian 	int l1, l2;
12575185a700Sflorian 
12585185a700Sflorian 	if (origin == NULL)
12595185a700Sflorian 		goto return_false;
12605185a700Sflorian 
12615185a700Sflorian 	if (dns_name_compare(origin, dns_rootname) == 0)
12625185a700Sflorian 		goto return_false;
12635185a700Sflorian 
12645185a700Sflorian 	if (!dns_name_issubdomain(name, origin))
12655185a700Sflorian 		goto return_false;
12665185a700Sflorian 
12675185a700Sflorian 	l1 = dns_name_countlabels(name);
12685185a700Sflorian 	l2 = dns_name_countlabels(origin);
12695185a700Sflorian 
12705185a700Sflorian 	if (l1 == l2)
12715185a700Sflorian 		goto return_false;
12725185a700Sflorian 
12735185a700Sflorian 	/* Master files should be case preserving. */
12745185a700Sflorian 	dns_name_getlabelsequence(name, l1 - l2, l2, target);
12755185a700Sflorian 	if (!dns_name_caseequal(origin, target))
12765185a700Sflorian 		goto return_false;
12775185a700Sflorian 
12785185a700Sflorian 	dns_name_getlabelsequence(name, 0, l1 - l2, target);
12791fb015a8Sflorian 	return (1);
12805185a700Sflorian 
12815185a700Sflorian return_false:
12825185a700Sflorian 	*target = *name;
12831fb015a8Sflorian 	return (0);
12845185a700Sflorian }
12855185a700Sflorian 
12865185a700Sflorian static isc_result_t
inet_totext(int af,isc_region_t * src,isc_buffer_t * target)12875185a700Sflorian inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
12885185a700Sflorian 	char tmpbuf[64];
12895185a700Sflorian 
12905185a700Sflorian 	/* Note - inet_ntop doesn't do size checking on its input. */
12915185a700Sflorian 	if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
12925185a700Sflorian 		return (ISC_R_NOSPACE);
12935185a700Sflorian 	if (strlen(tmpbuf) > isc_buffer_availablelength(target))
12945185a700Sflorian 		return (ISC_R_NOSPACE);
12955185a700Sflorian 	isc_buffer_putstr(target, tmpbuf);
12965185a700Sflorian 	return (ISC_R_SUCCESS);
12975185a700Sflorian }
12985185a700Sflorian 
12991fb015a8Sflorian static int
buffer_empty(isc_buffer_t * source)13005185a700Sflorian buffer_empty(isc_buffer_t *source) {
13011fb015a8Sflorian 	return((source->current == source->active) ? 1 : 0);
13025185a700Sflorian }
13035185a700Sflorian 
13045185a700Sflorian static isc_result_t
uint32_tobuffer(uint32_t value,isc_buffer_t * target)13055185a700Sflorian uint32_tobuffer(uint32_t value, isc_buffer_t *target) {
13065185a700Sflorian 	isc_region_t region;
13075185a700Sflorian 
13085185a700Sflorian 	isc_buffer_availableregion(target, &region);
13095185a700Sflorian 	if (region.length < 4)
13105185a700Sflorian 		return (ISC_R_NOSPACE);
13115185a700Sflorian 	isc_buffer_putuint32(target, value);
13125185a700Sflorian 	return (ISC_R_SUCCESS);
13135185a700Sflorian }
13145185a700Sflorian 
13155185a700Sflorian static isc_result_t
uint16_tobuffer(uint32_t value,isc_buffer_t * target)13165185a700Sflorian uint16_tobuffer(uint32_t value, isc_buffer_t *target) {
13175185a700Sflorian 	isc_region_t region;
13185185a700Sflorian 
13195185a700Sflorian 	if (value > 0xffff)
13205185a700Sflorian 		return (ISC_R_RANGE);
13215185a700Sflorian 	isc_buffer_availableregion(target, &region);
13225185a700Sflorian 	if (region.length < 2)
13235185a700Sflorian 		return (ISC_R_NOSPACE);
13245185a700Sflorian 	isc_buffer_putuint16(target, (uint16_t)value);
13255185a700Sflorian 	return (ISC_R_SUCCESS);
13265185a700Sflorian }
13275185a700Sflorian 
13285185a700Sflorian static isc_result_t
name_tobuffer(dns_name_t * name,isc_buffer_t * target)13295185a700Sflorian name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
13305185a700Sflorian 	isc_region_t r;
13315185a700Sflorian 	dns_name_toregion(name, &r);
13325185a700Sflorian 	return (isc_buffer_copyregion(target, &r));
13335185a700Sflorian }
13345185a700Sflorian 
13355185a700Sflorian static uint32_t
uint32_fromregion(isc_region_t * region)13365185a700Sflorian uint32_fromregion(isc_region_t *region) {
13375185a700Sflorian 	uint32_t value;
13385185a700Sflorian 
13395185a700Sflorian 	REQUIRE(region->length >= 4);
13405185a700Sflorian 	value = region->base[0] << 24;
13415185a700Sflorian 	value |= region->base[1] << 16;
13425185a700Sflorian 	value |= region->base[2] << 8;
13435185a700Sflorian 	value |= region->base[3];
13445185a700Sflorian 	return(value);
13455185a700Sflorian }
13465185a700Sflorian 
13475185a700Sflorian static uint16_t
uint16_fromregion(isc_region_t * region)13485185a700Sflorian uint16_fromregion(isc_region_t *region) {
13495185a700Sflorian 
13505185a700Sflorian 	REQUIRE(region->length >= 2);
13515185a700Sflorian 
13525185a700Sflorian 	return ((region->base[0] << 8) | region->base[1]);
13535185a700Sflorian }
13545185a700Sflorian 
13555185a700Sflorian static uint8_t
uint8_fromregion(isc_region_t * region)13565185a700Sflorian uint8_fromregion(isc_region_t *region) {
13575185a700Sflorian 
13585185a700Sflorian 	REQUIRE(region->length >= 1);
13595185a700Sflorian 
13605185a700Sflorian 	return (region->base[0]);
13615185a700Sflorian }
13625185a700Sflorian 
13635185a700Sflorian static uint8_t
uint8_consume_fromregion(isc_region_t * region)13645185a700Sflorian uint8_consume_fromregion(isc_region_t *region) {
13655185a700Sflorian 	uint8_t r = uint8_fromregion(region);
13665185a700Sflorian 
13675185a700Sflorian 	isc_region_consume(region, 1);
13685185a700Sflorian 	return r;
13695185a700Sflorian }
13705185a700Sflorian 
13715185a700Sflorian static const char atob_digits[86] =
13725185a700Sflorian 	"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
13735185a700Sflorian 	"abcdefghijklmnopqrstu";
13745185a700Sflorian /*
13755185a700Sflorian  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
13765185a700Sflorian  * Computes the number of bytes, and three kinds of simple checksums.
13775185a700Sflorian  * Incoming bytes are collected into 32-bit words, then printed in base 85:
13785185a700Sflorian  *	exp(85,5) > exp(2,32)
13795185a700Sflorian  * The ASCII characters used are between '!' and 'u';
13805185a700Sflorian  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
13815185a700Sflorian  *
13825185a700Sflorian  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
13835185a700Sflorian  * the atob/btoa programs, released with the compress program, in mod.sources.
13845185a700Sflorian  * Modified by Mike Schwartz 8/19/86 for use in BIND.
13855185a700Sflorian  * Modified to be re-entrant 3/2/99.
13865185a700Sflorian  */
13875185a700Sflorian 
13885185a700Sflorian struct state {
13895185a700Sflorian 	int32_t Ceor;
13905185a700Sflorian 	int32_t Csum;
13915185a700Sflorian 	int32_t Crot;
13925185a700Sflorian 	int32_t word;
13935185a700Sflorian 	int32_t bcount;
13945185a700Sflorian };
13955185a700Sflorian 
13965185a700Sflorian #define Ceor state->Ceor
13975185a700Sflorian #define Csum state->Csum
13985185a700Sflorian #define Crot state->Crot
13995185a700Sflorian #define word state->word
14005185a700Sflorian #define bcount state->bcount
14015185a700Sflorian 
14025185a700Sflorian static isc_result_t	byte_btoa(int c, isc_buffer_t *, struct state *state);
14035185a700Sflorian 
14045185a700Sflorian /*
14055185a700Sflorian  * Encode binary byte c into ASCII representation and place into *bufp,
14065185a700Sflorian  * advancing bufp.
14075185a700Sflorian  */
14085185a700Sflorian static isc_result_t
byte_btoa(int c,isc_buffer_t * target,struct state * state)14095185a700Sflorian byte_btoa(int c, isc_buffer_t *target, struct state *state) {
14105185a700Sflorian 	isc_region_t tr;
14115185a700Sflorian 
14125185a700Sflorian 	isc_buffer_availableregion(target, &tr);
14135185a700Sflorian 	Ceor ^= c;
14145185a700Sflorian 	Csum += c;
14155185a700Sflorian 	Csum += 1;
14165185a700Sflorian 	if ((Crot & 0x80000000)) {
14175185a700Sflorian 		Crot <<= 1;
14185185a700Sflorian 		Crot += 1;
14195185a700Sflorian 	} else {
14205185a700Sflorian 		Crot <<= 1;
14215185a700Sflorian 	}
14225185a700Sflorian 	Crot += c;
14235185a700Sflorian 
14245185a700Sflorian 	word <<= 8;
14255185a700Sflorian 	word |= c;
14265185a700Sflorian 	if (bcount == 3) {
14275185a700Sflorian 		if (word == 0) {
14285185a700Sflorian 			if (tr.length < 1)
14295185a700Sflorian 				return (ISC_R_NOSPACE);
14305185a700Sflorian 			tr.base[0] = 'z';
14315185a700Sflorian 			isc_buffer_add(target, 1);
14325185a700Sflorian 		} else {
14335185a700Sflorian 			register int tmp = 0;
14345185a700Sflorian 			register int32_t tmpword = word;
14355185a700Sflorian 
14365185a700Sflorian 			if (tmpword < 0) {
14375185a700Sflorian 				/*
14385185a700Sflorian 				 * Because some don't support u_long.
14395185a700Sflorian 				 */
14405185a700Sflorian 				tmp = 32;
14415185a700Sflorian 				tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
14425185a700Sflorian 			}
14435185a700Sflorian 			if (tmpword < 0) {
14445185a700Sflorian 				tmp = 64;
14455185a700Sflorian 				tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
14465185a700Sflorian 			}
14475185a700Sflorian 			if (tr.length < 5)
14485185a700Sflorian 				return (ISC_R_NOSPACE);
14495185a700Sflorian 			tr.base[0] = atob_digits[(tmpword /
1450*e6c7c102Sjsg 			    (int32_t)(85 * 85 * 85 * 85)) + tmp];
14515185a700Sflorian 			tmpword %= (int32_t)(85 * 85 * 85 * 85);
14525185a700Sflorian 			tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
14535185a700Sflorian 			tmpword %= (85 * 85 * 85);
14545185a700Sflorian 			tr.base[2] = atob_digits[tmpword / (85 * 85)];
14555185a700Sflorian 			tmpword %= (85 * 85);
14565185a700Sflorian 			tr.base[3] = atob_digits[tmpword / 85];
14575185a700Sflorian 			tmpword %= 85;
14585185a700Sflorian 			tr.base[4] = atob_digits[tmpword];
14595185a700Sflorian 			isc_buffer_add(target, 5);
14605185a700Sflorian 		}
14615185a700Sflorian 		bcount = 0;
14625185a700Sflorian 	} else {
14635185a700Sflorian 		bcount += 1;
14645185a700Sflorian 	}
14655185a700Sflorian 	return (ISC_R_SUCCESS);
14665185a700Sflorian }
14675185a700Sflorian 
14685185a700Sflorian /*
14695185a700Sflorian  * Encode the binary data from inbuf, of length inbuflen, into a
14705185a700Sflorian  * target.  Return success/failure status
14715185a700Sflorian  */
14725185a700Sflorian static isc_result_t
btoa_totext(unsigned char * inbuf,int inbuflen,isc_buffer_t * target)14735185a700Sflorian btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
14745185a700Sflorian 	int inc;
14755185a700Sflorian 	struct state statebuf, *state = &statebuf;
14765185a700Sflorian 	char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
14775185a700Sflorian 
14785185a700Sflorian 	Ceor = Csum = Crot = word = bcount = 0;
14795185a700Sflorian 	for (inc = 0; inc < inbuflen; inbuf++, inc++)
14805185a700Sflorian 		RETERR(byte_btoa(*inbuf, target, state));
14815185a700Sflorian 
14825185a700Sflorian 	while (bcount != 0)
14835185a700Sflorian 		RETERR(byte_btoa(0, target, state));
14845185a700Sflorian 
14855185a700Sflorian 	/*
14865185a700Sflorian 	 * Put byte count and checksum information at end of buffer,
14875185a700Sflorian 	 * delimited by 'x'
14885185a700Sflorian 	 */
14895185a700Sflorian 	snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1490873f12b9Sflorian 	return (isc_str_tobuffer(buf, target));
14915185a700Sflorian }
14925185a700Sflorian 
14935185a700Sflorian dns_rdatatype_t
dns_rdata_covers(dns_rdata_t * rdata)14945185a700Sflorian dns_rdata_covers(dns_rdata_t *rdata) {
14955185a700Sflorian 	if (rdata->type == dns_rdatatype_rrsig)
14965185a700Sflorian 		return (covers_rrsig(rdata));
14975185a700Sflorian 	return (covers_sig(rdata));
14985185a700Sflorian }
1499