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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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