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*407e2246Sflorian /* $Id: rdata.c,v 1.37 2024/12/09 12:24:01 florian 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 688a0b66ce4Sflorian dns_rdata_freestruct_cname(dns_rdata_cname_t *cname) { 689a0b66ce4Sflorian REQUIRE(cname != NULL); 6905185a700Sflorian 691a0b66ce4Sflorian freestruct_cname(cname); 692a0b66ce4Sflorian } 693a0b66ce4Sflorian 694a0b66ce4Sflorian void 695a0b66ce4Sflorian dns_rdata_freestruct_ns(dns_rdata_ns_t *ns) { 696a0b66ce4Sflorian REQUIRE(ns != NULL); 697a0b66ce4Sflorian 698a0b66ce4Sflorian freestruct_ns(ns); 699a0b66ce4Sflorian } 700a0b66ce4Sflorian 701a0b66ce4Sflorian void 702a0b66ce4Sflorian dns_rdata_freestruct_soa(dns_rdata_soa_t *soa) { 703a0b66ce4Sflorian REQUIRE(soa != NULL); 704a0b66ce4Sflorian 705a0b66ce4Sflorian freestruct_soa(soa); 706a0b66ce4Sflorian } 707a0b66ce4Sflorian 708a0b66ce4Sflorian void 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 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 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 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 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}, 814*407e2246Sflorian {"resinfo", 261}, 8159e6f49f3Sflorian {"rkey", 57}, 8169e6f49f3Sflorian {"rp", 17}, 8179e6f49f3Sflorian {"rrsig", 46}, 8189e6f49f3Sflorian {"rt", 21}, 8199e6f49f3Sflorian {"sig", 24}, 8209e6f49f3Sflorian {"sink", 40}, 8219e6f49f3Sflorian {"smimea", 53}, 8229e6f49f3Sflorian {"soa", 6}, 8239e6f49f3Sflorian {"spf", 99}, 8249e6f49f3Sflorian {"srv", 33}, 8259e6f49f3Sflorian {"sshfp", 44}, 82638bad3e5Sflorian {"svcb", 64}, 8279e6f49f3Sflorian {"ta", 32768}, 8289e6f49f3Sflorian {"talink", 58}, 8299e6f49f3Sflorian {"tkey", 249}, 8309e6f49f3Sflorian {"tlsa", 52}, 8319e6f49f3Sflorian {"tsig", 250}, 8329e6f49f3Sflorian {"txt", 16}, 8339e6f49f3Sflorian {"uid", 101}, 8349e6f49f3Sflorian {"uinfo", 100}, 8359e6f49f3Sflorian {"unspec", 103}, 8369e6f49f3Sflorian {"uri", 256}, 8379e6f49f3Sflorian {"wks", 11}, 838a944512fSflorian {"x25", 19}, 839a944512fSflorian {"zonemd", 63}, 8409e6f49f3Sflorian }; 8419e6f49f3Sflorian const dns_rdata_type_lookup_t *p; 8425185a700Sflorian unsigned int n; 8439e6f49f3Sflorian char lookup[sizeof("nsec3param")]; 8445185a700Sflorian 8455185a700Sflorian n = source->length; 8465185a700Sflorian 8475185a700Sflorian if (n == 0) 8485185a700Sflorian return (DNS_R_UNKNOWN); 8495185a700Sflorian 8509e6f49f3Sflorian /* source->base is not required to be NUL terminated. */ 8519e6f49f3Sflorian if ((size_t)snprintf(lookup, sizeof(lookup), "%.*s", n, source->base) 8529e6f49f3Sflorian >= sizeof(lookup)) 8539e6f49f3Sflorian return (DNS_R_UNKNOWN); 8545185a700Sflorian 8559e6f49f3Sflorian p = bsearch(lookup, type_lookup, 8569e6f49f3Sflorian sizeof(type_lookup)/sizeof(type_lookup[0]), sizeof(type_lookup[0]), 8579e6f49f3Sflorian type_cmp); 8585185a700Sflorian 8599e6f49f3Sflorian if (p) { 8609e6f49f3Sflorian if ((dns_rdatatype_attributes(p->val) & 8619e6f49f3Sflorian DNS_RDATATYPEATTR_RESERVED) != 0) 8629e6f49f3Sflorian return (ISC_R_NOTIMPLEMENTED); 8639e6f49f3Sflorian *typep = p->val; 8649e6f49f3Sflorian return (ISC_R_SUCCESS); 8659e6f49f3Sflorian } 8665185a700Sflorian 8679e6f49f3Sflorian if (n > 4 && strncasecmp("type", lookup, 4) == 0) { 8689e6f49f3Sflorian int val; 8699e6f49f3Sflorian const char *errstr; 8709e6f49f3Sflorian val = strtonum(lookup + 4, 0, UINT16_MAX, &errstr); 8719e6f49f3Sflorian if (errstr == NULL) { 8729e6f49f3Sflorian *typep = val; 8735185a700Sflorian return (ISC_R_SUCCESS); 8745185a700Sflorian } 8755185a700Sflorian } 8765185a700Sflorian 8775185a700Sflorian return (DNS_R_UNKNOWN); 8785185a700Sflorian } 8795185a700Sflorian 8805185a700Sflorian isc_result_t 8815185a700Sflorian dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) { 8825185a700Sflorian char buf[sizeof("TYPE65535")]; 8835185a700Sflorian 884a6fa6f7aSflorian switch (type) { 885a6fa6f7aSflorian case 0: 886873f12b9Sflorian return (isc_str_tobuffer("RESERVED0", target)); 887a6fa6f7aSflorian case 1: 888873f12b9Sflorian return (isc_str_tobuffer("A", target)); 889a6fa6f7aSflorian case 2: 890873f12b9Sflorian return (isc_str_tobuffer("NS", target)); 891a6fa6f7aSflorian case 3: 892873f12b9Sflorian return (isc_str_tobuffer("MD", target)); 893a6fa6f7aSflorian case 4: 894873f12b9Sflorian return (isc_str_tobuffer("MF", target)); 895a6fa6f7aSflorian case 5: 896873f12b9Sflorian return (isc_str_tobuffer("CNAME", target)); 897a6fa6f7aSflorian case 6: 898873f12b9Sflorian return (isc_str_tobuffer("SOA", target)); 899a6fa6f7aSflorian case 7: 900873f12b9Sflorian return (isc_str_tobuffer("MB", target)); 901a6fa6f7aSflorian case 8: 902873f12b9Sflorian return (isc_str_tobuffer("MG", target)); 903a6fa6f7aSflorian case 9: 904873f12b9Sflorian return (isc_str_tobuffer("MR", target)); 905a6fa6f7aSflorian case 10: 906873f12b9Sflorian return (isc_str_tobuffer("NULL", target)); 907a6fa6f7aSflorian case 11: 908873f12b9Sflorian return (isc_str_tobuffer("WKS", target)); 909a6fa6f7aSflorian case 12: 910873f12b9Sflorian return (isc_str_tobuffer("PTR", target)); 911a6fa6f7aSflorian case 13: 912873f12b9Sflorian return (isc_str_tobuffer("HINFO", target)); 913a6fa6f7aSflorian case 14: 914873f12b9Sflorian return (isc_str_tobuffer("MINFO", target)); 915a6fa6f7aSflorian case 15: 916873f12b9Sflorian return (isc_str_tobuffer("MX", target)); 917a6fa6f7aSflorian case 16: 918873f12b9Sflorian return (isc_str_tobuffer("TXT", target)); 919a6fa6f7aSflorian case 17: 920873f12b9Sflorian return (isc_str_tobuffer("RP", target)); 921a6fa6f7aSflorian case 18: 922873f12b9Sflorian return (isc_str_tobuffer("AFSDB", target)); 923a6fa6f7aSflorian case 19: 924873f12b9Sflorian return (isc_str_tobuffer("X25", target)); 925a6fa6f7aSflorian case 20: 926873f12b9Sflorian return (isc_str_tobuffer("ISDN", target)); 927a6fa6f7aSflorian case 21: 928873f12b9Sflorian return (isc_str_tobuffer("RT", target)); 929a6fa6f7aSflorian case 22: 930873f12b9Sflorian return (isc_str_tobuffer("NSAP", target)); 931a6fa6f7aSflorian case 23: 932873f12b9Sflorian return (isc_str_tobuffer("NSAP-PTR", target)); 933a6fa6f7aSflorian case 24: 934873f12b9Sflorian return (isc_str_tobuffer("SIG", target)); 935a6fa6f7aSflorian case 25: 936873f12b9Sflorian return (isc_str_tobuffer("KEY", target)); 937a6fa6f7aSflorian case 26: 938873f12b9Sflorian return (isc_str_tobuffer("PX", target)); 939a6fa6f7aSflorian case 27: 940873f12b9Sflorian return (isc_str_tobuffer("GPOS", target)); 941a6fa6f7aSflorian case 28: 942873f12b9Sflorian return (isc_str_tobuffer("AAAA", target)); 943a6fa6f7aSflorian case 29: 944873f12b9Sflorian return (isc_str_tobuffer("LOC", target)); 945a6fa6f7aSflorian case 30: 946873f12b9Sflorian return (isc_str_tobuffer("NXT", target)); 947a6fa6f7aSflorian case 31: 948873f12b9Sflorian return (isc_str_tobuffer("EID", target)); 949a6fa6f7aSflorian case 32: 950873f12b9Sflorian return (isc_str_tobuffer("NIMLOC", target)); 951a6fa6f7aSflorian case 33: 952873f12b9Sflorian return (isc_str_tobuffer("SRV", target)); 953a6fa6f7aSflorian case 34: 954873f12b9Sflorian return (isc_str_tobuffer("ATMA", target)); 955a6fa6f7aSflorian case 35: 956873f12b9Sflorian return (isc_str_tobuffer("NAPTR", target)); 957a6fa6f7aSflorian case 36: 958873f12b9Sflorian return (isc_str_tobuffer("KX", target)); 959a6fa6f7aSflorian case 37: 960873f12b9Sflorian return (isc_str_tobuffer("CERT", target)); 961a6fa6f7aSflorian case 38: 962873f12b9Sflorian return (isc_str_tobuffer("A6", target)); 963a6fa6f7aSflorian case 39: 964873f12b9Sflorian return (isc_str_tobuffer("DNAME", target)); 965a6fa6f7aSflorian case 40: 966873f12b9Sflorian return (isc_str_tobuffer("SINK", target)); 967a6fa6f7aSflorian case 41: 968873f12b9Sflorian return (isc_str_tobuffer("OPT", target)); 969a6fa6f7aSflorian case 42: 970873f12b9Sflorian return (isc_str_tobuffer("APL", target)); 971a6fa6f7aSflorian case 43: 972873f12b9Sflorian return (isc_str_tobuffer("DS", target)); 973a6fa6f7aSflorian case 44: 974873f12b9Sflorian return (isc_str_tobuffer("SSHFP", target)); 975a6fa6f7aSflorian case 45: 976873f12b9Sflorian return (isc_str_tobuffer("IPSECKEY", target)); 977a6fa6f7aSflorian case 46: 978873f12b9Sflorian return (isc_str_tobuffer("RRSIG", target)); 979a6fa6f7aSflorian case 47: 980873f12b9Sflorian return (isc_str_tobuffer("NSEC", target)); 981a6fa6f7aSflorian case 48: 982873f12b9Sflorian return (isc_str_tobuffer("DNSKEY", target)); 983a6fa6f7aSflorian case 49: 984873f12b9Sflorian return (isc_str_tobuffer("DHCID", target)); 985a6fa6f7aSflorian case 50: 986873f12b9Sflorian return (isc_str_tobuffer("NSEC3", target)); 987a6fa6f7aSflorian case 51: 988873f12b9Sflorian return (isc_str_tobuffer("NSEC3PARAM", target)); 989a6fa6f7aSflorian case 52: 990873f12b9Sflorian return (isc_str_tobuffer("TLSA", target)); 991a6fa6f7aSflorian case 53: 992873f12b9Sflorian return (isc_str_tobuffer("SMIMEA", target)); 993a6fa6f7aSflorian case 55: 994873f12b9Sflorian return (isc_str_tobuffer("HIP", target)); 995a6fa6f7aSflorian case 56: 996873f12b9Sflorian return (isc_str_tobuffer("NINFO", target)); 997a6fa6f7aSflorian case 57: 998873f12b9Sflorian return (isc_str_tobuffer("RKEY", target)); 999a6fa6f7aSflorian case 58: 1000873f12b9Sflorian return (isc_str_tobuffer("TALINK", target)); 1001a6fa6f7aSflorian case 59: 1002873f12b9Sflorian return (isc_str_tobuffer("CDS", target)); 1003a6fa6f7aSflorian case 60: 1004873f12b9Sflorian return (isc_str_tobuffer("CDNSKEY", target)); 1005a6fa6f7aSflorian case 61: 1006873f12b9Sflorian return (isc_str_tobuffer("OPENPGPKEY", target)); 1007a6fa6f7aSflorian case 62: 1008873f12b9Sflorian return (isc_str_tobuffer("CSYNC", target)); 1009a944512fSflorian case 63: 1010a944512fSflorian return (isc_str_tobuffer("ZONEMD", target)); 101138bad3e5Sflorian case 64: 101238bad3e5Sflorian return (isc_str_tobuffer("SVCB", target)); 101338bad3e5Sflorian case 65: 101438bad3e5Sflorian return (isc_str_tobuffer("HTTPS", target)); 1015a6fa6f7aSflorian case 99: 1016873f12b9Sflorian return (isc_str_tobuffer("SPF", target)); 1017a6fa6f7aSflorian case 100: 1018873f12b9Sflorian return (isc_str_tobuffer("UINFO", target)); 1019a6fa6f7aSflorian case 101: 1020873f12b9Sflorian return (isc_str_tobuffer("UID", target)); 1021a6fa6f7aSflorian case 102: 1022873f12b9Sflorian return (isc_str_tobuffer("GID", target)); 1023a6fa6f7aSflorian case 103: 1024873f12b9Sflorian return (isc_str_tobuffer("UNSPEC", target)); 1025a6fa6f7aSflorian case 104: 1026873f12b9Sflorian return (isc_str_tobuffer("NID", target)); 1027a6fa6f7aSflorian case 105: 1028873f12b9Sflorian return (isc_str_tobuffer("L32", target)); 1029a6fa6f7aSflorian case 106: 1030873f12b9Sflorian return (isc_str_tobuffer("L64", target)); 1031a6fa6f7aSflorian case 107: 1032873f12b9Sflorian return (isc_str_tobuffer("LP", target)); 1033a6fa6f7aSflorian case 108: 1034873f12b9Sflorian return (isc_str_tobuffer("EUI48", target)); 1035a6fa6f7aSflorian case 109: 1036873f12b9Sflorian return (isc_str_tobuffer("EUI64", target)); 1037a6fa6f7aSflorian case 249: 1038873f12b9Sflorian return (isc_str_tobuffer("TKEY", target)); 1039a6fa6f7aSflorian case 250: 1040873f12b9Sflorian return (isc_str_tobuffer("TSIG", target)); 1041a6fa6f7aSflorian case 251: 1042873f12b9Sflorian return (isc_str_tobuffer("IXFR", target)); 1043a6fa6f7aSflorian case 252: 1044873f12b9Sflorian return (isc_str_tobuffer("AXFR", target)); 1045a6fa6f7aSflorian case 253: 1046873f12b9Sflorian return (isc_str_tobuffer("MAILB", target)); 1047a6fa6f7aSflorian case 254: 1048873f12b9Sflorian return (isc_str_tobuffer("MAILA", target)); 1049a6fa6f7aSflorian case 255: 1050873f12b9Sflorian return (isc_str_tobuffer("ANY", target)); 1051a6fa6f7aSflorian case 256: 1052873f12b9Sflorian return (isc_str_tobuffer("URI", target)); 1053a6fa6f7aSflorian case 257: 1054873f12b9Sflorian return (isc_str_tobuffer("CAA", target)); 1055a6fa6f7aSflorian case 258: 1056873f12b9Sflorian return (isc_str_tobuffer("AVC", target)); 1057a6fa6f7aSflorian case 259: 1058873f12b9Sflorian return (isc_str_tobuffer("DOA", target)); 1059*407e2246Sflorian case 261: 1060*407e2246Sflorian return (isc_str_tobuffer("RESINFO", target)); 1061a6fa6f7aSflorian case 32768: 1062873f12b9Sflorian return (isc_str_tobuffer("TA", target)); 1063a6fa6f7aSflorian case 32769: 1064873f12b9Sflorian return (isc_str_tobuffer("DLV", target)); 1065a6fa6f7aSflorian default: 10665185a700Sflorian snprintf(buf, sizeof(buf), "TYPE%u", type); 1067873f12b9Sflorian return (isc_str_tobuffer(buf, target)); 10685185a700Sflorian } 1069a6fa6f7aSflorian } 10705185a700Sflorian 10715185a700Sflorian void 10725185a700Sflorian dns_rdatatype_format(dns_rdatatype_t rdtype, 10735185a700Sflorian char *array, unsigned int size) 10745185a700Sflorian { 10755185a700Sflorian isc_result_t result; 10765185a700Sflorian isc_buffer_t buf; 10775185a700Sflorian 10785185a700Sflorian if (size == 0U) 10795185a700Sflorian return; 10805185a700Sflorian 10815185a700Sflorian isc_buffer_init(&buf, array, size); 10825185a700Sflorian result = dns_rdatatype_totext(rdtype, &buf); 10835185a700Sflorian /* 10845185a700Sflorian * Null terminate. 10855185a700Sflorian */ 10865185a700Sflorian if (result == ISC_R_SUCCESS) { 10875185a700Sflorian if (isc_buffer_availablelength(&buf) >= 1) 10885185a700Sflorian isc_buffer_putuint8(&buf, 0); 10895185a700Sflorian else 10905185a700Sflorian result = ISC_R_NOSPACE; 10915185a700Sflorian } 10925185a700Sflorian if (result != ISC_R_SUCCESS) 10935185a700Sflorian strlcpy(array, "<unknown>", size); 10945185a700Sflorian } 10955185a700Sflorian 10965185a700Sflorian /* 10975185a700Sflorian * Private function. 10985185a700Sflorian */ 10995185a700Sflorian 11005185a700Sflorian static unsigned int 11015185a700Sflorian name_length(dns_name_t *name) { 11025185a700Sflorian return (name->length); 11035185a700Sflorian } 11045185a700Sflorian 11055185a700Sflorian static isc_result_t 11061fb015a8Sflorian txt_totext(isc_region_t *source, int quote, isc_buffer_t *target) { 11075185a700Sflorian unsigned int tl; 11085185a700Sflorian unsigned int n; 11095185a700Sflorian unsigned char *sp; 11105185a700Sflorian char *tp; 11115185a700Sflorian isc_region_t region; 11125185a700Sflorian 11135185a700Sflorian isc_buffer_availableregion(target, ®ion); 11145185a700Sflorian sp = source->base; 11155185a700Sflorian tp = (char *)region.base; 11165185a700Sflorian tl = region.length; 11175185a700Sflorian 11185185a700Sflorian n = *sp++; 11195185a700Sflorian 11205185a700Sflorian REQUIRE(n + 1 <= source->length); 11215185a700Sflorian if (n == 0U) 11221fb015a8Sflorian REQUIRE(quote); 11235185a700Sflorian 11245185a700Sflorian if (quote) { 11255185a700Sflorian if (tl < 1) 11265185a700Sflorian return (ISC_R_NOSPACE); 11275185a700Sflorian *tp++ = '"'; 11285185a700Sflorian tl--; 11295185a700Sflorian } 11305185a700Sflorian while (n--) { 11315185a700Sflorian /* 11325185a700Sflorian * \DDD space (0x20) if not quoting. 11335185a700Sflorian */ 11345185a700Sflorian if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) { 11355185a700Sflorian if (tl < 4) 11365185a700Sflorian return (ISC_R_NOSPACE); 11375185a700Sflorian *tp++ = 0x5c; 11385185a700Sflorian *tp++ = 0x30 + ((*sp / 100) % 10); 11395185a700Sflorian *tp++ = 0x30 + ((*sp / 10) % 10); 11405185a700Sflorian *tp++ = 0x30 + (*sp % 10); 11415185a700Sflorian sp++; 11425185a700Sflorian tl -= 4; 11435185a700Sflorian continue; 11445185a700Sflorian } 11455185a700Sflorian /* 11465185a700Sflorian * Escape double quote and backslash. If we are not 11475185a700Sflorian * enclosing the string in double quotes also escape 11485185a700Sflorian * at sign and semicolon. 11495185a700Sflorian */ 11505185a700Sflorian if (*sp == 0x22 || *sp == 0x5c || 11515185a700Sflorian (!quote && (*sp == 0x40 || *sp == 0x3b))) { 11525185a700Sflorian if (tl < 2) 11535185a700Sflorian return (ISC_R_NOSPACE); 11545185a700Sflorian *tp++ = '\\'; 11555185a700Sflorian tl--; 11565185a700Sflorian } 11575185a700Sflorian if (tl < 1) 11585185a700Sflorian return (ISC_R_NOSPACE); 11595185a700Sflorian *tp++ = *sp++; 11605185a700Sflorian tl--; 11615185a700Sflorian } 11625185a700Sflorian if (quote) { 11635185a700Sflorian if (tl < 1) 11645185a700Sflorian return (ISC_R_NOSPACE); 11655185a700Sflorian *tp++ = '"'; 11665185a700Sflorian tl--; 11675185a700Sflorian POST(tl); 11685185a700Sflorian } 11695185a700Sflorian isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); 11705185a700Sflorian isc_region_consume(source, *source->base + 1); 11715185a700Sflorian return (ISC_R_SUCCESS); 11725185a700Sflorian } 11735185a700Sflorian 11745185a700Sflorian static isc_result_t 11755185a700Sflorian txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { 11765185a700Sflorian unsigned int n; 11775185a700Sflorian isc_region_t sregion; 11785185a700Sflorian isc_region_t tregion; 11795185a700Sflorian 11805185a700Sflorian isc_buffer_activeregion(source, &sregion); 11815185a700Sflorian if (sregion.length == 0) 11825185a700Sflorian return (ISC_R_UNEXPECTEDEND); 11835185a700Sflorian n = *sregion.base + 1; 11845185a700Sflorian if (n > sregion.length) 11855185a700Sflorian return (ISC_R_UNEXPECTEDEND); 11865185a700Sflorian 11875185a700Sflorian isc_buffer_availableregion(target, &tregion); 11885185a700Sflorian if (n > tregion.length) 11895185a700Sflorian return (ISC_R_NOSPACE); 11905185a700Sflorian 11915185a700Sflorian if (tregion.base != sregion.base) 11925185a700Sflorian memmove(tregion.base, sregion.base, n); 11935185a700Sflorian isc_buffer_forward(source, n); 11945185a700Sflorian isc_buffer_add(target, n); 11955185a700Sflorian return (ISC_R_SUCCESS); 11965185a700Sflorian } 11975185a700Sflorian 11985185a700Sflorian /* 11995185a700Sflorian * Conversion of TXT-like rdata fields without length limits. 12005185a700Sflorian */ 12015185a700Sflorian static isc_result_t 12025185a700Sflorian multitxt_totext(isc_region_t *source, isc_buffer_t *target) { 12035185a700Sflorian unsigned int tl; 12045185a700Sflorian unsigned int n0, n; 12055185a700Sflorian unsigned char *sp; 12065185a700Sflorian char *tp; 12075185a700Sflorian isc_region_t region; 12085185a700Sflorian 12095185a700Sflorian isc_buffer_availableregion(target, ®ion); 12105185a700Sflorian sp = source->base; 12115185a700Sflorian tp = (char *)region.base; 12125185a700Sflorian tl = region.length; 12135185a700Sflorian 12145185a700Sflorian if (tl < 1) 12155185a700Sflorian return (ISC_R_NOSPACE); 12165185a700Sflorian *tp++ = '"'; 12175185a700Sflorian tl--; 12185185a700Sflorian do { 12195185a700Sflorian n = source->length; 12205185a700Sflorian n0 = source->length - 1; 12215185a700Sflorian 12225185a700Sflorian while (n--) { 12235185a700Sflorian if (*sp < 0x20 || *sp >= 0x7f) { 12245185a700Sflorian if (tl < 4) 12255185a700Sflorian return (ISC_R_NOSPACE); 12265185a700Sflorian *tp++ = 0x5c; 12275185a700Sflorian *tp++ = 0x30 + ((*sp / 100) % 10); 12285185a700Sflorian *tp++ = 0x30 + ((*sp / 10) % 10); 12295185a700Sflorian *tp++ = 0x30 + (*sp % 10); 12305185a700Sflorian sp++; 12315185a700Sflorian tl -= 4; 12325185a700Sflorian continue; 12335185a700Sflorian } 12345185a700Sflorian /* double quote, backslash */ 12355185a700Sflorian if (*sp == 0x22 || *sp == 0x5c) { 12365185a700Sflorian if (tl < 2) 12375185a700Sflorian return (ISC_R_NOSPACE); 12385185a700Sflorian *tp++ = '\\'; 12395185a700Sflorian tl--; 12405185a700Sflorian } 12415185a700Sflorian if (tl < 1) 12425185a700Sflorian return (ISC_R_NOSPACE); 12435185a700Sflorian *tp++ = *sp++; 12445185a700Sflorian tl--; 12455185a700Sflorian } 12465185a700Sflorian isc_region_consume(source, n0 + 1); 12475185a700Sflorian } while (source->length != 0); 12485185a700Sflorian if (tl < 1) 12495185a700Sflorian return (ISC_R_NOSPACE); 12505185a700Sflorian *tp++ = '"'; 12515185a700Sflorian tl--; 12525185a700Sflorian POST(tl); 12535185a700Sflorian isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); 12545185a700Sflorian return (ISC_R_SUCCESS); 12555185a700Sflorian } 12565185a700Sflorian 12571fb015a8Sflorian static int 12585185a700Sflorian name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) { 12595185a700Sflorian int l1, l2; 12605185a700Sflorian 12615185a700Sflorian if (origin == NULL) 12625185a700Sflorian goto return_false; 12635185a700Sflorian 12645185a700Sflorian if (dns_name_compare(origin, dns_rootname) == 0) 12655185a700Sflorian goto return_false; 12665185a700Sflorian 12675185a700Sflorian if (!dns_name_issubdomain(name, origin)) 12685185a700Sflorian goto return_false; 12695185a700Sflorian 12705185a700Sflorian l1 = dns_name_countlabels(name); 12715185a700Sflorian l2 = dns_name_countlabels(origin); 12725185a700Sflorian 12735185a700Sflorian if (l1 == l2) 12745185a700Sflorian goto return_false; 12755185a700Sflorian 12765185a700Sflorian /* Master files should be case preserving. */ 12775185a700Sflorian dns_name_getlabelsequence(name, l1 - l2, l2, target); 12785185a700Sflorian if (!dns_name_caseequal(origin, target)) 12795185a700Sflorian goto return_false; 12805185a700Sflorian 12815185a700Sflorian dns_name_getlabelsequence(name, 0, l1 - l2, target); 12821fb015a8Sflorian return (1); 12835185a700Sflorian 12845185a700Sflorian return_false: 12855185a700Sflorian *target = *name; 12861fb015a8Sflorian return (0); 12875185a700Sflorian } 12885185a700Sflorian 12895185a700Sflorian static isc_result_t 12905185a700Sflorian inet_totext(int af, isc_region_t *src, isc_buffer_t *target) { 12915185a700Sflorian char tmpbuf[64]; 12925185a700Sflorian 12935185a700Sflorian /* Note - inet_ntop doesn't do size checking on its input. */ 12945185a700Sflorian if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL) 12955185a700Sflorian return (ISC_R_NOSPACE); 12965185a700Sflorian if (strlen(tmpbuf) > isc_buffer_availablelength(target)) 12975185a700Sflorian return (ISC_R_NOSPACE); 12985185a700Sflorian isc_buffer_putstr(target, tmpbuf); 12995185a700Sflorian return (ISC_R_SUCCESS); 13005185a700Sflorian } 13015185a700Sflorian 13021fb015a8Sflorian static int 13035185a700Sflorian buffer_empty(isc_buffer_t *source) { 13041fb015a8Sflorian return((source->current == source->active) ? 1 : 0); 13055185a700Sflorian } 13065185a700Sflorian 13075185a700Sflorian static isc_result_t 13085185a700Sflorian uint32_tobuffer(uint32_t value, isc_buffer_t *target) { 13095185a700Sflorian isc_region_t region; 13105185a700Sflorian 13115185a700Sflorian isc_buffer_availableregion(target, ®ion); 13125185a700Sflorian if (region.length < 4) 13135185a700Sflorian return (ISC_R_NOSPACE); 13145185a700Sflorian isc_buffer_putuint32(target, value); 13155185a700Sflorian return (ISC_R_SUCCESS); 13165185a700Sflorian } 13175185a700Sflorian 13185185a700Sflorian static isc_result_t 13195185a700Sflorian uint16_tobuffer(uint32_t value, isc_buffer_t *target) { 13205185a700Sflorian isc_region_t region; 13215185a700Sflorian 13225185a700Sflorian if (value > 0xffff) 13235185a700Sflorian return (ISC_R_RANGE); 13245185a700Sflorian isc_buffer_availableregion(target, ®ion); 13255185a700Sflorian if (region.length < 2) 13265185a700Sflorian return (ISC_R_NOSPACE); 13275185a700Sflorian isc_buffer_putuint16(target, (uint16_t)value); 13285185a700Sflorian return (ISC_R_SUCCESS); 13295185a700Sflorian } 13305185a700Sflorian 13315185a700Sflorian static isc_result_t 13325185a700Sflorian name_tobuffer(dns_name_t *name, isc_buffer_t *target) { 13335185a700Sflorian isc_region_t r; 13345185a700Sflorian dns_name_toregion(name, &r); 13355185a700Sflorian return (isc_buffer_copyregion(target, &r)); 13365185a700Sflorian } 13375185a700Sflorian 13385185a700Sflorian static uint32_t 13395185a700Sflorian uint32_fromregion(isc_region_t *region) { 13405185a700Sflorian uint32_t value; 13415185a700Sflorian 13425185a700Sflorian REQUIRE(region->length >= 4); 13435185a700Sflorian value = region->base[0] << 24; 13445185a700Sflorian value |= region->base[1] << 16; 13455185a700Sflorian value |= region->base[2] << 8; 13465185a700Sflorian value |= region->base[3]; 13475185a700Sflorian return(value); 13485185a700Sflorian } 13495185a700Sflorian 13505185a700Sflorian static uint16_t 13515185a700Sflorian uint16_fromregion(isc_region_t *region) { 13525185a700Sflorian 13535185a700Sflorian REQUIRE(region->length >= 2); 13545185a700Sflorian 13555185a700Sflorian return ((region->base[0] << 8) | region->base[1]); 13565185a700Sflorian } 13575185a700Sflorian 13585185a700Sflorian static uint8_t 13595185a700Sflorian uint8_fromregion(isc_region_t *region) { 13605185a700Sflorian 13615185a700Sflorian REQUIRE(region->length >= 1); 13625185a700Sflorian 13635185a700Sflorian return (region->base[0]); 13645185a700Sflorian } 13655185a700Sflorian 13665185a700Sflorian static uint8_t 13675185a700Sflorian uint8_consume_fromregion(isc_region_t *region) { 13685185a700Sflorian uint8_t r = uint8_fromregion(region); 13695185a700Sflorian 13705185a700Sflorian isc_region_consume(region, 1); 13715185a700Sflorian return r; 13725185a700Sflorian } 13735185a700Sflorian 13745185a700Sflorian static const char atob_digits[86] = 13755185a700Sflorian "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \ 13765185a700Sflorian "abcdefghijklmnopqrstu"; 13775185a700Sflorian /* 13785185a700Sflorian * Subroutines to convert between 8 bit binary bytes and printable ASCII. 13795185a700Sflorian * Computes the number of bytes, and three kinds of simple checksums. 13805185a700Sflorian * Incoming bytes are collected into 32-bit words, then printed in base 85: 13815185a700Sflorian * exp(85,5) > exp(2,32) 13825185a700Sflorian * The ASCII characters used are between '!' and 'u'; 13835185a700Sflorian * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data. 13845185a700Sflorian * 13855185a700Sflorian * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for 13865185a700Sflorian * the atob/btoa programs, released with the compress program, in mod.sources. 13875185a700Sflorian * Modified by Mike Schwartz 8/19/86 for use in BIND. 13885185a700Sflorian * Modified to be re-entrant 3/2/99. 13895185a700Sflorian */ 13905185a700Sflorian 13915185a700Sflorian struct state { 13925185a700Sflorian int32_t Ceor; 13935185a700Sflorian int32_t Csum; 13945185a700Sflorian int32_t Crot; 13955185a700Sflorian int32_t word; 13965185a700Sflorian int32_t bcount; 13975185a700Sflorian }; 13985185a700Sflorian 13995185a700Sflorian #define Ceor state->Ceor 14005185a700Sflorian #define Csum state->Csum 14015185a700Sflorian #define Crot state->Crot 14025185a700Sflorian #define word state->word 14035185a700Sflorian #define bcount state->bcount 14045185a700Sflorian 14055185a700Sflorian static isc_result_t byte_btoa(int c, isc_buffer_t *, struct state *state); 14065185a700Sflorian 14075185a700Sflorian /* 14085185a700Sflorian * Encode binary byte c into ASCII representation and place into *bufp, 14095185a700Sflorian * advancing bufp. 14105185a700Sflorian */ 14115185a700Sflorian static isc_result_t 14125185a700Sflorian byte_btoa(int c, isc_buffer_t *target, struct state *state) { 14135185a700Sflorian isc_region_t tr; 14145185a700Sflorian 14155185a700Sflorian isc_buffer_availableregion(target, &tr); 14165185a700Sflorian Ceor ^= c; 14175185a700Sflorian Csum += c; 14185185a700Sflorian Csum += 1; 14195185a700Sflorian if ((Crot & 0x80000000)) { 14205185a700Sflorian Crot <<= 1; 14215185a700Sflorian Crot += 1; 14225185a700Sflorian } else { 14235185a700Sflorian Crot <<= 1; 14245185a700Sflorian } 14255185a700Sflorian Crot += c; 14265185a700Sflorian 14275185a700Sflorian word <<= 8; 14285185a700Sflorian word |= c; 14295185a700Sflorian if (bcount == 3) { 14305185a700Sflorian if (word == 0) { 14315185a700Sflorian if (tr.length < 1) 14325185a700Sflorian return (ISC_R_NOSPACE); 14335185a700Sflorian tr.base[0] = 'z'; 14345185a700Sflorian isc_buffer_add(target, 1); 14355185a700Sflorian } else { 14365185a700Sflorian register int tmp = 0; 14375185a700Sflorian register int32_t tmpword = word; 14385185a700Sflorian 14395185a700Sflorian if (tmpword < 0) { 14405185a700Sflorian /* 14415185a700Sflorian * Because some don't support u_long. 14425185a700Sflorian */ 14435185a700Sflorian tmp = 32; 14445185a700Sflorian tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32); 14455185a700Sflorian } 14465185a700Sflorian if (tmpword < 0) { 14475185a700Sflorian tmp = 64; 14485185a700Sflorian tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32); 14495185a700Sflorian } 14505185a700Sflorian if (tr.length < 5) 14515185a700Sflorian return (ISC_R_NOSPACE); 14525185a700Sflorian tr.base[0] = atob_digits[(tmpword / 1453e6c7c102Sjsg (int32_t)(85 * 85 * 85 * 85)) + tmp]; 14545185a700Sflorian tmpword %= (int32_t)(85 * 85 * 85 * 85); 14555185a700Sflorian tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)]; 14565185a700Sflorian tmpword %= (85 * 85 * 85); 14575185a700Sflorian tr.base[2] = atob_digits[tmpword / (85 * 85)]; 14585185a700Sflorian tmpword %= (85 * 85); 14595185a700Sflorian tr.base[3] = atob_digits[tmpword / 85]; 14605185a700Sflorian tmpword %= 85; 14615185a700Sflorian tr.base[4] = atob_digits[tmpword]; 14625185a700Sflorian isc_buffer_add(target, 5); 14635185a700Sflorian } 14645185a700Sflorian bcount = 0; 14655185a700Sflorian } else { 14665185a700Sflorian bcount += 1; 14675185a700Sflorian } 14685185a700Sflorian return (ISC_R_SUCCESS); 14695185a700Sflorian } 14705185a700Sflorian 14715185a700Sflorian /* 14725185a700Sflorian * Encode the binary data from inbuf, of length inbuflen, into a 14735185a700Sflorian * target. Return success/failure status 14745185a700Sflorian */ 14755185a700Sflorian static isc_result_t 14765185a700Sflorian btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) { 14775185a700Sflorian int inc; 14785185a700Sflorian struct state statebuf, *state = &statebuf; 14795185a700Sflorian char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")]; 14805185a700Sflorian 14815185a700Sflorian Ceor = Csum = Crot = word = bcount = 0; 14825185a700Sflorian for (inc = 0; inc < inbuflen; inbuf++, inc++) 14835185a700Sflorian RETERR(byte_btoa(*inbuf, target, state)); 14845185a700Sflorian 14855185a700Sflorian while (bcount != 0) 14865185a700Sflorian RETERR(byte_btoa(0, target, state)); 14875185a700Sflorian 14885185a700Sflorian /* 14895185a700Sflorian * Put byte count and checksum information at end of buffer, 14905185a700Sflorian * delimited by 'x' 14915185a700Sflorian */ 14925185a700Sflorian snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot); 1493873f12b9Sflorian return (isc_str_tobuffer(buf, target)); 14945185a700Sflorian } 14955185a700Sflorian 14965185a700Sflorian dns_rdatatype_t 14975185a700Sflorian dns_rdata_covers(dns_rdata_t *rdata) { 14985185a700Sflorian if (rdata->type == dns_rdatatype_rrsig) 14995185a700Sflorian return (covers_rrsig(rdata)); 15005185a700Sflorian return (covers_sig(rdata)); 15015185a700Sflorian } 1502