diff options
Diffstat (limited to '')
164 files changed, 31105 insertions, 0 deletions
diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c new file mode 100644 index 0000000..93f5559 --- /dev/null +++ b/lib/dns/rdata.c @@ -0,0 +1,2432 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <ctype.h> +#include <inttypes.h> + +#include <isc/base64.h> +#include <isc/hex.h> +#include <isc/lex.h> +#include <isc/mem.h> +#include <isc/parseint.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/stdlib.h> +#include <isc/util.h> + +#include <dns/callbacks.h> +#include <dns/cert.h> +#include <dns/compress.h> +#include <dns/dsdigest.h> +#include <dns/enumtype.h> +#include <dns/keyflags.h> +#include <dns/keyvalues.h> +#include <dns/message.h> +#include <dns/rcode.h> +#include <dns/rdata.h> +#include <dns/rdataclass.h> +#include <dns/rdatastruct.h> +#include <dns/rdatatype.h> +#include <dns/result.h> +#include <dns/secalg.h> +#include <dns/secproto.h> +#include <dns/time.h> +#include <dns/ttl.h> + +#define RETERR(x) \ + do { \ + isc_result_t _r = (x); \ + if (_r != ISC_R_SUCCESS) \ + return (_r); \ + } while (0) + +#define RETTOK(x) \ + do { \ + isc_result_t _r = (x); \ + if (_r != ISC_R_SUCCESS) { \ + isc_lex_ungettoken(lexer, &token); \ + return (_r); \ + } \ + } while (0) + +#define CHECK(op) \ + do { result = (op); \ + if (result != ISC_R_SUCCESS) goto cleanup; \ + } while (0) + +#define CHECKTOK(op) \ + do { result = (op); \ + if (result != ISC_R_SUCCESS) { \ + isc_lex_ungettoken(lexer, &token); \ + goto cleanup; \ + } \ + } while (0) + +#define DNS_AS_STR(t) ((t).value.as_textregion.base) + +#define ARGS_FROMTEXT int rdclass, dns_rdatatype_t type, \ + isc_lex_t *lexer, dns_name_t *origin, \ + unsigned int options, isc_buffer_t *target, \ + dns_rdatacallbacks_t *callbacks + +#define ARGS_TOTEXT dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \ + isc_buffer_t *target + +#define ARGS_FROMWIRE int rdclass, dns_rdatatype_t type, \ + isc_buffer_t *source, dns_decompress_t *dctx, \ + unsigned int options, isc_buffer_t *target + +#define ARGS_TOWIRE dns_rdata_t *rdata, dns_compress_t *cctx, \ + isc_buffer_t *target + +#define ARGS_COMPARE const dns_rdata_t *rdata1, const dns_rdata_t *rdata2 + +#define ARGS_FROMSTRUCT int rdclass, dns_rdatatype_t type, \ + void *source, isc_buffer_t *target + +#define ARGS_TOSTRUCT const dns_rdata_t *rdata, void *target, isc_mem_t *mctx + +#define ARGS_FREESTRUCT void *source + +#define ARGS_ADDLDATA dns_rdata_t *rdata, dns_additionaldatafunc_t add, \ + void *arg + +#define ARGS_DIGEST dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg + +#define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \ + dns_rdatatype_t type, bool wildcard + +#define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad + + +/*% + * Context structure for the totext_ functions. + * Contains formatting options for rdata-to-text + * conversion. + */ +typedef struct dns_rdata_textctx { + dns_name_t *origin; /*%< Current origin, or NULL. */ + unsigned int flags; /*%< DNS_STYLEFLAG_* */ + unsigned int width; /*%< Width of rdata column. */ + const char *linebreak; /*%< Line break string. */ +} dns_rdata_textctx_t; + +static isc_result_t +txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target); + +static isc_result_t +txt_fromtext(isc_textregion_t *source, isc_buffer_t *target); + +static isc_result_t +txt_fromwire(isc_buffer_t *source, isc_buffer_t *target); + +static isc_result_t +multitxt_totext(isc_region_t *source, isc_buffer_t *target); + +static isc_result_t +multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target); + +static bool +name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target); + +static unsigned int +name_length(dns_name_t *name); + +static isc_result_t +str_totext(const char *source, isc_buffer_t *target); + +static isc_result_t +inet_totext(int af, isc_region_t *src, isc_buffer_t *target); + +static bool +buffer_empty(isc_buffer_t *source); + +static void +buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region); + +static isc_result_t +uint32_tobuffer(uint32_t, isc_buffer_t *target); + +static isc_result_t +uint16_tobuffer(uint32_t, isc_buffer_t *target); + +static isc_result_t +uint8_tobuffer(uint32_t, isc_buffer_t *target); + +static isc_result_t +name_tobuffer(dns_name_t *name, isc_buffer_t *target); + +static uint32_t +uint32_fromregion(isc_region_t *region); + +static uint16_t +uint16_fromregion(isc_region_t *region); + +static uint8_t +uint8_fromregion(isc_region_t *region); + +static uint8_t +uint8_consume_fromregion(isc_region_t *region); + +static isc_result_t +mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length); + +static int +hexvalue(char value); + +static int +decvalue(char value); + +static isc_result_t +btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target); + +static isc_result_t +atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target); + +static void +default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...) + ISC_FORMAT_PRINTF(2, 3); + +static void +fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), + dns_rdatacallbacks_t *callbacks, const char *name, + unsigned long line, isc_token_t *token, isc_result_t result); + +static void +fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks); + +static isc_result_t +rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target); + +static void +warn_badname(dns_name_t *name, isc_lex_t *lexer, + dns_rdatacallbacks_t *callbacks); + +static void +warn_badmx(isc_token_t *token, isc_lex_t *lexer, + dns_rdatacallbacks_t *callbacks); + +static uint16_t +uint16_consume_fromregion(isc_region_t *region); + +static isc_result_t +unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target); + +static inline isc_result_t +generic_fromtext_key(ARGS_FROMTEXT); + +static inline isc_result_t +generic_totext_key(ARGS_TOTEXT); + +static inline isc_result_t +generic_fromwire_key(ARGS_FROMWIRE); + +static inline isc_result_t +generic_fromstruct_key(ARGS_FROMSTRUCT); + +static inline isc_result_t +generic_tostruct_key(ARGS_TOSTRUCT); + +static inline void +generic_freestruct_key(ARGS_FREESTRUCT); + +static isc_result_t +generic_fromtext_txt(ARGS_FROMTEXT); + +static isc_result_t +generic_totext_txt(ARGS_TOTEXT); + +static isc_result_t +generic_fromwire_txt(ARGS_FROMWIRE); + +static isc_result_t +generic_fromstruct_txt(ARGS_FROMSTRUCT); + +static isc_result_t +generic_tostruct_txt(ARGS_TOSTRUCT); + +static void +generic_freestruct_txt(ARGS_FREESTRUCT); + +static isc_result_t +generic_txt_first(dns_rdata_txt_t *txt); + +static isc_result_t +generic_txt_next(dns_rdata_txt_t *txt); + +static isc_result_t +generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string); + +static isc_result_t +generic_totext_ds(ARGS_TOTEXT); + +static isc_result_t +generic_tostruct_ds(ARGS_TOSTRUCT); + +static isc_result_t +generic_fromtext_ds(ARGS_FROMTEXT); + +static isc_result_t +generic_fromwire_ds(ARGS_FROMWIRE); + +static isc_result_t +generic_fromstruct_ds(ARGS_FROMSTRUCT); + +static isc_result_t +generic_fromtext_tlsa(ARGS_FROMTEXT); + +static isc_result_t +generic_totext_tlsa(ARGS_TOTEXT); + +static isc_result_t +generic_fromwire_tlsa(ARGS_FROMWIRE); + +static isc_result_t +generic_fromstruct_tlsa(ARGS_FROMSTRUCT); + +static isc_result_t +generic_tostruct_tlsa(ARGS_TOSTRUCT); + +static void +generic_freestruct_tlsa(ARGS_FREESTRUCT); + +/*% INT16 Size */ +#define NS_INT16SZ 2 +/*% IPv6 Address Size */ +#define NS_LOCATORSZ 8 + +/* + * Active Diretory gc._msdcs.<forest> prefix. + */ +static unsigned char gc_msdcs_data[] = "\002gc\006_msdcs"; +static unsigned char gc_msdcs_offset [] = { 0, 3 }; + +static dns_name_t const gc_msdcs = + DNS_NAME_INITNONABSOLUTE(gc_msdcs_data, gc_msdcs_offset); + +/*% + * convert presentation level address to network order binary form. + * \return + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * \note + * (1) does not touch `dst' unless it's returning 1. + */ +static inline int +locator_pton(const char *src, unsigned char *dst) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[NS_LOCATORSZ]; + unsigned char *tp = tmp, *endp; + const char *xdigits; + int ch, seen_xdigits; + unsigned int val; + + memset(tp, '\0', NS_LOCATORSZ); + endp = tp + NS_LOCATORSZ; + seen_xdigits = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr((xdigits = xdigits_l), ch); + if (pch == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (++seen_xdigits > 4) + return (0); + continue; + } + if (ch == ':') { + if (!seen_xdigits) + return (0); + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + seen_xdigits = 0; + val = 0; + continue; + } + return (0); + } + if (seen_xdigits) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (tp != endp) + return (0); + memmove(dst, tmp, NS_LOCATORSZ); + return (1); +} + +static inline int +getquad(const void *src, struct in_addr *dst, + isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) +{ + int result; + struct in_addr tmp; + + result = inet_aton(src, dst); + if (result == 1 && callbacks != NULL && + inet_pton(AF_INET, src, &tmp) != 1) { + const char *name = isc_lex_getsourcename(lexer); + if (name == NULL) + name = "UNKNOWN"; + (*callbacks->warn)(callbacks, "%s:%lu: \"%s\" " + "is not a decimal dotted quad", name, + isc_lex_getsourceline(lexer), src); + } + return (result); +} + +static inline isc_result_t +name_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) { + + if (mctx != NULL) + return (dns_name_dup(source, mctx, target)); + dns_name_clone(source, target); + return (ISC_R_SUCCESS); +} + +static inline void * +mem_maybedup(isc_mem_t *mctx, void *source, size_t length) { + void *copy; + + if (mctx == NULL) + return (source); + copy = isc_mem_allocate(mctx, length); + if (copy != NULL) + memmove(copy, source, length); + + return (copy); +} + +static inline isc_result_t +typemap_fromtext(isc_lex_t *lexer, isc_buffer_t *target, + bool allow_empty) +{ + isc_token_t token; + unsigned char bm[8*1024]; /* 64k bits */ + dns_rdatatype_t covered, max_used; + int octet; + unsigned int max_octet, newend, end; + int window; + bool first = true; + + max_used = 0; + bm[0] = 0; + end = 0; + + do { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, true)); + if (token.type != isc_tokentype_string) + break; + RETTOK(dns_rdatatype_fromtext(&covered, + &token.value.as_textregion)); + if (covered > max_used) { + newend = covered / 8; + if (newend > end) { + memset(&bm[end + 1], 0, newend - end); + end = newend; + } + max_used = covered; + } + bm[covered/8] |= (0x80>>(covered%8)); + first = false; + } while (1); + isc_lex_ungettoken(lexer, &token); + if (!allow_empty && first) + return (DNS_R_FORMERR); + + for (window = 0; window < 256 ; window++) { + if (max_used < window * 256) + break; + + max_octet = max_used - (window * 256); + if (max_octet >= 256) + max_octet = 31; + else + max_octet /= 8; + + /* + * Find if we have a type in this window. + */ + for (octet = max_octet; octet >= 0; octet--) { + if (bm[window * 32 + octet] != 0) + break; + } + if (octet < 0) + continue; + RETERR(uint8_tobuffer(window, target)); + RETERR(uint8_tobuffer(octet + 1, target)); + RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +typemap_totext(isc_region_t *sr, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ + unsigned int i, j, k; + unsigned int window, len; + bool first = true; + + for (i = 0; i < sr->length; i += len) { + if (tctx != NULL && + (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext(tctx->linebreak, target)); + first = true; + } + INSIST(i + 2 <= sr->length); + window = sr->base[i]; + len = sr->base[i + 1]; + INSIST(len > 0 && len <= 32); + i += 2; + INSIST(i + len <= sr->length); + for (j = 0; j < len; j++) { + dns_rdatatype_t t; + if (sr->base[i + j] == 0) + continue; + for (k = 0; k < 8; k++) { + if ((sr->base[i + j] & (0x80 >> k)) == 0) + continue; + t = window * 256 + j * 8 + k; + if (!first) + RETERR(str_totext(" ", target)); + first = false; + if (dns_rdatatype_isknown(t)) { + RETERR(dns_rdatatype_totext(t, target)); + } else { + char buf[sizeof("TYPE65535")]; + snprintf(buf, sizeof(buf), "TYPE%u", t); + RETERR(str_totext(buf, target)); + } + } + } + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +typemap_test(isc_region_t *sr, bool allow_empty) { + unsigned int window, lastwindow = 0; + unsigned int len; + bool first = true; + unsigned int i; + + for (i = 0; i < sr->length; i += len) { + /* + * Check for overflow. + */ + if (i + 2 > sr->length) + RETERR(DNS_R_FORMERR); + window = sr->base[i]; + len = sr->base[i + 1]; + i += 2; + /* + * Check that bitmap windows are in the correct order. + */ + if (!first && window <= lastwindow) + RETERR(DNS_R_FORMERR); + /* + * Check for legal lengths. + */ + if (len < 1 || len > 32) + RETERR(DNS_R_FORMERR); + /* + * Check for overflow. + */ + if (i + len > sr->length) + RETERR(DNS_R_FORMERR); + /* + * The last octet of the bitmap must be non zero. + */ + if (sr->base[i + len - 1] == 0) + RETERR(DNS_R_FORMERR); + lastwindow = window; + first = false; + } + if (i != sr->length) + return (DNS_R_EXTRADATA); + if (!allow_empty && first) + RETERR(DNS_R_FORMERR); + return (ISC_R_SUCCESS); +} + +static const char hexdigits[] = "0123456789abcdef"; +static const char decdigits[] = "0123456789"; + +#include "code.h" + +#define META 0x0001 +#define RESERVED 0x0002 + +/*** + *** Initialization + ***/ + +void +dns_rdata_init(dns_rdata_t *rdata) { + + REQUIRE(rdata != NULL); + + rdata->data = NULL; + rdata->length = 0; + rdata->rdclass = 0; + rdata->type = 0; + rdata->flags = 0; + ISC_LINK_INIT(rdata, link); + /* ISC_LIST_INIT(rdata->list); */ +} + +void +dns_rdata_reset(dns_rdata_t *rdata) { + + REQUIRE(rdata != NULL); + + REQUIRE(!ISC_LINK_LINKED(rdata, link)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->rdclass = 0; + rdata->type = 0; + rdata->flags = 0; +} + +/*** + *** + ***/ + +void +dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) { + + REQUIRE(src != NULL); + REQUIRE(target != NULL); + + REQUIRE(DNS_RDATA_INITIALIZED(target)); + + REQUIRE(DNS_RDATA_VALIDFLAGS(src)); + REQUIRE(DNS_RDATA_VALIDFLAGS(target)); + + target->data = src->data; + target->length = src->length; + target->rdclass = src->rdclass; + target->type = src->type; + target->flags = src->flags; +} + + +/*** + *** Comparisons + ***/ + +int +dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { + int result = 0; + bool use_default = false; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->length == 0 || rdata1->data != NULL); + REQUIRE(rdata2->length == 0 || rdata2->data != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); + + if (rdata1->rdclass != rdata2->rdclass) + return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); + + if (rdata1->type != rdata2->type) + return (rdata1->type < rdata2->type ? -1 : 1); + + COMPARESWITCH + + if (use_default) { + isc_region_t r1; + isc_region_t r2; + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + result = isc_region_compare(&r1, &r2); + } + return (result); +} + +int +dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { + int result = 0; + bool use_default = false; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->length == 0 || rdata1->data != NULL); + REQUIRE(rdata2->length == 0 || rdata2->data != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); + + if (rdata1->rdclass != rdata2->rdclass) + return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); + + if (rdata1->type != rdata2->type) + return (rdata1->type < rdata2->type ? -1 : 1); + + CASECOMPARESWITCH + + if (use_default) { + isc_region_t r1; + isc_region_t r2; + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + result = isc_region_compare(&r1, &r2); + } + return (result); +} + +/*** + *** Conversions + ***/ + +void +dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t type, isc_region_t *r) +{ + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(r != NULL); + + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + rdata->data = r->base; + rdata->length = r->length; + rdata->rdclass = rdclass; + rdata->type = type; + rdata->flags = 0; +} + +void +dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) { + + REQUIRE(rdata != NULL); + REQUIRE(r != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + r->base = rdata->data; + r->length = rdata->length; +} + +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) +{ + isc_result_t result = ISC_R_NOTIMPLEMENTED; + isc_region_t region; + isc_buffer_t ss; + isc_buffer_t st; + bool use_default = false; + uint32_t activelength; + unsigned int length; + + REQUIRE(dctx != NULL); + if (rdata != NULL) { + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + } + REQUIRE(source != NULL); + REQUIRE(target != NULL); + + if (type == 0) + return (DNS_R_FORMERR); + + ss = *source; + st = *target; + + activelength = isc_buffer_activelength(source); + INSIST(activelength < 65536); + + FROMWIRESWITCH + + if (use_default) { + if (activelength > isc_buffer_availablelength(target)) + result = ISC_R_NOSPACE; + else { + isc_buffer_putmem(target, isc_buffer_current(source), + activelength); + isc_buffer_forward(source, activelength); + result = ISC_R_SUCCESS; + } + } + + /* + * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH + * as we cannot transmit it. + */ + length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); + if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) + result = DNS_R_FORMERR; + + /* + * We should have consumed all of our buffer. + */ + if (result == ISC_R_SUCCESS && !buffer_empty(source)) + result = DNS_R_EXTRADATA; + + if (rdata != NULL && result == ISC_R_SUCCESS) { + region.base = isc_buffer_used(&st); + region.length = length; + dns_rdata_fromregion(rdata, rdclass, type, ®ion); + } + + if (result != ISC_R_SUCCESS) { + *source = ss; + *target = st; + } + return (result); +} + +isc_result_t +dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx, + isc_buffer_t *target) +{ + isc_result_t result = ISC_R_NOTIMPLEMENTED; + bool use_default = false; + isc_region_t tr; + isc_buffer_t st; + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + /* + * Some DynDNS meta-RRs have empty rdata. + */ + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { + INSIST(rdata->length == 0); + return (ISC_R_SUCCESS); + } + + st = *target; + + TOWIRESWITCH + + if (use_default) { + isc_buffer_availableregion(target, &tr); + if (tr.length < rdata->length) + return (ISC_R_NOSPACE); + memmove(tr.base, rdata->data, rdata->length); + isc_buffer_add(target, rdata->length); + return (ISC_R_SUCCESS); + } + if (result != ISC_R_SUCCESS) { + *target = st; + INSIST(target->used < 65536); + dns_compress_rollback(cctx, (uint16_t)target->used); + } + return (result); +} + +/* + * If the binary data in 'src' is valid uncompressed wire format + * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS + * and copy the validated rdata to 'dest'. Otherwise return an error. + */ +static isc_result_t +rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass, + dns_rdatatype_t type) +{ + dns_decompress_t dctx; + isc_result_t result; + + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); + isc_buffer_setactive(src, isc_buffer_usedlength(src)); + result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest); + dns_decompress_invalidate(&dctx); + + return (result); +} + +static isc_result_t +unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type, + isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target) +{ + isc_result_t result; + isc_buffer_t *buf = NULL; + isc_token_t token; + + if (type == 0 || dns_rdatatype_ismeta(type)) + return (DNS_R_METATYPE); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 65535U) + return (ISC_R_RANGE); + result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong); + if (result != ISC_R_SUCCESS) + return (result); + + result = isc_hex_tobuffer(lexer, buf, + (unsigned int)token.value.as_ulong); + if (result != ISC_R_SUCCESS) + goto failure; + if (isc_buffer_usedlength(buf) != token.value.as_ulong) { + result = ISC_R_UNEXPECTEDEND; + goto failure; + } + + if (dns_rdatatype_isknown(type)) { + result = rdata_validate(buf, target, rdclass, type); + } else { + isc_region_t r; + isc_buffer_usedregion(buf, &r); + result = isc_buffer_copyregion(target, &r); + } + if (result != ISC_R_SUCCESS) + goto failure; + + isc_buffer_free(&buf); + return (ISC_R_SUCCESS); + + failure: + isc_buffer_free(&buf); + return (result); +} + +isc_result_t +dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t type, isc_lex_t *lexer, + dns_name_t *origin, unsigned int options, isc_mem_t *mctx, + isc_buffer_t *target, dns_rdatacallbacks_t *callbacks) +{ + isc_result_t result = ISC_R_NOTIMPLEMENTED; + isc_region_t region; + isc_buffer_t st; + isc_token_t token; + unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | + ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; + char *name; + unsigned long line; + void (*callback)(dns_rdatacallbacks_t *, const char *, ...); + isc_result_t tresult; + unsigned int length; + bool unknown; + + REQUIRE(origin == NULL || dns_name_isabsolute(origin) == true); + if (rdata != NULL) { + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + } + if (callbacks != NULL) { + REQUIRE(callbacks->warn != NULL); + REQUIRE(callbacks->error != NULL); + } + + st = *target; + + if (callbacks != NULL) + callback = callbacks->error; + else + callback = default_fromtext_callback; + + result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false); + if (result != ISC_R_SUCCESS) { + name = isc_lex_getsourcename(lexer); + line = isc_lex_getsourceline(lexer); + fromtext_error(callback, callbacks, name, line, NULL, result); + return (result); + } + + unknown = false; + if (token.type == isc_tokentype_string && + strcmp(DNS_AS_STR(token), "\\#") == 0) { + /* + * If this is a TXT record '\#' could be a escaped '#'. + * Look to see if the next token is a number and if so + * treat it as a unknown record format. + */ + if (type == dns_rdatatype_txt) { + result = isc_lex_getmastertoken(lexer, &token, + isc_tokentype_number, + false); + if (result == ISC_R_SUCCESS) + isc_lex_ungettoken(lexer, &token); + } + + if (result == ISC_R_SUCCESS) { + unknown = true; + result = unknown_fromtext(rdclass, type, lexer, + mctx, target); + } else + options |= DNS_RDATA_UNKNOWNESCAPE; + } else + isc_lex_ungettoken(lexer, &token); + + if (!unknown) + FROMTEXTSWITCH + + /* + * Consume to end of line / file. + * If not at end of line initially set error code. + * Call callback via fromtext_error once if there was an error. + */ + do { + name = isc_lex_getsourcename(lexer); + line = isc_lex_getsourceline(lexer); + tresult = isc_lex_gettoken(lexer, lexoptions, &token); + if (tresult != ISC_R_SUCCESS) { + if (result == ISC_R_SUCCESS) + result = tresult; + if (callback != NULL) + fromtext_error(callback, callbacks, name, + line, NULL, result); + break; + } else if (token.type != isc_tokentype_eol && + token.type != isc_tokentype_eof) { + if (result == ISC_R_SUCCESS) + result = DNS_R_EXTRATOKEN; + if (callback != NULL) { + fromtext_error(callback, callbacks, name, + line, &token, result); + callback = NULL; + } + } else if (result != ISC_R_SUCCESS && callback != NULL) { + fromtext_error(callback, callbacks, name, line, + &token, result); + break; + } else { + if (token.type == isc_tokentype_eof) + fromtext_warneof(lexer, callbacks); + break; + } + } while (1); + + length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); + if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) + result = ISC_R_NOSPACE; + + if (rdata != NULL && result == ISC_R_SUCCESS) { + region.base = isc_buffer_used(&st); + region.length = length; + dns_rdata_fromregion(rdata, rdclass, type, ®ion); + } + if (result != ISC_R_SUCCESS) { + *target = st; + } + return (result); +} + +static isc_result_t +unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ + isc_result_t result; + char buf[sizeof("65535")]; + isc_region_t sr; + + strlcpy(buf, "\\# ", sizeof(buf)); + result = str_totext(buf, target); + if (result != ISC_R_SUCCESS) + return (result); + + dns_rdata_toregion(rdata, &sr); + INSIST(sr.length < 65536); + snprintf(buf, sizeof(buf), "%u", sr.length); + result = str_totext(buf, target); + if (result != ISC_R_SUCCESS) + return (result); + + if (sr.length != 0U) { + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + result = str_totext(" ( ", target); + else + result = str_totext(" ", target); + + if (result != ISC_R_SUCCESS) + return (result); + + if (tctx->width == 0) /* No splitting */ + result = isc_hex_totext(&sr, 0, "", target); + else + result = isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, + target); + if (result == ISC_R_SUCCESS && + (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + result = str_totext(" )", target); + } + return (result); +} + +static isc_result_t +rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ + isc_result_t result = ISC_R_NOTIMPLEMENTED; + bool use_default = false; + unsigned int cur; + + REQUIRE(rdata != NULL); + REQUIRE(tctx->origin == NULL || + dns_name_isabsolute(tctx->origin) == true); + + /* + * Some DynDNS meta-RRs have empty rdata. + */ + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { + INSIST(rdata->length == 0); + return (ISC_R_SUCCESS); + } + + if ((tctx->flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0) + return (unknown_totext(rdata, tctx, target)); + + cur = isc_buffer_usedlength(target); + + TOTEXTSWITCH + + if (use_default || (result == ISC_R_NOTIMPLEMENTED)) { + unsigned int u = isc_buffer_usedlength(target); + + INSIST(u >= cur); + isc_buffer_subtract(target, u - cur); + result = unknown_totext(rdata, tctx, target); + } + + return (result); +} + +isc_result_t +dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) +{ + dns_rdata_textctx_t tctx; + + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + /* + * Set up formatting options for single-line output. + */ + tctx.origin = origin; + tctx.flags = 0; + tctx.width = 60; + tctx.linebreak = " "; + return (rdata_totext(rdata, &tctx, target)); +} + +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) +{ + dns_rdata_textctx_t tctx; + + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + /* + * Set up formatting options for formatted output. + */ + tctx.origin = origin; + tctx.flags = flags; + if (split_width == 0xffffffff) + tctx.width = width; + else + tctx.width = split_width; + + if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) + tctx.linebreak = linebreak; + else { + if (split_width == 0xffffffff) + tctx.width = 60; /* Used for hex word length only. */ + tctx.linebreak = " "; + } + return (rdata_totext(rdata, &tctx, target)); +} + +isc_result_t +dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t type, void *source, + isc_buffer_t *target) +{ + isc_result_t result = ISC_R_NOTIMPLEMENTED; + isc_buffer_t st; + isc_region_t region; + bool use_default = false; + unsigned int length; + + REQUIRE(source != NULL); + if (rdata != NULL) { + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + } + + st = *target; + + FROMSTRUCTSWITCH + + if (use_default) + (void)NULL; + + length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); + if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) + result = ISC_R_NOSPACE; + + if (rdata != NULL && result == ISC_R_SUCCESS) { + region.base = isc_buffer_used(&st); + region.length = length; + dns_rdata_fromregion(rdata, rdclass, type, ®ion); + } + if (result != ISC_R_SUCCESS) + *target = st; + return (result); +} + +isc_result_t +dns_rdata_tostruct(const dns_rdata_t *rdata, void *target, isc_mem_t *mctx) { + isc_result_t result = ISC_R_NOTIMPLEMENTED; + bool use_default = false; + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + TOSTRUCTSWITCH + + if (use_default) + (void)NULL; + + return (result); +} + +void +dns_rdata_freestruct(void *source) { + dns_rdatacommon_t *common = source; + REQUIRE(source != NULL); + + FREESTRUCTSWITCH +} + +isc_result_t +dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add, + void *arg) +{ + isc_result_t result = ISC_R_NOTIMPLEMENTED; + bool use_default = false; + + /* + * Call 'add' for each name and type from 'rdata' which is subject to + * additional section processing. + */ + + REQUIRE(rdata != NULL); + REQUIRE(add != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + ADDITIONALDATASWITCH + + /* No additional processing for unknown types */ + if (use_default) + result = ISC_R_SUCCESS; + + return (result); +} + +isc_result_t +dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) { + isc_result_t result = ISC_R_NOTIMPLEMENTED; + bool use_default = false; + isc_region_t r; + + /* + * Send 'rdata' in DNSSEC canonical form to 'digest'. + */ + + REQUIRE(rdata != NULL); + REQUIRE(digest != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + + DIGESTSWITCH + + if (use_default) { + dns_rdata_toregion(rdata, &r); + result = (digest)(arg, &r); + } + + return (result); +} + +bool +dns_rdata_checkowner(dns_name_t *name, dns_rdataclass_t rdclass, + dns_rdatatype_t type, bool wildcard) +{ + bool result; + + CHECKOWNERSWITCH + return (result); +} + +bool +dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad) +{ + bool result; + + CHECKNAMESSWITCH + return (result); +} + +unsigned int +dns_rdatatype_attributes(dns_rdatatype_t type) +{ + RDATATYPE_ATTRIBUTE_SW + if (type >= (dns_rdatatype_t)128 && type < (dns_rdatatype_t)255) + return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META); + return (DNS_RDATATYPEATTR_UNKNOWN); +} + +isc_result_t +dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { + unsigned int hash; + unsigned int n; + unsigned char a, b; + + n = source->length; + + if (n == 0) + return (DNS_R_UNKNOWN); + + a = tolower((unsigned char)source->base[0]); + b = tolower((unsigned char)source->base[n - 1]); + + hash = ((a + n) * b) % 256; + + /* + * This switch block is inlined via \#define, and will use "return" + * to return a result to the caller if it is a valid (known) + * rdatatype name. + */ + RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep); + + if (source->length > 4 && source->length < (4 + sizeof("65000")) && + strncasecmp("type", source->base, 4) == 0) { + char buf[sizeof("65000")]; + char *endp; + unsigned int val; + + /* + * source->base is not required to be NUL terminated. + * Copy up to remaining bytes and NUL terminate. + */ + snprintf(buf, sizeof(buf), "%.*s", + (int)(source->length - 4), source->base + 4); + val = strtoul(buf, &endp, 10); + if (*endp == '\0' && val <= 0xffff) { + *typep = (dns_rdatatype_t)val; + return (ISC_R_SUCCESS); + } + } + + return (DNS_R_UNKNOWN); +} + +isc_result_t +dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) { + RDATATYPE_TOTEXT_SW + + return (dns_rdatatype_tounknowntext(type, target)); +} + +isc_result_t +dns_rdatatype_tounknowntext(dns_rdatatype_t type, isc_buffer_t *target) { + char buf[sizeof("TYPE65535")]; + + snprintf(buf, sizeof(buf), "TYPE%u", type); + return (str_totext(buf, target)); +} + +void +dns_rdatatype_format(dns_rdatatype_t rdtype, + char *array, unsigned int size) +{ + isc_result_t result; + isc_buffer_t buf; + + if (size == 0U) + return; + + isc_buffer_init(&buf, array, size); + result = dns_rdatatype_totext(rdtype, &buf); + /* + * Null terminate. + */ + if (result == ISC_R_SUCCESS) { + if (isc_buffer_availablelength(&buf) >= 1) + isc_buffer_putuint8(&buf, 0); + else + result = ISC_R_NOSPACE; + } + if (result != ISC_R_SUCCESS) + strlcpy(array, "<unknown>", size); +} + +/* + * Private function. + */ + +static unsigned int +name_length(dns_name_t *name) { + return (name->length); +} + +static isc_result_t +txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target) { + unsigned int tl; + unsigned int n; + unsigned char *sp; + char *tp; + isc_region_t region; + + isc_buffer_availableregion(target, ®ion); + sp = source->base; + tp = (char *)region.base; + tl = region.length; + + n = *sp++; + + REQUIRE(n + 1 <= source->length); + if (n == 0U) + REQUIRE(quote == true); + + if (quote) { + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = '"'; + tl--; + } + while (n--) { + /* + * \DDD space (0x20) if not quoting. + */ + if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) { + if (tl < 4) + return (ISC_R_NOSPACE); + *tp++ = 0x5c; + *tp++ = 0x30 + ((*sp / 100) % 10); + *tp++ = 0x30 + ((*sp / 10) % 10); + *tp++ = 0x30 + (*sp % 10); + sp++; + tl -= 4; + continue; + } + /* + * Escape double quote and backslash. If we are not + * enclosing the string in double quotes also escape + * at sign and semicolon. + */ + if (*sp == 0x22 || *sp == 0x5c || + (!quote && (*sp == 0x40 || *sp == 0x3b))) { + if (tl < 2) + return (ISC_R_NOSPACE); + *tp++ = '\\'; + tl--; + } + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = *sp++; + tl--; + } + if (quote) { + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = '"'; + tl--; + POST(tl); + } + isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); + isc_region_consume(source, *source->base + 1); + return (ISC_R_SUCCESS); +} + +static isc_result_t +txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { + isc_region_t tregion; + bool escape; + unsigned int n, nrem; + char *s; + unsigned char *t; + int d; + int c; + + isc_buffer_availableregion(target, &tregion); + s = source->base; + n = source->length; + t = tregion.base; + nrem = tregion.length; + escape = false; + if (nrem < 1) + return (ISC_R_NOSPACE); + /* + * Length byte. + */ + nrem--; + t++; + /* + * Maximum text string length. + */ + if (nrem > 255) + nrem = 255; + while (n-- != 0) { + c = (*s++) & 0xff; + if (escape && (d = decvalue((char)c)) != -1) { + c = d; + if (n == 0) + return (DNS_R_SYNTAX); + n--; + if ((d = decvalue(*s++)) != -1) + c = c * 10 + d; + else + return (DNS_R_SYNTAX); + if (n == 0) + return (DNS_R_SYNTAX); + n--; + if ((d = decvalue(*s++)) != -1) + c = c * 10 + d; + else + return (DNS_R_SYNTAX); + if (c > 255) + return (DNS_R_SYNTAX); + } else if (!escape && c == '\\') { + escape = true; + continue; + } + escape = false; + if (nrem == 0) + return ((tregion.length <= 256U) ? + ISC_R_NOSPACE : DNS_R_SYNTAX); + *t++ = c; + nrem--; + } + if (escape) + return (DNS_R_SYNTAX); + *tregion.base = (unsigned char)(t - tregion.base - 1); + isc_buffer_add(target, *tregion.base + 1); + return (ISC_R_SUCCESS); +} + +static isc_result_t +txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { + unsigned int n; + isc_region_t sregion; + isc_region_t tregion; + + isc_buffer_activeregion(source, &sregion); + if (sregion.length == 0) + return (ISC_R_UNEXPECTEDEND); + n = *sregion.base + 1; + if (n > sregion.length) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_availableregion(target, &tregion); + if (n > tregion.length) + return (ISC_R_NOSPACE); + + if (tregion.base != sregion.base) + memmove(tregion.base, sregion.base, n); + isc_buffer_forward(source, n); + isc_buffer_add(target, n); + return (ISC_R_SUCCESS); +} + +/* + * Conversion of TXT-like rdata fields without length limits. + */ +static isc_result_t +multitxt_totext(isc_region_t *source, isc_buffer_t *target) { + unsigned int tl; + unsigned int n0, n; + unsigned char *sp; + char *tp; + isc_region_t region; + + isc_buffer_availableregion(target, ®ion); + sp = source->base; + tp = (char *)region.base; + tl = region.length; + + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = '"'; + tl--; + do { + n = source->length; + n0 = source->length - 1; + + while (n--) { + if (*sp < 0x20 || *sp >= 0x7f) { + if (tl < 4) + return (ISC_R_NOSPACE); + *tp++ = 0x5c; + *tp++ = 0x30 + ((*sp / 100) % 10); + *tp++ = 0x30 + ((*sp / 10) % 10); + *tp++ = 0x30 + (*sp % 10); + sp++; + tl -= 4; + continue; + } + /* double quote, backslash */ + if (*sp == 0x22 || *sp == 0x5c) { + if (tl < 2) + return (ISC_R_NOSPACE); + *tp++ = '\\'; + tl--; + } + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = *sp++; + tl--; + } + isc_region_consume(source, n0 + 1); + } while (source->length != 0); + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = '"'; + tl--; + POST(tl); + isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); + return (ISC_R_SUCCESS); +} + +static isc_result_t +multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { + isc_region_t tregion; + bool escape; + unsigned int n, nrem; + char *s; + unsigned char *t0, *t; + int d; + int c; + + s = source->base; + n = source->length; + escape = false; + + do { + isc_buffer_availableregion(target, &tregion); + t0 = t = tregion.base; + nrem = tregion.length; + if (nrem < 1) + return (ISC_R_NOSPACE); + + while (n != 0) { + --n; + c = (*s++) & 0xff; + if (escape && (d = decvalue((char)c)) != -1) { + c = d; + if (n == 0) + return (DNS_R_SYNTAX); + n--; + if ((d = decvalue(*s++)) != -1) + c = c * 10 + d; + else + return (DNS_R_SYNTAX); + if (n == 0) + return (DNS_R_SYNTAX); + n--; + if ((d = decvalue(*s++)) != -1) + c = c * 10 + d; + else + return (DNS_R_SYNTAX); + if (c > 255) + return (DNS_R_SYNTAX); + } else if (!escape && c == '\\') { + escape = true; + continue; + } + escape = false; + *t++ = c; + nrem--; + if (nrem == 0) + break; + } + if (escape) + return (DNS_R_SYNTAX); + + isc_buffer_add(target, (unsigned int)(t - t0)); + } while (n != 0); + return (ISC_R_SUCCESS); +} + +static bool +name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) { + int l1, l2; + + if (origin == NULL) + goto return_false; + + if (dns_name_compare(origin, dns_rootname) == 0) + goto return_false; + + if (!dns_name_issubdomain(name, origin)) + goto return_false; + + l1 = dns_name_countlabels(name); + l2 = dns_name_countlabels(origin); + + if (l1 == l2) + goto return_false; + + /* Master files should be case preserving. */ + dns_name_getlabelsequence(name, l1 - l2, l2, target); + if (!dns_name_caseequal(origin, target)) + goto return_false; + + dns_name_getlabelsequence(name, 0, l1 - l2, target); + return (true); + +return_false: + *target = *name; + return (false); +} + +static isc_result_t +str_totext(const char *source, isc_buffer_t *target) { + unsigned int l; + isc_region_t region; + + isc_buffer_availableregion(target, ®ion); + l = strlen(source); + + if (l > region.length) + return (ISC_R_NOSPACE); + + memmove(region.base, source, l); + isc_buffer_add(target, l); + return (ISC_R_SUCCESS); +} + +static isc_result_t +inet_totext(int af, isc_region_t *src, isc_buffer_t *target) { + char tmpbuf[64]; + + /* Note - inet_ntop doesn't do size checking on its input. */ + if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL) + return (ISC_R_NOSPACE); + if (strlen(tmpbuf) > isc_buffer_availablelength(target)) + return (ISC_R_NOSPACE); + isc_buffer_putstr(target, tmpbuf); + return (ISC_R_SUCCESS); +} + +static bool +buffer_empty(isc_buffer_t *source) { + return((source->current == source->active) ? true : false); +} + +static void +buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) { + isc_buffer_init(buffer, region->base, region->length); + isc_buffer_add(buffer, region->length); + isc_buffer_setactive(buffer, region->length); +} + +static isc_result_t +uint32_tobuffer(uint32_t value, isc_buffer_t *target) { + isc_region_t region; + + isc_buffer_availableregion(target, ®ion); + if (region.length < 4) + return (ISC_R_NOSPACE); + isc_buffer_putuint32(target, value); + return (ISC_R_SUCCESS); +} + +static isc_result_t +uint16_tobuffer(uint32_t value, isc_buffer_t *target) { + isc_region_t region; + + if (value > 0xffff) + return (ISC_R_RANGE); + isc_buffer_availableregion(target, ®ion); + if (region.length < 2) + return (ISC_R_NOSPACE); + isc_buffer_putuint16(target, (uint16_t)value); + return (ISC_R_SUCCESS); +} + +static isc_result_t +uint8_tobuffer(uint32_t value, isc_buffer_t *target) { + isc_region_t region; + + if (value > 0xff) + return (ISC_R_RANGE); + isc_buffer_availableregion(target, ®ion); + if (region.length < 1) + return (ISC_R_NOSPACE); + isc_buffer_putuint8(target, (uint8_t)value); + return (ISC_R_SUCCESS); +} + +static isc_result_t +name_tobuffer(dns_name_t *name, isc_buffer_t *target) { + isc_region_t r; + dns_name_toregion(name, &r); + return (isc_buffer_copyregion(target, &r)); +} + +static uint32_t +uint32_fromregion(isc_region_t *region) { + uint32_t value; + + REQUIRE(region->length >= 4); + value = (uint32_t)region->base[0] << 24; + value |= (uint32_t)region->base[1] << 16; + value |= (uint32_t)region->base[2] << 8; + value |= (uint32_t)region->base[3]; + return(value); +} + +static uint16_t +uint16_consume_fromregion(isc_region_t *region) { + uint16_t r = uint16_fromregion(region); + + isc_region_consume(region, 2); + return r; +} + +static uint16_t +uint16_fromregion(isc_region_t *region) { + + REQUIRE(region->length >= 2); + + return ((region->base[0] << 8) | region->base[1]); +} + +static uint8_t +uint8_fromregion(isc_region_t *region) { + + REQUIRE(region->length >= 1); + + return (region->base[0]); +} + +static uint8_t +uint8_consume_fromregion(isc_region_t *region) { + uint8_t r = uint8_fromregion(region); + + isc_region_consume(region, 1); + return r; +} + +static isc_result_t +mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) { + isc_region_t tr; + + if (length == 0U) + return (ISC_R_SUCCESS); + + isc_buffer_availableregion(target, &tr); + if (length > tr.length) + return (ISC_R_NOSPACE); + if (tr.base != base) + memmove(tr.base, base, length); + isc_buffer_add(target, length); + return (ISC_R_SUCCESS); +} + +static int +hexvalue(char value) { + const char *s; + unsigned char c; + + c = (unsigned char)value; + + if (!isascii(c)) + return (-1); + if (isupper(c)) + c = tolower(c); + if ((s = strchr(hexdigits, c)) == NULL) + return (-1); + return (int)(s - hexdigits); +} + +static int +decvalue(char value) { + const char *s; + + /* + * isascii() is valid for full range of int values, no need to + * mask or cast. + */ + if (!isascii(value)) + return (-1); + if ((s = strchr(decdigits, value)) == NULL) + return (-1); + return (int)(s - decdigits); +} + +static const char atob_digits[86] = + "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \ + "abcdefghijklmnopqrstu"; +/* + * Subroutines to convert between 8 bit binary bytes and printable ASCII. + * Computes the number of bytes, and three kinds of simple checksums. + * Incoming bytes are collected into 32-bit words, then printed in base 85: + * exp(85,5) > exp(2,32) + * The ASCII characters used are between '!' and 'u'; + * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data. + * + * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for + * the atob/btoa programs, released with the compress program, in mod.sources. + * Modified by Mike Schwartz 8/19/86 for use in BIND. + * Modified to be re-entrant 3/2/99. + */ + + +struct state { + int32_t Ceor; + int32_t Csum; + int32_t Crot; + int32_t word; + int32_t bcount; +}; + +#define Ceor state->Ceor +#define Csum state->Csum +#define Crot state->Crot +#define word state->word +#define bcount state->bcount + +#define times85(x) ((((((x<<2)+x)<<2)+x)<<2)+x) + +static isc_result_t byte_atob(int c, isc_buffer_t *target, + struct state *state); +static isc_result_t putbyte(int c, isc_buffer_t *, struct state *state); +static isc_result_t byte_btoa(int c, isc_buffer_t *, struct state *state); + +/* + * Decode ASCII-encoded byte c into binary representation and + * place into *bufp, advancing bufp. + */ +static isc_result_t +byte_atob(int c, isc_buffer_t *target, struct state *state) { + const char *s; + if (c == 'z') { + if (bcount != 0) + return(DNS_R_SYNTAX); + else { + RETERR(putbyte(0, target, state)); + RETERR(putbyte(0, target, state)); + RETERR(putbyte(0, target, state)); + RETERR(putbyte(0, target, state)); + } + } else if ((s = strchr(atob_digits, c)) != NULL) { + if (bcount == 0) { + word = (int32_t)(s - atob_digits); + ++bcount; + } else if (bcount < 4) { + word = times85(word); + word += (int32_t)(s - atob_digits); + ++bcount; + } else { + word = times85(word); + word += (int32_t)(s - atob_digits); + RETERR(putbyte((word >> 24) & 0xff, target, state)); + RETERR(putbyte((word >> 16) & 0xff, target, state)); + RETERR(putbyte((word >> 8) & 0xff, target, state)); + RETERR(putbyte(word & 0xff, target, state)); + word = 0; + bcount = 0; + } + } else + return(DNS_R_SYNTAX); + return(ISC_R_SUCCESS); +} + +/* + * Compute checksum info and place c into target. + */ +static isc_result_t +putbyte(int c, isc_buffer_t *target, struct state *state) { + isc_region_t tr; + + Ceor ^= c; + Csum += c; + Csum += 1; + if ((Crot & 0x80000000)) { + Crot <<= 1; + Crot += 1; + } else { + Crot <<= 1; + } + Crot += c; + isc_buffer_availableregion(target, &tr); + if (tr.length < 1) + return (ISC_R_NOSPACE); + tr.base[0] = c; + isc_buffer_add(target, 1); + return (ISC_R_SUCCESS); +} + +/* + * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert + * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes; + * outbuflen must be divisible by 4. (Note: this is because outbuf is filled + * in 4 bytes at a time. If the actual data doesn't end on an even 4-byte + * boundary, there will be no problem...it will be padded with 0 bytes, and + * numbytes will indicate the correct number of bytes. The main point is + * that since the buffer is filled in 4 bytes at a time, even if there is + * not a full 4 bytes of data at the end, there has to be room to 0-pad the + * data, so the buffer must be of size divisible by 4). Place the number of + * output bytes in numbytes, and return a failure/success status. + */ + +static isc_result_t +atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) { + long oeor, osum, orot; + struct state statebuf, *state= &statebuf; + isc_token_t token; + char c; + char *e; + + Ceor = Csum = Crot = word = bcount = 0; + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + while (token.value.as_textregion.length != 0) { + if ((c = token.value.as_textregion.base[0]) == 'x') { + break; + } else + RETERR(byte_atob(c, target, state)); + isc_textregion_consume(&token.value.as_textregion, 1); + } + + /* + * Number of bytes. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if ((token.value.as_ulong % 4) != 0U) { + unsigned long padding = 4 - (token.value.as_ulong % 4); + if (isc_buffer_usedlength(target) < padding) + return (DNS_R_SYNTAX); + isc_buffer_subtract(target, padding); + } + + /* + * Checksum. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + oeor = strtol(DNS_AS_STR(token), &e, 16); + if (*e != 0) + return (DNS_R_SYNTAX); + + /* + * Checksum. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + osum = strtol(DNS_AS_STR(token), &e, 16); + if (*e != 0) + return (DNS_R_SYNTAX); + + /* + * Checksum. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + orot = strtol(DNS_AS_STR(token), &e, 16); + if (*e != 0) + return (DNS_R_SYNTAX); + + if ((oeor != Ceor) || (osum != Csum) || (orot != Crot)) + return(DNS_R_BADCKSUM); + return (ISC_R_SUCCESS); +} + +/* + * Encode binary byte c into ASCII representation and place into *bufp, + * advancing bufp. + */ +static isc_result_t +byte_btoa(int c, isc_buffer_t *target, struct state *state) { + isc_region_t tr; + + isc_buffer_availableregion(target, &tr); + Ceor ^= c; + Csum += c; + Csum += 1; + if ((Crot & 0x80000000)) { + Crot <<= 1; + Crot += 1; + } else { + Crot <<= 1; + } + Crot += c; + + word <<= 8; + word |= c; + if (bcount == 3) { + if (word == 0) { + if (tr.length < 1) + return (ISC_R_NOSPACE); + tr.base[0] = 'z'; + isc_buffer_add(target, 1); + } else { + register int tmp = 0; + register int32_t tmpword = word; + + if (tmpword < 0) { + /* + * Because some don't support u_long. + */ + tmp = 32; + tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32); + } + if (tmpword < 0) { + tmp = 64; + tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32); + } + if (tr.length < 5) + return (ISC_R_NOSPACE); + tr.base[0] = atob_digits[(tmpword / + (int32_t)(85 * 85 * 85 * 85)) + + tmp]; + tmpword %= (int32_t)(85 * 85 * 85 * 85); + tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)]; + tmpword %= (85 * 85 * 85); + tr.base[2] = atob_digits[tmpword / (85 * 85)]; + tmpword %= (85 * 85); + tr.base[3] = atob_digits[tmpword / 85]; + tmpword %= 85; + tr.base[4] = atob_digits[tmpword]; + isc_buffer_add(target, 5); + } + bcount = 0; + } else { + bcount += 1; + } + return (ISC_R_SUCCESS); +} + + +/* + * Encode the binary data from inbuf, of length inbuflen, into a + * target. Return success/failure status + */ +static isc_result_t +btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) { + int inc; + struct state statebuf, *state = &statebuf; + char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")]; + + Ceor = Csum = Crot = word = bcount = 0; + for (inc = 0; inc < inbuflen; inbuf++, inc++) + RETERR(byte_btoa(*inbuf, target, state)); + + while (bcount != 0) + RETERR(byte_btoa(0, target, state)); + + /* + * Put byte count and checksum information at end of buffer, + * delimited by 'x' + */ + snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot); + return (str_totext(buf, target)); +} + + +static void +default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, + ...) +{ + va_list ap; + + UNUSED(callbacks); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void +fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) { + if (isc_lex_isfile(lexer) && callbacks != NULL) { + const char *name = isc_lex_getsourcename(lexer); + if (name == NULL) + name = "UNKNOWN"; + (*callbacks->warn)(callbacks, + "%s:%lu: file does not end with newline", + name, isc_lex_getsourceline(lexer)); + } +} + +static void +warn_badmx(isc_token_t *token, isc_lex_t *lexer, + dns_rdatacallbacks_t *callbacks) +{ + const char *file; + unsigned long line; + + if (lexer != NULL) { + file = isc_lex_getsourcename(lexer); + line = isc_lex_getsourceline(lexer); + (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s", + file, line, DNS_AS_STR(*token), + dns_result_totext(DNS_R_MXISADDRESS)); + } +} + +static void +warn_badname(dns_name_t *name, isc_lex_t *lexer, + dns_rdatacallbacks_t *callbacks) +{ + const char *file; + unsigned long line; + char namebuf[DNS_NAME_FORMATSIZE]; + + if (lexer != NULL) { + file = isc_lex_getsourcename(lexer); + line = isc_lex_getsourceline(lexer); + dns_name_format(name, namebuf, sizeof(namebuf)); + (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s", + file, line, namebuf, + dns_result_totext(DNS_R_BADNAME)); + } +} + +static void +fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), + dns_rdatacallbacks_t *callbacks, const char *name, + unsigned long line, isc_token_t *token, isc_result_t result) +{ + if (name == NULL) + name = "UNKNOWN"; + + if (token != NULL) { + switch (token->type) { + case isc_tokentype_eol: + (*callback)(callbacks, "%s: %s:%lu: near eol: %s", + "dns_rdata_fromtext", name, line, + dns_result_totext(result)); + break; + case isc_tokentype_eof: + (*callback)(callbacks, "%s: %s:%lu: near eof: %s", + "dns_rdata_fromtext", name, line, + dns_result_totext(result)); + break; + case isc_tokentype_number: + (*callback)(callbacks, "%s: %s:%lu: near %lu: %s", + "dns_rdata_fromtext", name, line, + token->value.as_ulong, + dns_result_totext(result)); + break; + case isc_tokentype_string: + case isc_tokentype_qstring: + (*callback)(callbacks, "%s: %s:%lu: near '%s': %s", + "dns_rdata_fromtext", name, line, + DNS_AS_STR(*token), + dns_result_totext(result)); + break; + default: + (*callback)(callbacks, "%s: %s:%lu: %s", + "dns_rdata_fromtext", name, line, + dns_result_totext(result)); + break; + } + } else { + (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s", + name, line, dns_result_totext(result)); + } +} + +dns_rdatatype_t +dns_rdata_covers(dns_rdata_t *rdata) { + if (rdata->type == dns_rdatatype_rrsig) + return (covers_rrsig(rdata)); + return (covers_sig(rdata)); +} + +bool +dns_rdatatype_ismeta(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0) + return (true); + return (false); +} + +bool +dns_rdatatype_issingleton(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON) + != 0) + return (true); + return (false); +} + +bool +dns_rdatatype_notquestion(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION) + != 0) + return (true); + return (false); +} + +bool +dns_rdatatype_questiononly(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY) + != 0) + return (true); + return (false); +} + +bool +dns_rdatatype_atparent(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0) + return (true); + return (false); +} + +bool +dns_rdataclass_ismeta(dns_rdataclass_t rdclass) { + + if (rdclass == dns_rdataclass_reserved0 + || rdclass == dns_rdataclass_none + || rdclass == dns_rdataclass_any) + return (true); + + return (false); /* Assume it is not a meta class. */ +} + +bool +dns_rdatatype_isdnssec(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0) + return (true); + return (false); +} + +bool +dns_rdatatype_iszonecutauth(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) + & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH)) + != 0) + return (true); + return (false); +} + +bool +dns_rdatatype_isknown(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN) + == 0) + return (true); + return (false); +} + +void +dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_any; +} + +void +dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_none; +} + +void +dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_any; +} + +void +dns_rdata_makedelete(dns_rdata_t *rdata) { + REQUIRE(rdata != NULL); + + rdata->rdclass = dns_rdataclass_none; +} + +const char * +dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + switch (section) { + case DNS_SECTION_PREREQUISITE: + switch (rdata->rdclass) { + case dns_rdataclass_none: + switch (rdata->type) { + case dns_rdatatype_any: + return ("domain doesn't exist"); + default: + return ("rrset doesn't exist"); + } + case dns_rdataclass_any: + switch (rdata->type) { + case dns_rdatatype_any: + return ("domain exists"); + default: + return ("rrset exists (value independent)"); + } + default: + return ("rrset exists (value dependent)"); + } + case DNS_SECTION_UPDATE: + switch (rdata->rdclass) { + case dns_rdataclass_none: + return ("delete"); + case dns_rdataclass_any: + switch (rdata->type) { + case dns_rdatatype_any: + return ("delete all rrsets"); + default: + return ("delete rrset"); + } + default: + return ("add"); + } + } + return ("invalid"); +} diff --git a/lib/dns/rdata/any_255/tsig_250.c b/lib/dns/rdata/any_255/tsig_250.c new file mode 100644 index 0000000..5cb24b2 --- /dev/null +++ b/lib/dns/rdata/any_255/tsig_250.c @@ -0,0 +1,598 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_ANY_255_TSIG_250_C +#define RDATA_ANY_255_TSIG_250_C + +#define RRTYPE_TSIG_ATTRIBUTES \ + (DNS_RDATATYPEATTR_META | DNS_RDATATYPEATTR_NOTQUESTION) + +static inline isc_result_t +fromtext_any_tsig(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + uint64_t sigtime; + isc_buffer_t buffer; + dns_rcode_t rcode; + long i; + char *e; + + REQUIRE(type == dns_rdatatype_tsig); + REQUIRE(rdclass == dns_rdataclass_any); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Algorithm Name. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + /* + * Time Signed: 48 bits. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + sigtime = isc_string_touint64(DNS_AS_STR(token), &e, 10); + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + if ((sigtime >> 48) != 0) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer((uint16_t)(sigtime >> 32), target)); + RETERR(uint32_tobuffer((uint32_t)(sigtime & 0xffffffffU), target)); + + /* + * Fudge. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Signature Size. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Signature. + */ + RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong)); + + /* + * Original ID. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Error. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion) + != ISC_R_SUCCESS) + { + i = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0) + RETTOK(DNS_R_UNKNOWN); + if (i < 0 || i > 0xffff) + RETTOK(ISC_R_RANGE); + rcode = (dns_rcode_t)i; + } + RETERR(uint16_tobuffer(rcode, target)); + + /* + * Other Len. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Other Data. + */ + return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong)); +} + +static inline isc_result_t +totext_any_tsig(ARGS_TOTEXT) { + isc_region_t sr; + isc_region_t sigr; + char buf[sizeof(" 281474976710655 ")]; + char *bufp; + dns_name_t name; + dns_name_t prefix; + bool sub; + uint64_t sigtime; + unsigned short n; + + REQUIRE(rdata->type == dns_rdatatype_tsig); + REQUIRE(rdata->rdclass == dns_rdataclass_any); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + /* + * Algorithm Name. + */ + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_name_fromregion(&name, &sr); + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + RETERR(str_totext(" ", target)); + isc_region_consume(&sr, name_length(&name)); + + /* + * Time Signed. + */ + sigtime = ((uint64_t)sr.base[0] << 40) | + ((uint64_t)sr.base[1] << 32) | + ((uint64_t)sr.base[2] << 24) | + ((uint64_t)sr.base[3] << 16) | + ((uint64_t)sr.base[4] << 8) | + (uint64_t)sr.base[5]; + isc_region_consume(&sr, 6); + bufp = &buf[sizeof(buf) - 1]; + *bufp-- = 0; + *bufp-- = ' '; + do { + *bufp-- = decdigits[sigtime % 10]; + sigtime /= 10; + } while (sigtime != 0); + bufp++; + RETERR(str_totext(bufp, target)); + + /* + * Fudge. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Signature Size. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u", n); + RETERR(str_totext(buf, target)); + + /* + * Signature. + */ + if (n != 0U) { + REQUIRE(n <= sr.length); + sigr = sr; + sigr.length = n; + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sigr, 60, "", target)); + else + RETERR(isc_base64_totext(&sigr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" ) ", target)); + else + RETERR(str_totext(" ", target)); + isc_region_consume(&sr, n); + } else { + RETERR(str_totext(" ", target)); + } + + /* + * Original ID. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Error. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + RETERR(dns_tsigrcode_totext((dns_rcode_t)n, target)); + + /* + * Other Size. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), " %u ", n); + RETERR(str_totext(buf, target)); + + /* + * Other. + */ + if (tctx->width == 0) /* No splitting */ + return (isc_base64_totext(&sr, 60, "", target)); + else + return (isc_base64_totext(&sr, 60, " ", target)); +} + +static inline isc_result_t +fromwire_any_tsig(ARGS_FROMWIRE) { + isc_region_t sr; + dns_name_t name; + unsigned long n; + + REQUIRE(type == dns_rdatatype_tsig); + REQUIRE(rdclass == dns_rdataclass_any); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + /* + * Algorithm Name. + */ + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + isc_buffer_activeregion(source, &sr); + /* + * Time Signed + Fudge. + */ + if (sr.length < 8) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, 8)); + isc_region_consume(&sr, 8); + isc_buffer_forward(source, 8); + + /* + * Signature Length + Signature. + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + n = uint16_fromregion(&sr); + if (sr.length < n + 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, n + 2)); + isc_region_consume(&sr, n + 2); + isc_buffer_forward(source, n + 2); + + /* + * Original ID + Error. + */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_region_consume(&sr, 4); + isc_buffer_forward(source, 4); + + /* + * Other Length + Other. + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + n = uint16_fromregion(&sr); + if (sr.length < n + 2) + return (ISC_R_UNEXPECTEDEND); + isc_buffer_forward(source, n + 2); + return (mem_tobuffer(target, sr.base, n + 2)); +} + +static inline isc_result_t +towire_any_tsig(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_tsig); + REQUIRE(rdata->rdclass == dns_rdataclass_any); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_rdata_toregion(rdata, &sr); + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + RETERR(dns_name_towire(&name, cctx, target)); + isc_region_consume(&sr, name_length(&name)); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_any_tsig(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_tsig); + REQUIRE(rdata1->rdclass == dns_rdataclass_any); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_any_tsig(ARGS_FROMSTRUCT) { + dns_rdata_any_tsig_t *tsig = source; + isc_region_t tr; + + REQUIRE(type == dns_rdatatype_tsig); + REQUIRE(rdclass == dns_rdataclass_any); + REQUIRE(source != NULL); + REQUIRE(tsig->common.rdclass == rdclass); + REQUIRE(tsig->common.rdtype == type); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Algorithm Name. + */ + RETERR(name_tobuffer(&tsig->algorithm, target)); + + isc_buffer_availableregion(target, &tr); + if (tr.length < 6 + 2 + 2) + return (ISC_R_NOSPACE); + + /* + * Time Signed: 48 bits. + */ + RETERR(uint16_tobuffer((uint16_t)(tsig->timesigned >> 32), + target)); + RETERR(uint32_tobuffer((uint32_t)(tsig->timesigned & 0xffffffffU), + target)); + + /* + * Fudge. + */ + RETERR(uint16_tobuffer(tsig->fudge, target)); + + /* + * Signature Size. + */ + RETERR(uint16_tobuffer(tsig->siglen, target)); + + /* + * Signature. + */ + RETERR(mem_tobuffer(target, tsig->signature, tsig->siglen)); + + isc_buffer_availableregion(target, &tr); + if (tr.length < 2 + 2 + 2) + return (ISC_R_NOSPACE); + + /* + * Original ID. + */ + RETERR(uint16_tobuffer(tsig->originalid, target)); + + /* + * Error. + */ + RETERR(uint16_tobuffer(tsig->error, target)); + + /* + * Other Len. + */ + RETERR(uint16_tobuffer(tsig->otherlen, target)); + + /* + * Other Data. + */ + return (mem_tobuffer(target, tsig->other, tsig->otherlen)); +} + +static inline isc_result_t +tostruct_any_tsig(ARGS_TOSTRUCT) { + dns_rdata_any_tsig_t *tsig; + dns_name_t alg; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_tsig); + REQUIRE(rdata->rdclass == dns_rdataclass_any); + REQUIRE(rdata->length != 0); + + tsig = (dns_rdata_any_tsig_t *) target; + tsig->common.rdclass = rdata->rdclass; + tsig->common.rdtype = rdata->type; + ISC_LINK_INIT(&tsig->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Algorithm Name. + */ + dns_name_init(&alg, NULL); + dns_name_fromregion(&alg, &sr); + dns_name_init(&tsig->algorithm, NULL); + RETERR(name_duporclone(&alg, mctx, &tsig->algorithm)); + + isc_region_consume(&sr, name_length(&tsig->algorithm)); + + /* + * Time Signed. + */ + INSIST(sr.length >= 6); + tsig->timesigned = ((uint64_t)sr.base[0] << 40) | + ((uint64_t)sr.base[1] << 32) | + ((uint64_t)sr.base[2] << 24) | + ((uint64_t)sr.base[3] << 16) | + ((uint64_t)sr.base[4] << 8) | + (uint64_t)sr.base[5]; + isc_region_consume(&sr, 6); + + /* + * Fudge. + */ + tsig->fudge = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Signature Size. + */ + tsig->siglen = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Signature. + */ + INSIST(sr.length >= tsig->siglen); + tsig->signature = mem_maybedup(mctx, sr.base, tsig->siglen); + if (tsig->signature == NULL) + goto cleanup; + isc_region_consume(&sr, tsig->siglen); + + /* + * Original ID. + */ + tsig->originalid = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Error. + */ + tsig->error = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Other Size. + */ + tsig->otherlen = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Other. + */ + INSIST(sr.length == tsig->otherlen); + tsig->other = mem_maybedup(mctx, sr.base, tsig->otherlen); + if (tsig->other == NULL) + goto cleanup; + + tsig->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&tsig->algorithm, tsig->mctx); + if (mctx != NULL && tsig->signature != NULL) + isc_mem_free(mctx, tsig->signature); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_any_tsig(ARGS_FREESTRUCT) { + dns_rdata_any_tsig_t *tsig = (dns_rdata_any_tsig_t *) source; + + REQUIRE(source != NULL); + REQUIRE(tsig->common.rdtype == dns_rdatatype_tsig); + REQUIRE(tsig->common.rdclass == dns_rdataclass_any); + + if (tsig->mctx == NULL) + return; + + dns_name_free(&tsig->algorithm, tsig->mctx); + if (tsig->signature != NULL) + isc_mem_free(tsig->mctx, tsig->signature); + if (tsig->other != NULL) + isc_mem_free(tsig->mctx, tsig->other); + tsig->mctx = NULL; +} + +static inline isc_result_t +additionaldata_any_tsig(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_tsig); + REQUIRE(rdata->rdclass == dns_rdataclass_any); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_any_tsig(ARGS_DIGEST) { + + REQUIRE(rdata->type == dns_rdatatype_tsig); + REQUIRE(rdata->rdclass == dns_rdataclass_any); + + UNUSED(rdata); + UNUSED(digest); + UNUSED(arg); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline bool +checkowner_any_tsig(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_tsig); + REQUIRE(rdclass == dns_rdataclass_any); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_any_tsig(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_tsig); + REQUIRE(rdata->rdclass == dns_rdataclass_any); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_any_tsig(ARGS_COMPARE) { + return (compare_any_tsig(rdata1, rdata2)); +} + +#endif /* RDATA_ANY_255_TSIG_250_C */ diff --git a/lib/dns/rdata/any_255/tsig_250.h b/lib/dns/rdata/any_255/tsig_250.h new file mode 100644 index 0000000..6ace1d2 --- /dev/null +++ b/lib/dns/rdata/any_255/tsig_250.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ANY_255_TSIG_250_H +#define ANY_255_TSIG_250_H 1 + +/*% RFC2845 */ +typedef struct dns_rdata_any_tsig { + dns_rdatacommon_t common; + isc_mem_t * mctx; + dns_name_t algorithm; + uint64_t timesigned; + uint16_t fudge; + uint16_t siglen; + unsigned char * signature; + uint16_t originalid; + uint16_t error; + uint16_t otherlen; + unsigned char * other; +} dns_rdata_any_tsig_t; + +#endif /* ANY_255_TSIG_250_H */ diff --git a/lib/dns/rdata/ch_3/a_1.c b/lib/dns/rdata/ch_3/a_1.c new file mode 100644 index 0000000..94cae92 --- /dev/null +++ b/lib/dns/rdata/ch_3/a_1.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* by Bjorn.Victor@it.uu.se, 2005-05-07 */ +/* Based on generic/soa_6.c and generic/mx_15.c */ + +#ifndef RDATA_CH_3_A_1_C +#define RDATA_CH_3_A_1_C + +#include <isc/net.h> + +#define RRTYPE_A_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_ch_a(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_ch); /* 3 */ + + UNUSED(type); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + /* get domain name */ + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + if ((options & DNS_RDATA_CHECKNAMES) != 0 && + (options & DNS_RDATA_CHECKREVERSE) != 0) { + bool ok; + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + } + + /* 16-bit octal address */ + RETERR(isc_lex_getoctaltoken(lexer, &token, false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + return (uint16_tobuffer(token.value.as_ulong, target)); +} + +static inline isc_result_t +totext_ch_a(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("0177777")]; + uint16_t addr; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_ch); /* 3 */ + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + addr = uint16_fromregion(®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + snprintf(buf, sizeof(buf), "%o", addr); /* note octal */ + RETERR(str_totext(" ", target)); + return (str_totext(buf, target)); +} + +static inline isc_result_t +fromwire_ch_a(ARGS_FROMWIRE) { + isc_region_t sregion; + isc_region_t tregion; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_ch); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + if (sregion.length < 2) + return (ISC_R_UNEXPECTEDEND); + if (tregion.length < 2) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 2); + isc_buffer_forward(source, 2); + isc_buffer_add(target, 2); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_ch_a(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t sregion; + isc_region_t tregion; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_ch); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + + dns_rdata_toregion(rdata, &sregion); + + dns_name_fromregion(&name, &sregion); + isc_region_consume(&sregion, name_length(&name)); + RETERR(dns_name_towire(&name, cctx, target)); + + isc_buffer_availableregion(target, &tregion); + if (tregion.length < 2) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 2); + isc_buffer_add(target, 2); + return (ISC_R_SUCCESS); +} + +static inline int +compare_ch_a(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_a); + REQUIRE(rdata1->rdclass == dns_rdataclass_ch); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + order = memcmp(region1.base, region2.base, 2); + if (order != 0) + order = (order < 0) ? -1 : 1; + return (order); +} + +static inline isc_result_t +fromstruct_ch_a(ARGS_FROMSTRUCT) { + dns_rdata_ch_a_t *a = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(source != NULL); + REQUIRE(a->common.rdtype == type); + REQUIRE(a->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&a->ch_addr_dom, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + + return (uint16_tobuffer(ntohs(a->ch_addr), target)); +} + +static inline isc_result_t +tostruct_ch_a(ARGS_TOSTRUCT) { + dns_rdata_ch_a_t *a = target; + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_ch); + REQUIRE(rdata->length != 0); + + a->common.rdclass = rdata->rdclass; + a->common.rdtype = rdata->type; + ISC_LINK_INIT(&a->common, link); + + dns_rdata_toregion(rdata, ®ion); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + + dns_name_init(&a->ch_addr_dom, NULL); + RETERR(name_duporclone(&name, mctx, &a->ch_addr_dom)); + a->ch_addr = htons(uint16_fromregion(®ion)); + a->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_ch_a(ARGS_FREESTRUCT) { + dns_rdata_ch_a_t *a = source; + + REQUIRE(source != NULL); + REQUIRE(a->common.rdtype == dns_rdatatype_a); + + if (a->mctx == NULL) + return; + + dns_name_free(&a->ch_addr_dom, a->mctx); + a->mctx = NULL; +} + +static inline isc_result_t +additionaldata_ch_a(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_ch); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_ch_a(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_ch); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + isc_region_consume(&r, name_length(&name)); + RETERR(dns_name_digest(&name, digest, arg)); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_ch_a(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_ch); + + UNUSED(type); + + return (dns_name_ishostname(name, wildcard)); +} + +static inline bool +checknames_ch_a(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_ch); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + + return (true); +} + +static inline int +casecompare_ch_a(ARGS_COMPARE) { + return (compare_ch_a(rdata1, rdata2)); +} +#endif /* RDATA_CH_3_A_1_C */ diff --git a/lib/dns/rdata/ch_3/a_1.h b/lib/dns/rdata/ch_3/a_1.h new file mode 100644 index 0000000..a969534 --- /dev/null +++ b/lib/dns/rdata/ch_3/a_1.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* by Bjorn.Victor@it.uu.se, 2005-05-07 */ +/* Based on generic/mx_15.h */ + +#ifndef CH_3_A_1_H +#define CH_3_A_1_H 1 + +typedef uint16_t ch_addr_t; + +typedef struct dns_rdata_ch_a { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t ch_addr_dom; /* ch-addr domain for back mapping */ + ch_addr_t ch_addr; /* chaos address (16 bit) network order */ +} dns_rdata_ch_a_t; + +#endif /* CH_3_A_1_H */ diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c new file mode 100644 index 0000000..812dfa6 --- /dev/null +++ b/lib/dns/rdata/generic/afsdb_18.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1183 */ + +#ifndef RDATA_GENERIC_AFSDB_18_C +#define RDATA_GENERIC_AFSDB_18_C + +#define RRTYPE_AFSDB_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_afsdb(ARGS_FROMTEXT) { + isc_token_t token; + isc_buffer_t buffer; + dns_name_t name; + bool ok; + + REQUIRE(type == dns_rdatatype_afsdb); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Subtype. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Hostname. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_afsdb(ARGS_TOTEXT) { + dns_name_t name; + dns_name_t prefix; + isc_region_t region; + char buf[sizeof("64000 ")]; + bool sub; + unsigned int num; + + REQUIRE(rdata->type == dns_rdatatype_afsdb); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u ", num); + RETERR(str_totext(buf, target)); + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_afsdb(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sr; + isc_region_t tr; + + REQUIRE(type == dns_rdatatype_afsdb); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + isc_buffer_activeregion(source, &sr); + isc_buffer_availableregion(target, &tr); + if (tr.length < 2) + return (ISC_R_NOSPACE); + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + memmove(tr.base, sr.base, 2); + isc_buffer_forward(source, 2); + isc_buffer_add(target, 2); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_afsdb(ARGS_TOWIRE) { + isc_region_t tr; + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_afsdb); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + isc_buffer_availableregion(target, &tr); + dns_rdata_toregion(rdata, &sr); + if (tr.length < 2) + return (ISC_R_NOSPACE); + memmove(tr.base, sr.base, 2); + isc_region_consume(&sr, 2); + isc_buffer_add(target, 2); + + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_afsdb(ARGS_COMPARE) { + int result; + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_afsdb); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + result = memcmp(rdata1->data, rdata2->data, 2); + if (result != 0) + return (result < 0 ? -1 : 1); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 2); + isc_region_consume(®ion2, 2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_afsdb(ARGS_FROMSTRUCT) { + dns_rdata_afsdb_t *afsdb = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_afsdb); + REQUIRE(source != NULL); + REQUIRE(afsdb->common.rdclass == rdclass); + REQUIRE(afsdb->common.rdtype == type); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(afsdb->subtype, target)); + dns_name_toregion(&afsdb->server, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_afsdb(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_afsdb_t *afsdb = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_afsdb); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + afsdb->common.rdclass = rdata->rdclass; + afsdb->common.rdtype = rdata->type; + ISC_LINK_INIT(&afsdb->common, link); + + dns_name_init(&afsdb->server, NULL); + + dns_rdata_toregion(rdata, ®ion); + + afsdb->subtype = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + + RETERR(name_duporclone(&name, mctx, &afsdb->server)); + afsdb->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_afsdb(ARGS_FREESTRUCT) { + dns_rdata_afsdb_t *afsdb = source; + + REQUIRE(source != NULL); + REQUIRE(afsdb->common.rdtype == dns_rdatatype_afsdb); + + if (afsdb->mctx == NULL) + return; + + dns_name_free(&afsdb->server, afsdb->mctx); + afsdb->mctx = NULL; +} + +static inline isc_result_t +additionaldata_afsdb(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_afsdb); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_afsdb(ARGS_DIGEST) { + isc_region_t r1, r2; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_afsdb); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + isc_region_consume(&r2, 2); + r1.length = 2; + RETERR((digest)(arg, &r1)); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_afsdb(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_afsdb); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_afsdb(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_afsdb); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_afsdb(ARGS_COMPARE) { + return (compare_afsdb(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_AFSDB_18_C */ diff --git a/lib/dns/rdata/generic/afsdb_18.h b/lib/dns/rdata/generic/afsdb_18.h new file mode 100644 index 0000000..24da1aa --- /dev/null +++ b/lib/dns/rdata/generic/afsdb_18.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_AFSDB_18_H +#define GENERIC_AFSDB_18_H 1 + + +/*! + * \brief Per RFC1183 */ + +typedef struct dns_rdata_afsdb { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t subtype; + dns_name_t server; +} dns_rdata_afsdb_t; + +#endif /* GENERIC_AFSDB_18_H */ + diff --git a/lib/dns/rdata/generic/avc_258.c b/lib/dns/rdata/generic/avc_258.c new file mode 100644 index 0000000..31bbaff --- /dev/null +++ b/lib/dns/rdata/generic/avc_258.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_AVC_258_C +#define RDATA_GENERIC_AVC_258_C + +#define RRTYPE_AVC_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_avc(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_avc); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + return (generic_fromtext_txt(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_avc(ARGS_TOTEXT) { + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_avc); + + return (generic_totext_txt(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_avc(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_avc); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + return (generic_fromwire_txt(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_avc(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_avc); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_avc(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_avc); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_avc(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_avc); + + return (generic_fromstruct_txt(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_avc(ARGS_TOSTRUCT) { + dns_rdata_avc_t *avc = target; + + REQUIRE(rdata->type == dns_rdatatype_avc); + REQUIRE(target != NULL); + + avc->common.rdclass = rdata->rdclass; + avc->common.rdtype = rdata->type; + ISC_LINK_INIT(&avc->common, link); + + return (generic_tostruct_txt(rdata, target, mctx)); +} + +static inline void +freestruct_avc(ARGS_FREESTRUCT) { + dns_rdata_avc_t *txt = source; + + REQUIRE(source != NULL); + REQUIRE(txt->common.rdtype == dns_rdatatype_avc); + + generic_freestruct_txt(source); +} + +static inline isc_result_t +additionaldata_avc(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_avc); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_avc(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_avc); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_avc(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_avc); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_avc(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_avc); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_avc(ARGS_COMPARE) { + return (compare_avc(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_AVC_258_C */ diff --git a/lib/dns/rdata/generic/avc_258.h b/lib/dns/rdata/generic/avc_258.h new file mode 100644 index 0000000..88abadd --- /dev/null +++ b/lib/dns/rdata/generic/avc_258.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_AVC_258_H +#define GENERIC_AVC_258_H 1 + +typedef dns_rdata_txt_string_t dns_rdata_avc_string_t; + +typedef struct dns_rdata_avc { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *data; + uint16_t length; + /* private */ + uint16_t offset; +} dns_rdata_avc_t; + +/* + * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done + * via rdatastructpre.h and rdatastructsuf.h. + */ +#endif /* GENERIC_AVC_258_H */ diff --git a/lib/dns/rdata/generic/caa_257.c b/lib/dns/rdata/generic/caa_257.c new file mode 100644 index 0000000..4dc3639 --- /dev/null +++ b/lib/dns/rdata/generic/caa_257.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_CAA_257_C +#define GENERIC_CAA_257_C 1 + +#define RRTYPE_CAA_ATTRIBUTES (0) + +static unsigned char const alphanumeric[256] = { + /* 0x00-0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10-0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x20-0x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x30-0x3f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + /* 0x40-0x4f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x50-0x5f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + /* 0x60-0x6f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x70-0x7f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + /* 0x80-0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x90-0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xa0-0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xb0-0xbf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xc0-0xcf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xd0-0xdf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xe0-0xef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xf0-0xff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static inline isc_result_t +fromtext_caa(ARGS_FROMTEXT) { + isc_token_t token; + isc_textregion_t tr; + uint8_t flags; + unsigned int i; + + REQUIRE(type == dns_rdatatype_caa); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* Flags. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 255U) + RETTOK(ISC_R_RANGE); + flags = (uint8_t)(token.value.as_ulong & 255U); + RETERR(uint8_tobuffer(flags, target)); + + /* + * Tag + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + tr = token.value.as_textregion; + for (i = 0; i < tr.length; i++) + if (!alphanumeric[(unsigned char) tr.base[i]]) + RETTOK(DNS_R_SYNTAX); + RETERR(uint8_tobuffer(tr.length, target)); + RETERR(mem_tobuffer(target, tr.base, tr.length)); + + /* + * Value + */ + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qstring, false)); + if (token.type != isc_tokentype_qstring && + token.type != isc_tokentype_string) + RETERR(DNS_R_SYNTAX); + RETERR(multitxt_fromtext(&token.value.as_textregion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_caa(ARGS_TOTEXT) { + isc_region_t region; + uint8_t flags; + char buf[256]; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_caa); + REQUIRE(rdata->length >= 3U); + REQUIRE(rdata->data != NULL); + + dns_rdata_toregion(rdata, ®ion); + + /* + * Flags + */ + flags = uint8_consume_fromregion(®ion); + snprintf(buf, sizeof(buf), "%u ", flags); + RETERR(str_totext(buf, target)); + + /* + * Tag + */ + RETERR(txt_totext(®ion, false, target)); + RETERR(str_totext(" ", target)); + + /* + * Value + */ + RETERR(multitxt_totext(®ion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_caa(ARGS_FROMWIRE) { + isc_region_t sr; + unsigned int len, i; + + REQUIRE(type == dns_rdatatype_caa); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + /* + * Flags + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + + /* + * Flags, tag length + */ + RETERR(mem_tobuffer(target, sr.base, 2)); + len = sr.base[1]; + isc_region_consume(&sr, 2); + isc_buffer_forward(source, 2); + + /* + * Zero length tag fields are illegal. + */ + if (sr.length < len || len == 0) + RETERR(DNS_R_FORMERR); + + /* Check the Tag's value */ + for (i = 0; i < len; i++) + if (!alphanumeric[sr.base[i]]) + RETERR(DNS_R_FORMERR); + /* + * Tag + Value + */ + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_caa(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_caa); + REQUIRE(rdata->length >= 3U); + REQUIRE(rdata->data != NULL); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_caa(ARGS_COMPARE) { + isc_region_t r1, r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_caa); + REQUIRE(rdata1->length >= 3U); + REQUIRE(rdata2->length >= 3U); + REQUIRE(rdata1->data != NULL); + REQUIRE(rdata2->data != NULL); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_caa(ARGS_FROMSTRUCT) { + dns_rdata_caa_t *caa = source; + isc_region_t region; + unsigned int i; + + REQUIRE(type == dns_rdatatype_caa); + REQUIRE(source != NULL); + REQUIRE(caa->common.rdtype == type); + REQUIRE(caa->common.rdclass == rdclass); + REQUIRE(caa->tag != NULL && caa->tag_len != 0); + REQUIRE(caa->value != NULL); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Flags + */ + RETERR(uint8_tobuffer(caa->flags, target)); + + /* + * Tag length + */ + RETERR(uint8_tobuffer(caa->tag_len, target)); + + /* + * Tag + */ + region.base = caa->tag; + region.length = caa->tag_len; + for (i = 0; i < region.length; i++) + if (!alphanumeric[region.base[i]]) + RETERR(DNS_R_SYNTAX); + RETERR(isc_buffer_copyregion(target, ®ion)); + + /* + * Value + */ + region.base = caa->value; + region.length = caa->value_len; + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_caa(ARGS_TOSTRUCT) { + dns_rdata_caa_t *caa = target; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_caa); + REQUIRE(target != NULL); + REQUIRE(rdata->length >= 3U); + REQUIRE(rdata->data != NULL); + + caa->common.rdclass = rdata->rdclass; + caa->common.rdtype = rdata->type; + ISC_LINK_INIT(&caa->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Flags + */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + caa->flags = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Tag length + */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + caa->tag_len = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Tag + */ + if (sr.length < caa->tag_len) + return (ISC_R_UNEXPECTEDEND); + caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len); + if (caa->tag == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(&sr, caa->tag_len); + + /* + * Value + */ + caa->value_len = sr.length; + caa->value = mem_maybedup(mctx, sr.base, sr.length); + if (caa->value == NULL) + return (ISC_R_NOMEMORY); + + caa->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_caa(ARGS_FREESTRUCT) { + dns_rdata_caa_t *caa = (dns_rdata_caa_t *) source; + + REQUIRE(source != NULL); + REQUIRE(caa->common.rdtype == dns_rdatatype_caa); + + if (caa->mctx == NULL) + return; + + if (caa->tag != NULL) + isc_mem_free(caa->mctx, caa->tag); + if (caa->value != NULL) + isc_mem_free(caa->mctx, caa->value); + caa->mctx = NULL; +} + +static inline isc_result_t +additionaldata_caa(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_caa); + REQUIRE(rdata->data != NULL); + REQUIRE(rdata->length >= 3U); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_caa(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_caa); + REQUIRE(rdata->data != NULL); + REQUIRE(rdata->length >= 3U); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_caa(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_caa); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_caa(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_caa); + REQUIRE(rdata->data != NULL); + REQUIRE(rdata->length >= 3U); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_caa(ARGS_COMPARE) { + return (compare_caa(rdata1, rdata2)); +} + +#endif /* GENERIC_CAA_257_C */ diff --git a/lib/dns/rdata/generic/caa_257.h b/lib/dns/rdata/generic/caa_257.h new file mode 100644 index 0000000..c16e427 --- /dev/null +++ b/lib/dns/rdata/generic/caa_257.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_CAA_257_H +#define GENERIC_CAA_257_H 1 + + +typedef struct dns_rdata_caa { + dns_rdatacommon_t common; + isc_mem_t * mctx; + uint8_t flags; + unsigned char * tag; + uint8_t tag_len; + unsigned char *value; + uint16_t value_len; +} dns_rdata_caa_t; + +#endif /* GENERIC_CAA_257_H */ diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c new file mode 100644 index 0000000..afcdbc2 --- /dev/null +++ b/lib/dns/rdata/generic/cdnskey_60.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* draft-ietf-dnsop-delegation-trust-maintainance-14 */ + +#ifndef RDATA_GENERIC_CDNSKEY_60_C +#define RDATA_GENERIC_CDNSKEY_60_C + +#include <dst/dst.h> + +#define RRTYPE_CDNSKEY_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_cdnskey(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_cdnskey); + + return (generic_fromtext_key(rdclass, type, lexer, origin, + options, target, callbacks)); +} + +static inline isc_result_t +totext_cdnskey(ARGS_TOTEXT) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_cdnskey); + + return (generic_totext_key(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_cdnskey(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_cdnskey); + + return (generic_fromwire_key(rdclass, type, source, dctx, + options, target)); +} + +static inline isc_result_t +towire_cdnskey(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_cdnskey); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_cdnskey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_cdnskey); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_cdnskey(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_cdnskey); + + return (generic_fromstruct_key(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_cdnskey(ARGS_TOSTRUCT) { + dns_rdata_cdnskey_t *dnskey = target; + + REQUIRE(dnskey != NULL); + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_cdnskey); + + dnskey->common.rdclass = rdata->rdclass; + dnskey->common.rdtype = rdata->type; + ISC_LINK_INIT(&dnskey->common, link); + + return (generic_tostruct_key(rdata, target, mctx)); +} + +static inline void +freestruct_cdnskey(ARGS_FREESTRUCT) { + dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *) source; + + REQUIRE(dnskey != NULL); + REQUIRE(dnskey->common.rdtype == dns_rdatatype_cdnskey); + + generic_freestruct_key(source); +} + +static inline isc_result_t +additionaldata_cdnskey(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_cdnskey); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_cdnskey(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_cdnskey); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_cdnskey(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_cdnskey); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_cdnskey(ARGS_CHECKNAMES) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_cdnskey); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_cdnskey(ARGS_COMPARE) { + + /* + * Treat ALG 253 (private DNS) subtype name case sensistively. + */ + return (compare_cdnskey(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_CDNSKEY_60_C */ diff --git a/lib/dns/rdata/generic/cdnskey_60.h b/lib/dns/rdata/generic/cdnskey_60.h new file mode 100644 index 0000000..541a4c2 --- /dev/null +++ b/lib/dns/rdata/generic/cdnskey_60.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_CDNSKEY_60_H +#define GENERIC_CDNSKEY_60_H 1 + +/* CDNSKEY records have the same RDATA fields as DNSKEY records. */ +typedef struct dns_rdata_key dns_rdata_cdnskey_t; + +#endif /* GENERIC_CDNSKEY_60_H */ diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c new file mode 100644 index 0000000..e1ea7ce --- /dev/null +++ b/lib/dns/rdata/generic/cds_59.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* draft-ietf-dnsop-delegation-trust-maintainance-14 */ + +#ifndef RDATA_GENERIC_CDS_59_C +#define RDATA_GENERIC_CDS_59_C + +#define RRTYPE_CDS_ATTRIBUTES 0 + +#include <isc/sha1.h> +#include <isc/sha2.h> + +#include <dns/ds.h> + +#include "dst_gost.h" + +static inline isc_result_t +fromtext_cds(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_cds); + + return (generic_fromtext_ds(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_cds(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_cds); + + return (generic_totext_ds(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_cds(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_cds); + + return (generic_fromwire_ds(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_cds(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_cds); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_cds(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_cds); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_cds(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_cds); + + return (generic_fromstruct_ds(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_cds(ARGS_TOSTRUCT) { + dns_rdata_cds_t *cds = target; + + REQUIRE(rdata->type == dns_rdatatype_cds); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + /* + * Checked by generic_tostruct_ds(). + */ + cds->common.rdclass = rdata->rdclass; + cds->common.rdtype = rdata->type; + ISC_LINK_INIT(&cds->common, link); + + return (generic_tostruct_ds(rdata, target, mctx)); +} + +static inline void +freestruct_cds(ARGS_FREESTRUCT) { + dns_rdata_cds_t *ds = source; + + REQUIRE(ds != NULL); + REQUIRE(ds->common.rdtype == dns_rdatatype_cds); + + if (ds->mctx == NULL) + return; + + if (ds->digest != NULL) + isc_mem_free(ds->mctx, ds->digest); + ds->mctx = NULL; +} + +static inline isc_result_t +additionaldata_cds(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_cds); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_cds(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_cds); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_cds(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_cds); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_cds(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_cds); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_cds(ARGS_COMPARE) { + return (compare_cds(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_CDS_59_C */ diff --git a/lib/dns/rdata/generic/cds_59.h b/lib/dns/rdata/generic/cds_59.h new file mode 100644 index 0000000..0797bca --- /dev/null +++ b/lib/dns/rdata/generic/cds_59.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_CDS_59_H +#define GENERIC_CDS_59_H 1 + +/* CDS records have the same RDATA fields as DS records. */ +typedef struct dns_rdata_ds dns_rdata_cds_t; + +#endif /* GENERIC_CDS_59_H */ diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c new file mode 100644 index 0000000..237a806 --- /dev/null +++ b/lib/dns/rdata/generic/cert_37.c @@ -0,0 +1,277 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2538 */ + +#ifndef RDATA_GENERIC_CERT_37_C +#define RDATA_GENERIC_CERT_37_C + +#define RRTYPE_CERT_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_cert(ARGS_FROMTEXT) { + isc_token_t token; + dns_secalg_t secalg; + dns_cert_t cert; + + REQUIRE(type == dns_rdatatype_cert); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * Cert type. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_cert_fromtext(&cert, &token.value.as_textregion)); + RETERR(uint16_tobuffer(cert, target)); + + /* + * Key tag. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secalg_fromtext(&secalg, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &secalg, 1)); + + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_cert(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000 ")]; + unsigned int n; + + REQUIRE(rdata->type == dns_rdatatype_cert); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + /* + * Type. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + RETERR(dns_cert_totext((dns_cert_t)n, target)); + RETERR(str_totext(" ", target)); + + /* + * Key tag. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Algorithm. + */ + RETERR(dns_secalg_totext(sr.base[0], target)); + isc_region_consume(&sr, 1); + + /* + * Cert. + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_cert(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_cert); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 5) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_cert(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_cert); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_cert(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_cert); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_cert(ARGS_FROMSTRUCT) { + dns_rdata_cert_t *cert = source; + + REQUIRE(type == dns_rdatatype_cert); + REQUIRE(source != NULL); + REQUIRE(cert->common.rdtype == type); + REQUIRE(cert->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(cert->type, target)); + RETERR(uint16_tobuffer(cert->key_tag, target)); + RETERR(uint8_tobuffer(cert->algorithm, target)); + + return (mem_tobuffer(target, cert->certificate, cert->length)); +} + +static inline isc_result_t +tostruct_cert(ARGS_TOSTRUCT) { + dns_rdata_cert_t *cert = target; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_cert); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + cert->common.rdclass = rdata->rdclass; + cert->common.rdtype = rdata->type; + ISC_LINK_INIT(&cert->common, link); + + dns_rdata_toregion(rdata, ®ion); + + cert->type = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + cert->key_tag = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + cert->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + cert->length = region.length; + + cert->certificate = mem_maybedup(mctx, region.base, region.length); + if (cert->certificate == NULL) + return (ISC_R_NOMEMORY); + + cert->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_cert(ARGS_FREESTRUCT) { + dns_rdata_cert_t *cert = source; + + REQUIRE(cert != NULL); + REQUIRE(cert->common.rdtype == dns_rdatatype_cert); + + if (cert->mctx == NULL) + return; + + if (cert->certificate != NULL) + isc_mem_free(cert->mctx, cert->certificate); + cert->mctx = NULL; +} + +static inline isc_result_t +additionaldata_cert(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_cert); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_cert(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_cert); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_cert(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_cert); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_cert(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_cert); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + + +static inline int +casecompare_cert(ARGS_COMPARE) { + return (compare_cert(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_CERT_37_C */ diff --git a/lib/dns/rdata/generic/cert_37.h b/lib/dns/rdata/generic/cert_37.h new file mode 100644 index 0000000..db760e1 --- /dev/null +++ b/lib/dns/rdata/generic/cert_37.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_CERT_37_H +#define GENERIC_CERT_37_H 1 + +/*% RFC2538 */ +typedef struct dns_rdata_cert { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t type; + uint16_t key_tag; + uint8_t algorithm; + uint16_t length; + unsigned char *certificate; +} dns_rdata_cert_t; + +#endif /* GENERIC_CERT_37_H */ diff --git a/lib/dns/rdata/generic/cname_5.c b/lib/dns/rdata/generic/cname_5.c new file mode 100644 index 0000000..3da82eb --- /dev/null +++ b/lib/dns/rdata/generic/cname_5.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_CNAME_5_C +#define RDATA_GENERIC_CNAME_5_C + +#define RRTYPE_CNAME_ATTRIBUTES \ + (DNS_RDATATYPEATTR_EXCLUSIVE | DNS_RDATATYPEATTR_SINGLETON) + +static inline isc_result_t +fromtext_cname(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_cname); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_cname(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_cname); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_cname(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_cname); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_cname(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_cname); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_cname(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_cname); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_cname(ARGS_FROMSTRUCT) { + dns_rdata_cname_t *cname = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_cname); + REQUIRE(source != NULL); + REQUIRE(cname->common.rdtype == type); + REQUIRE(cname->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&cname->cname, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_cname(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_cname_t *cname = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_cname); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + cname->common.rdclass = rdata->rdclass; + cname->common.rdtype = rdata->type; + ISC_LINK_INIT(&cname->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&cname->cname, NULL); + RETERR(name_duporclone(&name, mctx, &cname->cname)); + cname->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_cname(ARGS_FREESTRUCT) { + dns_rdata_cname_t *cname = source; + + REQUIRE(source != NULL); + + if (cname->mctx == NULL) + return; + + dns_name_free(&cname->cname, cname->mctx); + cname->mctx = NULL; +} + +static inline isc_result_t +additionaldata_cname(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_cname); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_cname(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_cname); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_cname(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_cname); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_cname(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_cname); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_cname(ARGS_COMPARE) { + return (compare_cname(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_CNAME_5_C */ diff --git a/lib/dns/rdata/generic/cname_5.h b/lib/dns/rdata/generic/cname_5.h new file mode 100644 index 0000000..6a5b645 --- /dev/null +++ b/lib/dns/rdata/generic/cname_5.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_CNAME_5_H +#define GENERIC_CNAME_5_H 1 + +typedef struct dns_rdata_cname { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t cname; +} dns_rdata_cname_t; + +#endif /* GENERIC_CNAME_5_H */ diff --git a/lib/dns/rdata/generic/csync_62.c b/lib/dns/rdata/generic/csync_62.c new file mode 100644 index 0000000..c639128 --- /dev/null +++ b/lib/dns/rdata/generic/csync_62.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC 7477 */ + +#ifndef RDATA_GENERIC_CSYNC_62_C +#define RDATA_GENERIC_CSYNC_62_C + +#define RRTYPE_CSYNC_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_csync(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_csync); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* Serial. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* Flags. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* Type Map */ + return (typemap_fromtext(lexer, target, true)); +} + +static inline isc_result_t +totext_csync(ARGS_TOTEXT) { + unsigned long num; + char buf[sizeof("0123456789")]; /* Also TYPE65535 */ + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_csync); + REQUIRE(rdata->length >= 6); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + num = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + snprintf(buf, sizeof(buf), "%lu", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + num = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%lu", num); + RETERR(str_totext(buf, target)); + + /* + * Don't leave a trailing space when there's no typemap present. + */ + if (sr.length > 0) { + RETERR(str_totext(" ", target)); + } + return (typemap_totext(&sr, NULL, target)); +} + +static /* inline */ isc_result_t +fromwire_csync(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_csync); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(options); + UNUSED(dctx); + + /* + * Serial + Flags + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 6) + return (ISC_R_UNEXPECTEDEND); + + RETERR(mem_tobuffer(target, sr.base, 6)); + isc_buffer_forward(source, 6); + isc_region_consume(&sr, 6); + + RETERR(typemap_test(&sr, true)); + + RETERR(mem_tobuffer(target, sr.base, sr.length)); + isc_buffer_forward(source, sr.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_csync(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_csync); + REQUIRE(rdata->length >= 6); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_csync(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_csync); + REQUIRE(rdata1->length >= 6); + REQUIRE(rdata2->length >= 6); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_csync(ARGS_FROMSTRUCT) { + dns_rdata_csync_t *csync = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_csync); + REQUIRE(source != NULL); + REQUIRE(csync->common.rdtype == type); + REQUIRE(csync->common.rdclass == rdclass); + REQUIRE(csync->typebits != NULL || csync->len == 0); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint32_tobuffer(csync->serial, target)); + RETERR(uint16_tobuffer(csync->flags, target)); + + region.base = csync->typebits; + region.length = csync->len; + RETERR(typemap_test(®ion, true)); + return (mem_tobuffer(target, csync->typebits, csync->len)); +} + +static inline isc_result_t +tostruct_csync(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_csync_t *csync = target; + + REQUIRE(rdata->type == dns_rdatatype_csync); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + csync->common.rdclass = rdata->rdclass; + csync->common.rdtype = rdata->type; + ISC_LINK_INIT(&csync->common, link); + + dns_rdata_toregion(rdata, ®ion); + + csync->serial = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + csync->flags = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + csync->len = region.length; + csync->typebits = mem_maybedup(mctx, region.base, region.length); + if (csync->typebits == NULL) + goto cleanup; + + csync->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_csync(ARGS_FREESTRUCT) { + dns_rdata_csync_t *csync = source; + + REQUIRE(source != NULL); + REQUIRE(csync->common.rdtype == dns_rdatatype_csync); + + if (csync->mctx == NULL) + return; + + if (csync->typebits != NULL) + isc_mem_free(csync->mctx, csync->typebits); + csync->mctx = NULL; +} + +static inline isc_result_t +additionaldata_csync(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_csync); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_csync(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_csync); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_csync(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_csync); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_csync(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_csync); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_csync(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_csync); + REQUIRE(rdata1->length >= 6); + REQUIRE(rdata2->length >= 6); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} +#endif /* RDATA_GENERIC_CSYNC_62_C */ diff --git a/lib/dns/rdata/generic/csync_62.h b/lib/dns/rdata/generic/csync_62.h new file mode 100644 index 0000000..a1f63d5 --- /dev/null +++ b/lib/dns/rdata/generic/csync_62.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_CSYNC_62_H +#define GENERIC_CSYNC_62_H 1 + +/*! + * \brief Per RFC 7477 + */ + +typedef struct dns_rdata_csync { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint32_t serial; + uint16_t flags; + unsigned char *typebits; + uint16_t len; +} dns_rdata_csync_t; + +#endif /* GENERIC_CSYNC_62_H */ diff --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c new file mode 100644 index 0000000..0f05ba8 --- /dev/null +++ b/lib/dns/rdata/generic/dlv_32769.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC3658 */ + +#ifndef RDATA_GENERIC_DLV_32769_C +#define RDATA_GENERIC_DLV_32769_C + +#define RRTYPE_DLV_ATTRIBUTES 0 + +#include <isc/sha1.h> +#include <isc/sha2.h> + +#include <dns/ds.h> + +#include "dst_gost.h" + +static inline isc_result_t +fromtext_dlv(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_dlv); + + return (generic_fromtext_ds(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_dlv(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_dlv); + + return (generic_totext_ds(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_dlv(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_dlv); + + return (generic_fromwire_ds(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_dlv(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_dlv); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_dlv(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_dlv); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_dlv(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_dlv); + + return (generic_fromstruct_ds(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_dlv(ARGS_TOSTRUCT) { + dns_rdata_dlv_t *dlv = target; + + REQUIRE(rdata->type == dns_rdatatype_dlv); + + dlv->common.rdclass = rdata->rdclass; + dlv->common.rdtype = rdata->type; + ISC_LINK_INIT(&dlv->common, link); + + return (generic_tostruct_ds(rdata, target, mctx)); +} + +static inline void +freestruct_dlv(ARGS_FREESTRUCT) { + dns_rdata_dlv_t *dlv = source; + + REQUIRE(dlv != NULL); + REQUIRE(dlv->common.rdtype == dns_rdatatype_dlv); + + if (dlv->mctx == NULL) + return; + + if (dlv->digest != NULL) + isc_mem_free(dlv->mctx, dlv->digest); + dlv->mctx = NULL; +} + +static inline isc_result_t +additionaldata_dlv(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_dlv); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_dlv(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_dlv); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_dlv(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_dlv); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_dlv(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_dlv); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_dlv(ARGS_COMPARE) { + return (compare_dlv(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_DLV_32769_C */ diff --git a/lib/dns/rdata/generic/dlv_32769.h b/lib/dns/rdata/generic/dlv_32769.h new file mode 100644 index 0000000..b94df71 --- /dev/null +++ b/lib/dns/rdata/generic/dlv_32769.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* draft-ietf-dnsext-delegation-signer-05.txt */ +#ifndef GENERIC_DLV_32769_H +#define GENERIC_DLV_32769_H 1 + +typedef struct dns_rdata_ds dns_rdata_dlv_t; + +#endif /* GENERIC_DLV_32769_H */ diff --git a/lib/dns/rdata/generic/dname_39.c b/lib/dns/rdata/generic/dname_39.c new file mode 100644 index 0000000..50c5838 --- /dev/null +++ b/lib/dns/rdata/generic/dname_39.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2672 */ + +#ifndef RDATA_GENERIC_DNAME_39_C +#define RDATA_GENERIC_DNAME_39_C + +#define RRTYPE_DNAME_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON) + +static inline isc_result_t +fromtext_dname(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_dname); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_dname(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_dname); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_dname(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_dname); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + return(dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_dname(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_dname); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_dname(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_dname); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_dname(ARGS_FROMSTRUCT) { + dns_rdata_dname_t *dname = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_dname); + REQUIRE(source != NULL); + REQUIRE(dname->common.rdtype == type); + REQUIRE(dname->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&dname->dname, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_dname(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_dname_t *dname = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_dname); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + dname->common.rdclass = rdata->rdclass; + dname->common.rdtype = rdata->type; + ISC_LINK_INIT(&dname->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&dname->dname, NULL); + RETERR(name_duporclone(&name, mctx, &dname->dname)); + dname->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_dname(ARGS_FREESTRUCT) { + dns_rdata_dname_t *dname = source; + + REQUIRE(source != NULL); + REQUIRE(dname->common.rdtype == dns_rdatatype_dname); + + if (dname->mctx == NULL) + return; + + dns_name_free(&dname->dname, dname->mctx); + dname->mctx = NULL; +} + +static inline isc_result_t +additionaldata_dname(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_dname); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_dname(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_dname); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_dname(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_dname); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_dname(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_dname); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_dname(ARGS_COMPARE) { + return (compare_dname(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_DNAME_39_C */ diff --git a/lib/dns/rdata/generic/dname_39.h b/lib/dns/rdata/generic/dname_39.h new file mode 100644 index 0000000..12b02e2 --- /dev/null +++ b/lib/dns/rdata/generic/dname_39.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_DNAME_39_H +#define GENERIC_DNAME_39_H 1 + + +/*! + * \brief per RFC2672 */ + +typedef struct dns_rdata_dname { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t dname; +} dns_rdata_dname_t; + +#endif /* GENERIC_DNAME_39_H */ diff --git a/lib/dns/rdata/generic/dnskey_48.c b/lib/dns/rdata/generic/dnskey_48.c new file mode 100644 index 0000000..f20a8f6 --- /dev/null +++ b/lib/dns/rdata/generic/dnskey_48.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_DNSKEY_48_C +#define RDATA_GENERIC_DNSKEY_48_C + +#include <dst/dst.h> + +#define RRTYPE_DNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) + +static inline isc_result_t +fromtext_dnskey(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_dnskey); + + return (generic_fromtext_key(rdclass, type, lexer, origin, + options, target, callbacks)); +} + +static inline isc_result_t +totext_dnskey(ARGS_TOTEXT) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_dnskey); + + return (generic_totext_key(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_dnskey(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_dnskey); + + return (generic_fromwire_key(rdclass, type, source, dctx, + options, target)); +} + +static inline isc_result_t +towire_dnskey(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_dnskey); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_dnskey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_dnskey); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_dnskey(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_dnskey); + + return (generic_fromstruct_key(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_dnskey(ARGS_TOSTRUCT) { + dns_rdata_dnskey_t *dnskey = target; + + REQUIRE(dnskey != NULL); + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_dnskey); + + dnskey->common.rdclass = rdata->rdclass; + dnskey->common.rdtype = rdata->type; + ISC_LINK_INIT(&dnskey->common, link); + + return (generic_tostruct_key(rdata, target, mctx)); +} + +static inline void +freestruct_dnskey(ARGS_FREESTRUCT) { + dns_rdata_dnskey_t *dnskey = (dns_rdata_dnskey_t *) source; + + REQUIRE(dnskey != NULL); + REQUIRE(dnskey->common.rdtype == dns_rdatatype_dnskey); + + generic_freestruct_key(source); +} + +static inline isc_result_t +additionaldata_dnskey(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_dnskey); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_dnskey(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_dnskey); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_dnskey(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_dnskey); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_dnskey(ARGS_CHECKNAMES) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_dnskey); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_dnskey(ARGS_COMPARE) { + + /* + * Treat ALG 253 (private DNS) subtype name case sensistively. + */ + return (compare_dnskey(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_DNSKEY_48_C */ diff --git a/lib/dns/rdata/generic/dnskey_48.h b/lib/dns/rdata/generic/dnskey_48.h new file mode 100644 index 0000000..ac4a6de --- /dev/null +++ b/lib/dns/rdata/generic/dnskey_48.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_DNSKEY_48_H +#define GENERIC_DNSKEY_48_H 1 + +/*! + * \brief per RFC2535 + */ + +typedef struct dns_rdata_key dns_rdata_dnskey_t; + +#endif /* GENERIC_DNSKEY_48_H */ diff --git a/lib/dns/rdata/generic/doa_259.c b/lib/dns/rdata/generic/doa_259.c new file mode 100644 index 0000000..16c0703 --- /dev/null +++ b/lib/dns/rdata/generic/doa_259.c @@ -0,0 +1,358 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_DOA_259_C +#define RDATA_GENERIC_DOA_259_C + +#define RRTYPE_DOA_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_doa(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_doa); + + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * DOA-ENTERPRISE + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* + * DOA-TYPE + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* + * DOA-LOCATION + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) { + RETTOK(ISC_R_RANGE); + } + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * DOA-MEDIA-TYPE + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + + /* + * DOA-DATA + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcmp(DNS_AS_STR(token), "-") == 0) { + return (ISC_R_SUCCESS); + } else { + isc_lex_ungettoken(lexer, &token); + return (isc_base64_tobuffer(lexer, target, -1)); + } +} + +static inline isc_result_t +totext_doa(ARGS_TOTEXT) { + char buf[sizeof("4294967295 ")]; + isc_region_t region; + uint32_t n; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_doa); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + + /* + * DOA-ENTERPRISE + */ + n = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * DOA-TYPE + */ + n = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * DOA-LOCATION + */ + n = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * DOA-MEDIA-TYPE + */ + RETERR(txt_totext(®ion, true, target)); + RETERR(str_totext(" ", target)); + + /* + * DOA-DATA + */ + if (region.length == 0) { + return (str_totext("-", target)); + } else { + return (isc_base64_totext(®ion, 60, "", target)); + } +} + +static inline isc_result_t +fromwire_doa(ARGS_FROMWIRE) { + isc_region_t region; + + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + REQUIRE(type == dns_rdatatype_doa); + + isc_buffer_activeregion(source, ®ion); + /* + * DOA-MEDIA-TYPE may be an empty <character-string> (i.e., + * comprising of just the length octet) and DOA-DATA can have + * zero length. + */ + if (region.length < 4 + 4 + 1 + 1) { + return (ISC_R_UNEXPECTEDEND); + } + + /* + * Check whether DOA-MEDIA-TYPE length is not malformed. + */ + if (region.base[9] > region.length - 10) { + return (ISC_R_UNEXPECTEDEND); + } + + isc_buffer_forward(source, region.length); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline isc_result_t +towire_doa(ARGS_TOWIRE) { + isc_region_t region; + + UNUSED(cctx); + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_doa); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_doa(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->type == dns_rdatatype_doa); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_doa(ARGS_FROMSTRUCT) { + dns_rdata_doa_t *doa = source; + + REQUIRE(type == dns_rdatatype_doa); + REQUIRE(source != NULL); + REQUIRE(doa->common.rdtype == dns_rdatatype_doa); + REQUIRE(doa->common.rdclass == rdclass); + + RETERR(uint32_tobuffer(doa->enterprise, target)); + RETERR(uint32_tobuffer(doa->type, target)); + RETERR(uint8_tobuffer(doa->location, target)); + RETERR(uint8_tobuffer(doa->mediatype_len, target)); + RETERR(mem_tobuffer(target, doa->mediatype, doa->mediatype_len)); + return (mem_tobuffer(target, doa->data, doa->data_len)); +} + +static inline isc_result_t +tostruct_doa(ARGS_TOSTRUCT) { + dns_rdata_doa_t *doa = target; + isc_region_t region; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_doa); + REQUIRE(rdata->length != 0); + + doa->common.rdclass = rdata->rdclass; + doa->common.rdtype = rdata->type; + ISC_LINK_INIT(&doa->common, link); + + dns_rdata_toregion(rdata, ®ion); + + /* + * DOA-ENTERPRISE + */ + if (region.length < 4) { + return (ISC_R_UNEXPECTEDEND); + } + doa->enterprise = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + /* + * DOA-TYPE + */ + if (region.length < 4) { + return (ISC_R_UNEXPECTEDEND); + } + doa->type = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + /* + * DOA-LOCATION + */ + if (region.length < 1) { + return (ISC_R_UNEXPECTEDEND); + } + doa->location = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + /* + * DOA-MEDIA-TYPE + */ + if (region.length < 1) { + return (ISC_R_UNEXPECTEDEND); + } + doa->mediatype_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + INSIST(doa->mediatype_len <= region.length); + doa->mediatype = mem_maybedup(mctx, region.base, doa->mediatype_len); + if (doa->mediatype == NULL) { + goto cleanup; + } + isc_region_consume(®ion, doa->mediatype_len); + + /* + * DOA-DATA + */ + doa->data_len = region.length; + doa->data = NULL; + if (doa->data_len > 0) { + doa->data = mem_maybedup(mctx, region.base, doa->data_len); + if (doa->data == NULL) { + goto cleanup; + } + isc_region_consume(®ion, doa->data_len); + } + + doa->mctx = mctx; + + return (ISC_R_SUCCESS); + +cleanup: + if (mctx != NULL && doa->mediatype != NULL) { + isc_mem_free(mctx, doa->mediatype); + } + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_doa(ARGS_FREESTRUCT) { + dns_rdata_doa_t *doa = source; + + REQUIRE(source != NULL); + REQUIRE(doa->common.rdtype == dns_rdatatype_doa); + + if (doa->mctx == NULL) { + return; + } + + if (doa->mediatype != NULL) { + isc_mem_free(doa->mctx, doa->mediatype); + } + if (doa->data != NULL) { + isc_mem_free(doa->mctx, doa->data); + } + + doa->mctx = NULL; +} + +static inline isc_result_t +additionaldata_doa(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_doa); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_doa(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_doa); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_doa(ARGS_CHECKOWNER) { + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + REQUIRE(type == dns_rdatatype_doa); + + return (true); +} + +static inline bool +checknames_doa(ARGS_CHECKNAMES) { + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + REQUIRE(rdata->type == dns_rdatatype_doa); + + return (true); +} + +static inline int +casecompare_doa(ARGS_COMPARE) { + return (compare_doa(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_DOA_259_C */ diff --git a/lib/dns/rdata/generic/doa_259.h b/lib/dns/rdata/generic/doa_259.h new file mode 100644 index 0000000..5ac5fbb --- /dev/null +++ b/lib/dns/rdata/generic/doa_259.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_DOA_259_H +#define GENERIC_DOA_259_H 1 + +typedef struct dns_rdata_doa { + dns_rdatacommon_t common; + isc_mem_t * mctx; + unsigned char * mediatype; + unsigned char * data; + uint32_t enterprise; + uint32_t type; + uint16_t data_len; + uint8_t location; + uint8_t mediatype_len; +} dns_rdata_doa_t; + +#endif /* GENERIC_DOA_259_H */ diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c new file mode 100644 index 0000000..d25c1a6 --- /dev/null +++ b/lib/dns/rdata/generic/ds_43.c @@ -0,0 +1,400 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC3658 */ + +#ifndef RDATA_GENERIC_DS_43_C +#define RDATA_GENERIC_DS_43_C + +#define RRTYPE_DS_ATTRIBUTES \ + (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT) + +#include <isc/sha1.h> +#include <isc/sha2.h> + +#include <dns/ds.h> + +#include "dst_gost.h" + +static inline isc_result_t +generic_fromtext_ds(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char c; + int length; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * Key tag. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Digest type. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_dsdigest_fromtext(&c, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Digest. + */ + switch (c) { + case DNS_DSDIGEST_SHA1: + length = ISC_SHA1_DIGESTLENGTH; + break; + case DNS_DSDIGEST_SHA256: + length = ISC_SHA256_DIGESTLENGTH; + break; +#ifdef ISC_GOST_DIGESTLENGTH + case DNS_DSDIGEST_GOST: + length = ISC_GOST_DIGESTLENGTH; + break; +#endif + case DNS_DSDIGEST_SHA384: + length = ISC_SHA384_DIGESTLENGTH; + break; + default: + length = -1; + break; + } + return (isc_hex_tobuffer(lexer, target, length)); +} + +static inline isc_result_t +fromtext_ds(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_ds); + + return (generic_fromtext_ds(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +generic_totext_ds(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000 ")]; + unsigned int n; + + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + /* + * Key tag. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Algorithm. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Digest type. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u", n); + RETERR(str_totext(buf, target)); + + /* + * Digest. + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + } else + RETERR(str_totext("[omitted]", target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_ds(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_ds); + + return (generic_totext_ds(rdata, tctx, target)); +} + +static inline isc_result_t +generic_fromwire_ds(ARGS_FROMWIRE) { + isc_region_t sr; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + + /* + * Check digest lengths if we know them. + */ + if (sr.length < 4 || + (sr.base[3] == DNS_DSDIGEST_SHA1 && + sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || + (sr.base[3] == DNS_DSDIGEST_SHA256 && + sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || +#ifdef ISC_GOST_DIGESTLENGTH + (sr.base[3] == DNS_DSDIGEST_GOST && + sr.length < 4 + ISC_GOST_DIGESTLENGTH) || +#endif + (sr.base[3] == DNS_DSDIGEST_SHA384 && + sr.length < 4 + ISC_SHA384_DIGESTLENGTH)) + return (ISC_R_UNEXPECTEDEND); + + /* + * Only copy digest lengths if we know them. + * If there is extra data dns_rdata_fromwire() will + * detect that. + */ + if (sr.base[3] == DNS_DSDIGEST_SHA1) + sr.length = 4 + ISC_SHA1_DIGESTLENGTH; + else if (sr.base[3] == DNS_DSDIGEST_SHA256) + sr.length = 4 + ISC_SHA256_DIGESTLENGTH; +#ifdef ISC_GOST_DIGESTLENGTH + else if (sr.base[3] == DNS_DSDIGEST_GOST) + sr.length = 4 + ISC_GOST_DIGESTLENGTH; +#endif + else if (sr.base[3] == DNS_DSDIGEST_SHA384) + sr.length = 4 + ISC_SHA384_DIGESTLENGTH; + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +fromwire_ds(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_ds); + + return (generic_fromwire_ds(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_ds(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_ds); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_ds(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ds); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +generic_fromstruct_ds(ARGS_FROMSTRUCT) { + dns_rdata_ds_t *ds = source; + + REQUIRE(source != NULL); + REQUIRE(ds->common.rdtype == type); + REQUIRE(ds->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + switch (ds->digest_type) { + case DNS_DSDIGEST_SHA1: + REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH); + break; + case DNS_DSDIGEST_SHA256: + REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH); + break; +#ifdef ISC_GOST_DIGESTLENGTH + case DNS_DSDIGEST_GOST: + REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH); + break; +#endif + case DNS_DSDIGEST_SHA384: + REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH); + break; + } + + RETERR(uint16_tobuffer(ds->key_tag, target)); + RETERR(uint8_tobuffer(ds->algorithm, target)); + RETERR(uint8_tobuffer(ds->digest_type, target)); + + return (mem_tobuffer(target, ds->digest, ds->length)); +} + +static inline isc_result_t +fromstruct_ds(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_ds); + + return (generic_fromstruct_ds(rdclass, type, source, target)); +} + +static inline isc_result_t +generic_tostruct_ds(ARGS_TOSTRUCT) { + dns_rdata_ds_t *ds = target; + isc_region_t region; + + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + REQUIRE(ds->common.rdtype == rdata->type); + REQUIRE(ds->common.rdclass == rdata->rdclass); + REQUIRE(!ISC_LINK_LINKED(&ds->common, link)); + + dns_rdata_toregion(rdata, ®ion); + + ds->key_tag = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + ds->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + ds->digest_type = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + ds->length = region.length; + + ds->digest = mem_maybedup(mctx, region.base, region.length); + if (ds->digest == NULL) + return (ISC_R_NOMEMORY); + + ds->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +tostruct_ds(ARGS_TOSTRUCT) { + dns_rdata_ds_t *ds = target; + + REQUIRE(rdata->type == dns_rdatatype_ds); + REQUIRE(target != NULL); + + ds->common.rdclass = rdata->rdclass; + ds->common.rdtype = rdata->type; + ISC_LINK_INIT(&ds->common, link); + + return (generic_tostruct_ds(rdata, target, mctx)); +} + +static inline void +freestruct_ds(ARGS_FREESTRUCT) { + dns_rdata_ds_t *ds = source; + + REQUIRE(ds != NULL); + REQUIRE(ds->common.rdtype == dns_rdatatype_ds); + + if (ds->mctx == NULL) + return; + + if (ds->digest != NULL) + isc_mem_free(ds->mctx, ds->digest); + ds->mctx = NULL; +} + +static inline isc_result_t +additionaldata_ds(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_ds); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_ds(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_ds); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_ds(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_ds); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_ds(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_ds); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_ds(ARGS_COMPARE) { + return (compare_ds(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_DS_43_C */ diff --git a/lib/dns/rdata/generic/ds_43.h b/lib/dns/rdata/generic/ds_43.h new file mode 100644 index 0000000..0d373ec --- /dev/null +++ b/lib/dns/rdata/generic/ds_43.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_DS_43_H +#define GENERIC_DS_43_H 1 + +/*! + * \brief per draft-ietf-dnsext-delegation-signer-05.txt */ +typedef struct dns_rdata_ds { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t key_tag; + uint8_t algorithm; + uint8_t digest_type; + uint16_t length; + unsigned char *digest; +} dns_rdata_ds_t; + +#endif /* GENERIC_DS_43_H */ diff --git a/lib/dns/rdata/generic/eui48_108.c b/lib/dns/rdata/generic/eui48_108.c new file mode 100644 index 0000000..686f23f --- /dev/null +++ b/lib/dns/rdata/generic/eui48_108.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_EUI48_108_C +#define RDATA_GENERIC_EUI48_108_C + +#include <string.h> + +#define RRTYPE_EUI48_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_eui48(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char eui48[6]; + unsigned int l0, l1, l2, l3, l4, l5; + int n; + + REQUIRE(type == dns_rdatatype_eui48); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + n = sscanf(DNS_AS_STR(token), "%2x-%2x-%2x-%2x-%2x-%2x", + &l0, &l1, &l2, &l3, &l4, &l5); + if (n != 6 || l0 > 255U || l1 > 255U || l2 > 255U || l3 > 255U || + l4 > 255U || l5 > 255U) + return (DNS_R_BADEUI); + + eui48[0] = l0; + eui48[1] = l1; + eui48[2] = l2; + eui48[3] = l3; + eui48[4] = l4; + eui48[5] = l5; + return (mem_tobuffer(target, eui48, sizeof(eui48))); +} + +static inline isc_result_t +totext_eui48(ARGS_TOTEXT) { + char buf[sizeof("xx-xx-xx-xx-xx-xx")]; + + REQUIRE(rdata->type == dns_rdatatype_eui48); + REQUIRE(rdata->length == 6); + + UNUSED(tctx); + + (void)snprintf(buf, sizeof(buf), "%02x-%02x-%02x-%02x-%02x-%02x", + rdata->data[0], rdata->data[1], rdata->data[2], + rdata->data[3], rdata->data[4], rdata->data[5]); + return (str_totext(buf, target)); +} + +static inline isc_result_t +fromwire_eui48(ARGS_FROMWIRE) { + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_eui48); + + UNUSED(type); + UNUSED(options); + UNUSED(rdclass); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length != 6) + return (DNS_R_FORMERR); + isc_buffer_forward(source, sregion.length); + return (mem_tobuffer(target, sregion.base, sregion.length)); +} + +static inline isc_result_t +towire_eui48(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_eui48); + REQUIRE(rdata->length == 6); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_eui48(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_eui48); + REQUIRE(rdata1->length == 6); + REQUIRE(rdata2->length == 6); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_eui48(ARGS_FROMSTRUCT) { + dns_rdata_eui48_t *eui48 = source; + + REQUIRE(type == dns_rdatatype_eui48); + REQUIRE(source != NULL); + REQUIRE(eui48->common.rdtype == type); + REQUIRE(eui48->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, eui48->eui48, sizeof(eui48->eui48))); +} + +static inline isc_result_t +tostruct_eui48(ARGS_TOSTRUCT) { + dns_rdata_eui48_t *eui48 = target; + + REQUIRE(rdata->type == dns_rdatatype_eui48); + REQUIRE(target != NULL); + REQUIRE(rdata->length == 6); + + UNUSED(mctx); + + eui48->common.rdclass = rdata->rdclass; + eui48->common.rdtype = rdata->type; + ISC_LINK_INIT(&eui48->common, link); + + memmove(eui48->eui48, rdata->data, rdata->length); + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_eui48(ARGS_FREESTRUCT) { + dns_rdata_eui48_t *eui48 = source; + + REQUIRE(source != NULL); + REQUIRE(eui48->common.rdtype == dns_rdatatype_eui48); + + return; +} + +static inline isc_result_t +additionaldata_eui48(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_eui48); + REQUIRE(rdata->length == 6); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_eui48(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_eui48); + REQUIRE(rdata->length == 6); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_eui48(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_eui48); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_eui48(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_eui48); + REQUIRE(rdata->length == 6); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_eui48(ARGS_COMPARE) { + return (compare_eui48(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_EUI48_108_C */ diff --git a/lib/dns/rdata/generic/eui48_108.h b/lib/dns/rdata/generic/eui48_108.h new file mode 100644 index 0000000..1bb168a --- /dev/null +++ b/lib/dns/rdata/generic/eui48_108.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_EUI48_108_H +#define GENERIC_EUI48_108_H 1 + +typedef struct dns_rdata_eui48 { + dns_rdatacommon_t common; + unsigned char eui48[6]; +} dns_rdata_eui48_t; + +#endif /* GENERIC_EUI48_10k_H */ diff --git a/lib/dns/rdata/generic/eui64_109.c b/lib/dns/rdata/generic/eui64_109.c new file mode 100644 index 0000000..0a37326 --- /dev/null +++ b/lib/dns/rdata/generic/eui64_109.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_EUI64_109_C +#define RDATA_GENERIC_EUI64_109_C + +#include <string.h> + +#define RRTYPE_EUI64_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_eui64(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char eui64[8]; + unsigned int l0, l1, l2, l3, l4, l5, l6, l7; + int n; + + REQUIRE(type == dns_rdatatype_eui64); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + n = sscanf(DNS_AS_STR(token), "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x", + &l0, &l1, &l2, &l3, &l4, &l5, &l6, &l7); + if (n != 8 || l0 > 255U || l1 > 255U || l2 > 255U || l3 > 255U || + l4 > 255U || l5 > 255U || l6 > 255U || l7 > 255U) + return (DNS_R_BADEUI); + + eui64[0] = l0; + eui64[1] = l1; + eui64[2] = l2; + eui64[3] = l3; + eui64[4] = l4; + eui64[5] = l5; + eui64[6] = l6; + eui64[7] = l7; + return (mem_tobuffer(target, eui64, sizeof(eui64))); +} + +static inline isc_result_t +totext_eui64(ARGS_TOTEXT) { + char buf[sizeof("xx-xx-xx-xx-xx-xx-xx-xx")]; + + REQUIRE(rdata->type == dns_rdatatype_eui64); + REQUIRE(rdata->length == 8); + + UNUSED(tctx); + + (void)snprintf(buf, sizeof(buf), + "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", + rdata->data[0], rdata->data[1], + rdata->data[2], rdata->data[3], + rdata->data[4], rdata->data[5], + rdata->data[6], rdata->data[7]); + return (str_totext(buf, target)); +} + +static inline isc_result_t +fromwire_eui64(ARGS_FROMWIRE) { + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_eui64); + + UNUSED(type); + UNUSED(options); + UNUSED(rdclass); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length != 8) + return (DNS_R_FORMERR); + isc_buffer_forward(source, sregion.length); + return (mem_tobuffer(target, sregion.base, sregion.length)); +} + +static inline isc_result_t +towire_eui64(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_eui64); + REQUIRE(rdata->length == 8); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_eui64(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_eui64); + REQUIRE(rdata1->length == 8); + REQUIRE(rdata2->length == 8); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_eui64(ARGS_FROMSTRUCT) { + dns_rdata_eui64_t *eui64 = source; + + REQUIRE(type == dns_rdatatype_eui64); + REQUIRE(source != NULL); + REQUIRE(eui64->common.rdtype == type); + REQUIRE(eui64->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, eui64->eui64, sizeof(eui64->eui64))); +} + +static inline isc_result_t +tostruct_eui64(ARGS_TOSTRUCT) { + dns_rdata_eui64_t *eui64 = target; + + REQUIRE(rdata->type == dns_rdatatype_eui64); + REQUIRE(target != NULL); + REQUIRE(rdata->length == 8); + + UNUSED(mctx); + + eui64->common.rdclass = rdata->rdclass; + eui64->common.rdtype = rdata->type; + ISC_LINK_INIT(&eui64->common, link); + + memmove(eui64->eui64, rdata->data, rdata->length); + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_eui64(ARGS_FREESTRUCT) { + dns_rdata_eui64_t *eui64 = source; + + REQUIRE(source != NULL); + REQUIRE(eui64->common.rdtype == dns_rdatatype_eui64); + + return; +} + +static inline isc_result_t +additionaldata_eui64(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_eui64); + REQUIRE(rdata->length == 8); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_eui64(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_eui64); + REQUIRE(rdata->length == 8); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_eui64(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_eui64); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_eui64(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_eui64); + REQUIRE(rdata->length == 8); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_eui64(ARGS_COMPARE) { + return (compare_eui64(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_EUI64_109_C */ diff --git a/lib/dns/rdata/generic/eui64_109.h b/lib/dns/rdata/generic/eui64_109.h new file mode 100644 index 0000000..638c72e --- /dev/null +++ b/lib/dns/rdata/generic/eui64_109.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_EUI64_109_H +#define GENERIC_EUI64_109_H 1 + +typedef struct dns_rdata_eui64 { + dns_rdatacommon_t common; + unsigned char eui64[8]; +} dns_rdata_eui64_t; + +#endif /* GENERIC_EUI64_10k_H */ diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c new file mode 100644 index 0000000..6242932 --- /dev/null +++ b/lib/dns/rdata/generic/gpos_27.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1712 */ + +#ifndef RDATA_GENERIC_GPOS_27_C +#define RDATA_GENERIC_GPOS_27_C + +#define RRTYPE_GPOS_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_gpos(ARGS_FROMTEXT) { + isc_token_t token; + int i; + + REQUIRE(type == dns_rdatatype_gpos); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + for (i = 0; i < 3; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_gpos(ARGS_TOTEXT) { + isc_region_t region; + int i; + + REQUIRE(rdata->type == dns_rdatatype_gpos); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + + for (i = 0; i < 3; i++) { + RETERR(txt_totext(®ion, true, target)); + if (i != 2) + RETERR(str_totext(" ", target)); + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_gpos(ARGS_FROMWIRE) { + int i; + + REQUIRE(type == dns_rdatatype_gpos); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + for (i = 0; i < 3; i++) + RETERR(txt_fromwire(source, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_gpos(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_gpos); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_gpos(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_gpos); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_gpos(ARGS_FROMSTRUCT) { + dns_rdata_gpos_t *gpos = source; + + REQUIRE(type == dns_rdatatype_gpos); + REQUIRE(source != NULL); + REQUIRE(gpos->common.rdtype == type); + REQUIRE(gpos->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(gpos->long_len, target)); + RETERR(mem_tobuffer(target, gpos->longitude, gpos->long_len)); + RETERR(uint8_tobuffer(gpos->lat_len, target)); + RETERR(mem_tobuffer(target, gpos->latitude, gpos->lat_len)); + RETERR(uint8_tobuffer(gpos->alt_len, target)); + return (mem_tobuffer(target, gpos->altitude, gpos->alt_len)); +} + +static inline isc_result_t +tostruct_gpos(ARGS_TOSTRUCT) { + dns_rdata_gpos_t *gpos = target; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_gpos); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + gpos->common.rdclass = rdata->rdclass; + gpos->common.rdtype = rdata->type; + ISC_LINK_INIT(&gpos->common, link); + + dns_rdata_toregion(rdata, ®ion); + gpos->long_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + gpos->longitude = mem_maybedup(mctx, region.base, gpos->long_len); + if (gpos->longitude == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(®ion, gpos->long_len); + + gpos->lat_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + gpos->latitude = mem_maybedup(mctx, region.base, gpos->lat_len); + if (gpos->latitude == NULL) + goto cleanup_longitude; + isc_region_consume(®ion, gpos->lat_len); + + gpos->alt_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + if (gpos->lat_len > 0) { + gpos->altitude = + mem_maybedup(mctx, region.base, gpos->alt_len); + if (gpos->altitude == NULL) + goto cleanup_latitude; + } else + gpos->altitude = NULL; + + gpos->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup_latitude: + if (mctx != NULL && gpos->longitude != NULL) + isc_mem_free(mctx, gpos->longitude); + + cleanup_longitude: + if (mctx != NULL && gpos->latitude != NULL) + isc_mem_free(mctx, gpos->latitude); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_gpos(ARGS_FREESTRUCT) { + dns_rdata_gpos_t *gpos = source; + + REQUIRE(source != NULL); + REQUIRE(gpos->common.rdtype == dns_rdatatype_gpos); + + if (gpos->mctx == NULL) + return; + + if (gpos->longitude != NULL) + isc_mem_free(gpos->mctx, gpos->longitude); + if (gpos->latitude != NULL) + isc_mem_free(gpos->mctx, gpos->latitude); + if (gpos->altitude != NULL) + isc_mem_free(gpos->mctx, gpos->altitude); + gpos->mctx = NULL; +} + +static inline isc_result_t +additionaldata_gpos(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_gpos); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_gpos(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_gpos); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_gpos(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_gpos); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_gpos(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_gpos); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_gpos(ARGS_COMPARE) { + return (compare_gpos(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_GPOS_27_C */ diff --git a/lib/dns/rdata/generic/gpos_27.h b/lib/dns/rdata/generic/gpos_27.h new file mode 100644 index 0000000..fac72cd --- /dev/null +++ b/lib/dns/rdata/generic/gpos_27.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_GPOS_27_H +#define GENERIC_GPOS_27_H 1 + + +/*! + * \brief per RFC1712 */ + +typedef struct dns_rdata_gpos { + dns_rdatacommon_t common; + isc_mem_t *mctx; + char *longitude; + char *latitude; + char *altitude; + uint8_t long_len; + uint8_t lat_len; + uint8_t alt_len; +} dns_rdata_gpos_t; + +#endif /* GENERIC_GPOS_27_H */ diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c new file mode 100644 index 0000000..528be5e --- /dev/null +++ b/lib/dns/rdata/generic/hinfo_13.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_HINFO_13_C +#define RDATA_GENERIC_HINFO_13_C + +#define RRTYPE_HINFO_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_hinfo(ARGS_FROMTEXT) { + isc_token_t token; + int i; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + REQUIRE(type == dns_rdatatype_hinfo); + + for (i = 0; i < 2; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_hinfo(ARGS_TOTEXT) { + isc_region_t region; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_hinfo); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + RETERR(txt_totext(®ion, true, target)); + RETERR(str_totext(" ", target)); + return (txt_totext(®ion, true, target)); +} + +static inline isc_result_t +fromwire_hinfo(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_hinfo); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + RETERR(txt_fromwire(source, target)); + return (txt_fromwire(source, target)); +} + +static inline isc_result_t +towire_hinfo(ARGS_TOWIRE) { + + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_hinfo); + REQUIRE(rdata->length != 0); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_hinfo(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_hinfo); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_hinfo(ARGS_FROMSTRUCT) { + dns_rdata_hinfo_t *hinfo = source; + + REQUIRE(type == dns_rdatatype_hinfo); + REQUIRE(source != NULL); + REQUIRE(hinfo->common.rdtype == type); + REQUIRE(hinfo->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(hinfo->cpu_len, target)); + RETERR(mem_tobuffer(target, hinfo->cpu, hinfo->cpu_len)); + RETERR(uint8_tobuffer(hinfo->os_len, target)); + return (mem_tobuffer(target, hinfo->os, hinfo->os_len)); +} + +static inline isc_result_t +tostruct_hinfo(ARGS_TOSTRUCT) { + dns_rdata_hinfo_t *hinfo = target; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_hinfo); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + hinfo->common.rdclass = rdata->rdclass; + hinfo->common.rdtype = rdata->type; + ISC_LINK_INIT(&hinfo->common, link); + + dns_rdata_toregion(rdata, ®ion); + hinfo->cpu_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + hinfo->cpu = mem_maybedup(mctx, region.base, hinfo->cpu_len); + if (hinfo->cpu == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(®ion, hinfo->cpu_len); + + hinfo->os_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + hinfo->os = mem_maybedup(mctx, region.base, hinfo->os_len); + if (hinfo->os == NULL) + goto cleanup; + + hinfo->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL && hinfo->cpu != NULL) + isc_mem_free(mctx, hinfo->cpu); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_hinfo(ARGS_FREESTRUCT) { + dns_rdata_hinfo_t *hinfo = source; + + REQUIRE(source != NULL); + + if (hinfo->mctx == NULL) + return; + + if (hinfo->cpu != NULL) + isc_mem_free(hinfo->mctx, hinfo->cpu); + if (hinfo->os != NULL) + isc_mem_free(hinfo->mctx, hinfo->os); + hinfo->mctx = NULL; +} + +static inline isc_result_t +additionaldata_hinfo(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_hinfo); + + UNUSED(add); + UNUSED(arg); + UNUSED(rdata); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_hinfo(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_hinfo); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_hinfo(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_hinfo); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_hinfo(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_hinfo); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_hinfo(ARGS_COMPARE) { + return (compare_hinfo(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_HINFO_13_C */ diff --git a/lib/dns/rdata/generic/hinfo_13.h b/lib/dns/rdata/generic/hinfo_13.h new file mode 100644 index 0000000..323be22 --- /dev/null +++ b/lib/dns/rdata/generic/hinfo_13.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_HINFO_13_H +#define GENERIC_HINFO_13_H 1 + + +typedef struct dns_rdata_hinfo { + dns_rdatacommon_t common; + isc_mem_t *mctx; + char *cpu; + char *os; + uint8_t cpu_len; + uint8_t os_len; +} dns_rdata_hinfo_t; + +#endif /* GENERIC_HINFO_13_H */ diff --git a/lib/dns/rdata/generic/hip_55.c b/lib/dns/rdata/generic/hip_55.c new file mode 100644 index 0000000..36c9273 --- /dev/null +++ b/lib/dns/rdata/generic/hip_55.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC 5205 */ + +#ifndef RDATA_GENERIC_HIP_5_C +#define RDATA_GENERIC_HIP_5_C + +#define RRTYPE_HIP_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_hip(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + isc_buffer_t hit_len; + isc_buffer_t key_len; + unsigned char *start; + size_t len; + + REQUIRE(type == dns_rdatatype_hip); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Dummy HIT len. + */ + hit_len = *target; + RETERR(uint8_tobuffer(0, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Dummy KEY len. + */ + key_len = *target; + RETERR(uint16_tobuffer(0, target)); + + /* + * HIT (base16). + */ + start = isc_buffer_used(target); + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target)); + + /* + * Fill in HIT len. + */ + len = (unsigned char *)isc_buffer_used(target) - start; + if (len > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer((uint32_t)len, &hit_len)); + + /* + * Public key (base64). + */ + start = isc_buffer_used(target); + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target)); + + /* + * Fill in KEY len. + */ + len = (unsigned char *)isc_buffer_used(target) - start; + if (len > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer((uint32_t)len, &key_len)); + + if (origin == NULL) + origin = dns_rootname; + + /* + * Rendezvous Servers. + */ + dns_name_init(&name, NULL); + do { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + true)); + if (token.type != isc_tokentype_string) + break; + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, + target)); + } while (1); + + /* + * Let upper layer handle eol/eof. + */ + isc_lex_ungettoken(lexer, &token); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_hip(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + unsigned int length, key_len, hit_len; + unsigned char algorithm; + char buf[sizeof("225 ")]; + + REQUIRE(rdata->type == dns_rdatatype_hip); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + + hit_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + key_len = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext("( ", target)); + + /* + * Algorithm + */ + snprintf(buf, sizeof(buf), "%u ", algorithm); + RETERR(str_totext(buf, target)); + + /* + * HIT. + */ + INSIST(hit_len < region.length); + length = region.length; + region.length = hit_len; + RETERR(isc_hex_totext(®ion, 1, "", target)); + region.length = length - hit_len; + RETERR(str_totext(tctx->linebreak, target)); + + /* + * Public KEY. + */ + INSIST(key_len <= region.length); + length = region.length; + region.length = key_len; + RETERR(isc_base64_totext(®ion, 1, "", target)); + region.length = length - key_len; + RETERR(str_totext(tctx->linebreak, target)); + + /* + * Rendezvous Servers. + */ + dns_name_init(&name, NULL); + while (region.length > 0) { + dns_name_fromregion(&name, ®ion); + + RETERR(dns_name_totext(&name, false, target)); + isc_region_consume(®ion, name.length); + if (region.length > 0) + RETERR(str_totext(tctx->linebreak, target)); + } + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_hip(ARGS_FROMWIRE) { + isc_region_t region, rr; + dns_name_t name; + uint8_t hit_len; + uint16_t key_len; + + REQUIRE(type == dns_rdatatype_hip); + + UNUSED(type); + UNUSED(rdclass); + + isc_buffer_activeregion(source, ®ion); + if (region.length < 4U) + RETERR(DNS_R_FORMERR); + + rr = region; + hit_len = uint8_fromregion(®ion); + if (hit_len == 0) + RETERR(DNS_R_FORMERR); + isc_region_consume(®ion, 2); /* hit length + algorithm */ + key_len = uint16_fromregion(®ion); + if (key_len == 0) + RETERR(DNS_R_FORMERR); + isc_region_consume(®ion, 2); + if (region.length < (unsigned) (hit_len + key_len)) + RETERR(DNS_R_FORMERR); + + RETERR(mem_tobuffer(target, rr.base, 4 + hit_len + key_len)); + isc_buffer_forward(source, 4 + hit_len + key_len); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + while (isc_buffer_activelength(source) > 0) { + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_hip(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_hip); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_hip(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_hip); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_hip(ARGS_FROMSTRUCT) { + dns_rdata_hip_t *hip = source; + dns_rdata_hip_t myhip; + isc_result_t result; + + REQUIRE(type == dns_rdatatype_hip); + REQUIRE(source != NULL); + REQUIRE(hip->common.rdtype == type); + REQUIRE(hip->common.rdclass == rdclass); + REQUIRE(hip->hit_len > 0 && hip->hit != NULL); + REQUIRE(hip->key_len > 0 && hip->key != NULL); + REQUIRE((hip->servers == NULL && hip->servers_len == 0) || + (hip->servers != NULL && hip->servers_len != 0)); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(hip->hit_len, target)); + RETERR(uint8_tobuffer(hip->algorithm, target)); + RETERR(uint16_tobuffer(hip->key_len, target)); + RETERR(mem_tobuffer(target, hip->hit, hip->hit_len)); + RETERR(mem_tobuffer(target, hip->key, hip->key_len)); + + myhip = *hip; + for (result = dns_rdata_hip_first(&myhip); + result == ISC_R_SUCCESS; + result = dns_rdata_hip_next(&myhip)) + /* empty */; + + return(mem_tobuffer(target, hip->servers, hip->servers_len)); +} + +static inline isc_result_t +tostruct_hip(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_hip_t *hip = target; + + REQUIRE(rdata->type == dns_rdatatype_hip); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + hip->common.rdclass = rdata->rdclass; + hip->common.rdtype = rdata->type; + ISC_LINK_INIT(&hip->common, link); + + dns_rdata_toregion(rdata, ®ion); + + hip->hit_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + hip->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + hip->key_len = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + hip->hit = hip->key = hip->servers = NULL; + + hip->hit = mem_maybedup(mctx, region.base, hip->hit_len); + if (hip->hit == NULL) + goto cleanup; + isc_region_consume(®ion, hip->hit_len); + + INSIST(hip->key_len <= region.length); + + hip->key = mem_maybedup(mctx, region.base, hip->key_len); + if (hip->key == NULL) + goto cleanup; + isc_region_consume(®ion, hip->key_len); + + hip->servers_len = region.length; + if (hip->servers_len != 0) { + hip->servers = mem_maybedup(mctx, region.base, region.length); + if (hip->servers == NULL) + goto cleanup; + } + + hip->offset = hip->servers_len; + hip->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (hip->hit != NULL) + isc_mem_free(mctx, hip->hit); + if (hip->key != NULL) + isc_mem_free(mctx, hip->key); + if (hip->servers != NULL) + isc_mem_free(mctx, hip->servers); + return (ISC_R_NOMEMORY); + +} + +static inline void +freestruct_hip(ARGS_FREESTRUCT) { + dns_rdata_hip_t *hip = source; + + REQUIRE(source != NULL); + + if (hip->mctx == NULL) + return; + + isc_mem_free(hip->mctx, hip->hit); + isc_mem_free(hip->mctx, hip->key); + if (hip->servers != NULL) + isc_mem_free(hip->mctx, hip->servers); + hip->mctx = NULL; +} + +static inline isc_result_t +additionaldata_hip(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_hip); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_hip(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_hip); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_hip(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_hip); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_hip(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_hip); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +isc_result_t +dns_rdata_hip_first(dns_rdata_hip_t *hip) { + if (hip->servers_len == 0) + return (ISC_R_NOMORE); + hip->offset = 0; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_hip_next(dns_rdata_hip_t *hip) { + isc_region_t region; + dns_name_t name; + + if (hip->offset >= hip->servers_len) + return (ISC_R_NOMORE); + + region.base = hip->servers + hip->offset; + region.length = hip->servers_len - hip->offset; + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + hip->offset += name.length; + INSIST(hip->offset <= hip->servers_len); + return (ISC_R_SUCCESS); +} + +void +dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) { + isc_region_t region; + + REQUIRE(hip->offset < hip->servers_len); + + region.base = hip->servers + hip->offset; + region.length = hip->servers_len - hip->offset; + dns_name_fromregion(name, ®ion); + + INSIST(name->length + hip->offset <= hip->servers_len); +} + +static inline int +casecompare_hip(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + uint8_t hit_len; + uint16_t key_len; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_hip); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + INSIST(r1.length > 4); + INSIST(r2.length > 4); + order = memcmp(r1.base, r2.base, 4); + if (order != 0) + return (order); + + hit_len = uint8_fromregion(&r1); + isc_region_consume(&r1, 2); /* hit length + algorithm */ + key_len = uint16_fromregion(&r1); + isc_region_consume(&r1, 2); /* key length */ + isc_region_consume(&r2, 4); + + INSIST(r1.length >= (unsigned) (hit_len + key_len)); + INSIST(r2.length >= (unsigned) (hit_len + key_len)); + order = memcmp(r1.base, r2.base, hit_len + key_len); + if (order != 0) + return (order); + isc_region_consume(&r1, hit_len + key_len); + isc_region_consume(&r2, hit_len + key_len); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + while (r1.length != 0 && r2.length != 0) { + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + } + return (isc_region_compare(&r1, &r2)); +} + +#endif /* RDATA_GENERIC_HIP_5_C */ diff --git a/lib/dns/rdata/generic/hip_55.h b/lib/dns/rdata/generic/hip_55.h new file mode 100644 index 0000000..12c195c --- /dev/null +++ b/lib/dns/rdata/generic/hip_55.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_HIP_5_H +#define GENERIC_HIP_5_H 1 + +/* RFC 5205 */ + +typedef struct dns_rdata_hip { + dns_rdatacommon_t common; + isc_mem_t * mctx; + unsigned char * hit; + unsigned char * key; + unsigned char * servers; + uint8_t algorithm; + uint8_t hit_len; + uint16_t key_len; + uint16_t servers_len; + /* Private */ + uint16_t offset; +} dns_rdata_hip_t; + +isc_result_t +dns_rdata_hip_first(dns_rdata_hip_t *); + +isc_result_t +dns_rdata_hip_next(dns_rdata_hip_t *); + +void +dns_rdata_hip_current(dns_rdata_hip_t *, dns_name_t *); + +#endif /* GENERIC_HIP_5_H */ diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c new file mode 100644 index 0000000..f68f0b8 --- /dev/null +++ b/lib/dns/rdata/generic/ipseckey_45.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef RDATA_GENERIC_IPSECKEY_45_C +#define RDATA_GENERIC_IPSECKEY_45_C + +#include <string.h> + +#include <isc/net.h> + +#define RRTYPE_IPSECKEY_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_ipseckey(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + unsigned int gateway; + struct in_addr addr; + unsigned char addr6[16]; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_ipseckey); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Precedence. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Gateway type. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0x3U) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + gateway = token.value.as_ulong; + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Gateway. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + switch (gateway) { + case 0: + if (strcmp(DNS_AS_STR(token), ".") != 0) + RETTOK(DNS_R_SYNTAX); + break; + + case 1: + if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1) + RETTOK(DNS_R_BADDOTTEDQUAD); + isc_buffer_availableregion(target, ®ion); + if (region.length < 4) + return (ISC_R_NOSPACE); + memmove(region.base, &addr, 4); + isc_buffer_add(target, 4); + break; + + case 2: + if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) + RETTOK(DNS_R_BADAAAA); + isc_buffer_availableregion(target, ®ion); + if (region.length < 16) + return (ISC_R_NOSPACE); + memmove(region.base, addr6, 16); + isc_buffer_add(target, 16); + break; + + case 3: + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, + options, target)); + break; + } + + /* + * Public key. + */ + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_ipseckey(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + char buf[sizeof("255 ")]; + unsigned short num; + unsigned short gateway; + + REQUIRE(rdata->type == dns_rdatatype_ipseckey); + REQUIRE(rdata->length >= 3); + + dns_name_init(&name, NULL); + + if (rdata->data[1] > 3U) + return (ISC_R_NOTIMPLEMENTED); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext("( ", target)); + + /* + * Precedence. + */ + dns_rdata_toregion(rdata, ®ion); + num = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + snprintf(buf, sizeof(buf), "%u ", num); + RETERR(str_totext(buf, target)); + + /* + * Gateway type. + */ + gateway = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + snprintf(buf, sizeof(buf), "%u ", gateway); + RETERR(str_totext(buf, target)); + + /* + * Algorithm. + */ + num = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + snprintf(buf, sizeof(buf), "%u ", num); + RETERR(str_totext(buf, target)); + + /* + * Gateway. + */ + switch (gateway) { + case 0: + RETERR(str_totext(".", target)); + break; + + case 1: + RETERR(inet_totext(AF_INET, ®ion, target)); + isc_region_consume(®ion, 4); + break; + + case 2: + RETERR(inet_totext(AF_INET6, ®ion, target)); + isc_region_consume(®ion, 16); + break; + + case 3: + dns_name_fromregion(&name, ®ion); + RETERR(dns_name_totext(&name, false, target)); + isc_region_consume(®ion, name_length(&name)); + break; + } + + /* + * Key. + */ + if (region.length > 0U) { + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(®ion, 60, "", target)); + else + RETERR(isc_base64_totext(®ion, tctx->width - 2, + tctx->linebreak, target)); + } + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_ipseckey(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_ipseckey); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + isc_buffer_activeregion(source, ®ion); + if (region.length < 3) + return (ISC_R_UNEXPECTEDEND); + + switch (region.base[1]) { + case 0: + isc_buffer_forward(source, region.length); + return (mem_tobuffer(target, region.base, region.length)); + + case 1: + if (region.length < 7) + return (ISC_R_UNEXPECTEDEND); + isc_buffer_forward(source, region.length); + return (mem_tobuffer(target, region.base, region.length)); + + case 2: + if (region.length < 19) + return (ISC_R_UNEXPECTEDEND); + isc_buffer_forward(source, region.length); + return (mem_tobuffer(target, region.base, region.length)); + + case 3: + RETERR(mem_tobuffer(target, region.base, 3)); + isc_buffer_forward(source, 3); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + isc_buffer_activeregion(source, ®ion); + isc_buffer_forward(source, region.length); + return(mem_tobuffer(target, region.base, region.length)); + + default: + return (ISC_R_NOTIMPLEMENTED); + } +} + +static inline isc_result_t +towire_ipseckey(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_ipseckey); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_ipseckey(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ipseckey); + REQUIRE(rdata1->length >= 3); + REQUIRE(rdata2->length >= 3); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_ipseckey(ARGS_FROMSTRUCT) { + dns_rdata_ipseckey_t *ipseckey = source; + isc_region_t region; + uint32_t n; + + REQUIRE(type == dns_rdatatype_ipseckey); + REQUIRE(source != NULL); + REQUIRE(ipseckey->common.rdtype == type); + REQUIRE(ipseckey->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + if (ipseckey->gateway_type > 3U) + return (ISC_R_NOTIMPLEMENTED); + + RETERR(uint8_tobuffer(ipseckey->precedence, target)); + RETERR(uint8_tobuffer(ipseckey->gateway_type, target)); + RETERR(uint8_tobuffer(ipseckey->algorithm, target)); + + switch (ipseckey->gateway_type) { + case 0: + break; + + case 1: + n = ntohl(ipseckey->in_addr.s_addr); + RETERR(uint32_tobuffer(n, target)); + break; + + case 2: + RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16)); + break; + + case 3: + dns_name_toregion(&ipseckey->gateway, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + break; + } + + return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength)); +} + +static inline isc_result_t +tostruct_ipseckey(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_ipseckey_t *ipseckey = target; + dns_name_t name; + uint32_t n; + + REQUIRE(rdata->type == dns_rdatatype_ipseckey); + REQUIRE(target != NULL); + REQUIRE(rdata->length >= 3); + + if (rdata->data[1] > 3U) + return (ISC_R_NOTIMPLEMENTED); + + ipseckey->common.rdclass = rdata->rdclass; + ipseckey->common.rdtype = rdata->type; + ISC_LINK_INIT(&ipseckey->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + + ipseckey->precedence = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + ipseckey->gateway_type = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + ipseckey->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + switch (ipseckey->gateway_type) { + case 0: + break; + + case 1: + n = uint32_fromregion(®ion); + ipseckey->in_addr.s_addr = htonl(n); + isc_region_consume(®ion, 4); + break; + + case 2: + memmove(ipseckey->in6_addr.s6_addr, region.base, 16); + isc_region_consume(®ion, 16); + break; + + case 3: + dns_name_init(&ipseckey->gateway, NULL); + dns_name_fromregion(&name, ®ion); + RETERR(name_duporclone(&name, mctx, &ipseckey->gateway)); + isc_region_consume(®ion, name_length(&name)); + break; + } + + ipseckey->keylength = region.length; + if (ipseckey->keylength != 0U) { + ipseckey->key = mem_maybedup(mctx, region.base, + ipseckey->keylength); + if (ipseckey->key == NULL) { + if (ipseckey->gateway_type == 3) + dns_name_free(&ipseckey->gateway, + ipseckey->mctx); + return (ISC_R_NOMEMORY); + } + } else + ipseckey->key = NULL; + + ipseckey->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_ipseckey(ARGS_FREESTRUCT) { + dns_rdata_ipseckey_t *ipseckey = source; + + REQUIRE(source != NULL); + REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey); + + if (ipseckey->mctx == NULL) + return; + + if (ipseckey->gateway_type == 3) + dns_name_free(&ipseckey->gateway, ipseckey->mctx); + + if (ipseckey->key != NULL) + isc_mem_free(ipseckey->mctx, ipseckey->key); + + ipseckey->mctx = NULL; +} + +static inline isc_result_t +additionaldata_ipseckey(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_ipseckey); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_ipseckey(ARGS_DIGEST) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_ipseckey); + + dns_rdata_toregion(rdata, ®ion); + return ((digest)(arg, ®ion)); +} + +static inline bool +checkowner_ipseckey(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_ipseckey); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_ipseckey(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_ipseckey); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_ipseckey(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ipseckey); + REQUIRE(rdata1->length >= 3); + REQUIRE(rdata2->length >= 3); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3) + return (isc_region_compare(®ion1, ®ion2)); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + isc_region_consume(®ion1, 3); + isc_region_consume(®ion2, 3); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + return (isc_region_compare(®ion1, ®ion2)); +} + +#endif /* RDATA_GENERIC_IPSECKEY_45_C */ diff --git a/lib/dns/rdata/generic/ipseckey_45.h b/lib/dns/rdata/generic/ipseckey_45.h new file mode 100644 index 0000000..e3f5804 --- /dev/null +++ b/lib/dns/rdata/generic/ipseckey_45.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_IPSECKEY_45_H +#define GENERIC_IPSECKEY_45_H 1 + +typedef struct dns_rdata_ipseckey { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint8_t precedence; + uint8_t gateway_type; + uint8_t algorithm; + struct in_addr in_addr; /* gateway type 1 */ + struct in6_addr in6_addr; /* gateway type 2 */ + dns_name_t gateway; /* gateway type 3 */ + unsigned char *key; + uint16_t keylength; +} dns_rdata_ipseckey_t; + +#endif /* GENERIC_IPSECKEY_45_H */ diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c new file mode 100644 index 0000000..a73cd1f --- /dev/null +++ b/lib/dns/rdata/generic/isdn_20.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1183 */ + +#ifndef RDATA_GENERIC_ISDN_20_C +#define RDATA_GENERIC_ISDN_20_C + +#define RRTYPE_ISDN_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_isdn(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_isdn); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* ISDN-address */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + + /* sa: optional */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + true)); + if (token.type != isc_tokentype_string && + token.type != isc_tokentype_qstring) { + isc_lex_ungettoken(lexer, &token); + return (ISC_R_SUCCESS); + } + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_isdn(ARGS_TOTEXT) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_isdn); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + RETERR(txt_totext(®ion, true, target)); + if (region.length == 0) + return (ISC_R_SUCCESS); + RETERR(str_totext(" ", target)); + return (txt_totext(®ion, true, target)); +} + +static inline isc_result_t +fromwire_isdn(ARGS_FROMWIRE) { + REQUIRE(type == dns_rdatatype_isdn); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + RETERR(txt_fromwire(source, target)); + if (buffer_empty(source)) + return (ISC_R_SUCCESS); + return (txt_fromwire(source, target)); +} + +static inline isc_result_t +towire_isdn(ARGS_TOWIRE) { + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_isdn); + REQUIRE(rdata->length != 0); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_isdn(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_isdn); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_isdn(ARGS_FROMSTRUCT) { + dns_rdata_isdn_t *isdn = source; + + REQUIRE(type == dns_rdatatype_isdn); + REQUIRE(source != NULL); + REQUIRE(isdn->common.rdtype == type); + REQUIRE(isdn->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(isdn->isdn_len, target)); + RETERR(mem_tobuffer(target, isdn->isdn, isdn->isdn_len)); + if (isdn->subaddress == NULL) + return (ISC_R_SUCCESS); + RETERR(uint8_tobuffer(isdn->subaddress_len, target)); + return (mem_tobuffer(target, isdn->subaddress, isdn->subaddress_len)); +} + +static inline isc_result_t +tostruct_isdn(ARGS_TOSTRUCT) { + dns_rdata_isdn_t *isdn = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_isdn); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + isdn->common.rdclass = rdata->rdclass; + isdn->common.rdtype = rdata->type; + ISC_LINK_INIT(&isdn->common, link); + + dns_rdata_toregion(rdata, &r); + + isdn->isdn_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + isdn->isdn = mem_maybedup(mctx, r.base, isdn->isdn_len); + if (isdn->isdn == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(&r, isdn->isdn_len); + + if (r.length == 0) { + isdn->subaddress_len = 0; + isdn->subaddress = NULL; + } else { + isdn->subaddress_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + isdn->subaddress = mem_maybedup(mctx, r.base, + isdn->subaddress_len); + if (isdn->subaddress == NULL) + goto cleanup; + } + + isdn->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL && isdn->isdn != NULL) + isc_mem_free(mctx, isdn->isdn); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_isdn(ARGS_FREESTRUCT) { + dns_rdata_isdn_t *isdn = source; + + REQUIRE(source != NULL); + + if (isdn->mctx == NULL) + return; + + if (isdn->isdn != NULL) + isc_mem_free(isdn->mctx, isdn->isdn); + if (isdn->subaddress != NULL) + isc_mem_free(isdn->mctx, isdn->subaddress); + isdn->mctx = NULL; +} + +static inline isc_result_t +additionaldata_isdn(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_isdn); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_isdn(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_isdn); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_isdn(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_isdn); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_isdn(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_isdn); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_isdn(ARGS_COMPARE) { + return (compare_isdn(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_ISDN_20_C */ diff --git a/lib/dns/rdata/generic/isdn_20.h b/lib/dns/rdata/generic/isdn_20.h new file mode 100644 index 0000000..48758bb --- /dev/null +++ b/lib/dns/rdata/generic/isdn_20.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_ISDN_20_H +#define GENERIC_ISDN_20_H 1 + + +/*! + * \brief Per RFC1183 */ + +typedef struct dns_rdata_isdn { + dns_rdatacommon_t common; + isc_mem_t *mctx; + char *isdn; + char *subaddress; + uint8_t isdn_len; + uint8_t subaddress_len; +} dns_rdata_isdn_t; + +#endif /* GENERIC_ISDN_20_H */ diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c new file mode 100644 index 0000000..6dd2eab --- /dev/null +++ b/lib/dns/rdata/generic/key_25.c @@ -0,0 +1,436 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_KEY_25_C +#define RDATA_GENERIC_KEY_25_C + +#include <dst/dst.h> + +#define RRTYPE_KEY_ATTRIBUTES (0) + +static inline isc_result_t +generic_fromtext_key(ARGS_FROMTEXT) { + isc_result_t result; + isc_token_t token; + dns_secalg_t alg; + dns_secproto_t proto; + dns_keyflags_t flags; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* flags */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); + RETERR(uint16_tobuffer(flags, target)); + + /* protocol */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &proto, 1)); + + /* algorithm */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &alg, 1)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + result = isc_base64_tobuffer(lexer, target, -1); + if (result != ISC_R_SUCCESS) + return (result); + + /* Ensure there's at least enough data to compute a key ID for MD5 */ + if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7) + return (ISC_R_UNEXPECTEDEND); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +generic_totext_key(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("[key id = 64000]")]; + unsigned int flags; + unsigned char algorithm; + char algbuf[DNS_NAME_FORMATSIZE]; + const char *keyinfo; + isc_region_t tmpr; + + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* flags */ + flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u", flags); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + if ((flags & DNS_KEYFLAG_KSK) != 0) { + if (flags & DNS_KEYFLAG_REVOKE) + keyinfo = "revoked KSK"; + else + keyinfo = "KSK"; + } else + keyinfo = "ZSK"; + + + /* protocol */ + snprintf(buf, sizeof(buf), "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* algorithm */ + algorithm = sr.base[0]; + snprintf(buf, sizeof(buf), "%u", algorithm); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 && + algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &sr); + dns_name_format(&name, algbuf, sizeof(algbuf)); + } else { + dns_secalg_format((dns_secalg_t) algorithm, algbuf, + sizeof(algbuf)); + } + + /* key */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + + if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + } else { + dns_rdata_toregion(rdata, &tmpr); + snprintf(buf, sizeof(buf), "[key id = %u]", + dst_region_computeid(&tmpr, algorithm)); + RETERR(str_totext(buf, target)); + } + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) + RETERR(str_totext(tctx->linebreak, target)); + else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" ", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(")", target)); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { + + if (rdata->type == dns_rdatatype_dnskey || + rdata->type == dns_rdatatype_cdnskey) { + RETERR(str_totext(" ; ", target)); + RETERR(str_totext(keyinfo, target)); + } + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(algbuf, target)); + RETERR(str_totext(" ; key id = ", target)); + dns_rdata_toregion(rdata, &tmpr); + snprintf(buf, sizeof(buf), "%u", + dst_region_computeid(&tmpr, algorithm)); + RETERR(str_totext(buf, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +generic_fromwire_key(ARGS_FROMWIRE) { + unsigned char algorithm; + isc_region_t sr; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + + algorithm = sr.base[3]; + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_region_consume(&sr, 4); + isc_buffer_forward(source, 4); + + if (algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + } + + /* + * RSAMD5 computes key ID differently from other + * algorithms: we need to ensure there's enough data + * present for the computation + */ + if (algorithm == DST_ALG_RSAMD5 && sr.length < 3) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +fromtext_key(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_key); + + return (generic_fromtext_key(rdclass, type, lexer, origin, + options, target, callbacks)); +} + +static inline isc_result_t +totext_key(ARGS_TOTEXT) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_key); + + return (generic_totext_key(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_key(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_key); + + return (generic_fromwire_key(rdclass, type, source, dctx, + options, target)); +} + +static inline isc_result_t +towire_key(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_key); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_key(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_key); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +generic_fromstruct_key(ARGS_FROMSTRUCT) { + dns_rdata_key_t *key = source; + + REQUIRE(key != NULL); + REQUIRE(key->common.rdtype == type); + REQUIRE(key->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + /* Flags */ + RETERR(uint16_tobuffer(key->flags, target)); + + /* Protocol */ + RETERR(uint8_tobuffer(key->protocol, target)); + + /* Algorithm */ + RETERR(uint8_tobuffer(key->algorithm, target)); + + /* Data */ + return (mem_tobuffer(target, key->data, key->datalen)); +} + +static inline isc_result_t +generic_tostruct_key(ARGS_TOSTRUCT) { + dns_rdata_key_t *key = target; + isc_region_t sr; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->length != 0); + + REQUIRE(key != NULL); + REQUIRE(key->common.rdclass == rdata->rdclass); + REQUIRE(key->common.rdtype == rdata->type); + REQUIRE(!ISC_LINK_LINKED(&key->common, link)); + + dns_rdata_toregion(rdata, &sr); + + /* Flags */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + key->flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* Protocol */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + key->protocol = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Algorithm */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + key->algorithm = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Data */ + key->datalen = sr.length; + key->data = mem_maybedup(mctx, sr.base, key->datalen); + if (key->data == NULL) + return (ISC_R_NOMEMORY); + + key->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +generic_freestruct_key(ARGS_FREESTRUCT) { + dns_rdata_key_t *key = (dns_rdata_key_t *) source; + + REQUIRE(key != NULL); + + if (key->mctx == NULL) + return; + + if (key->data != NULL) + isc_mem_free(key->mctx, key->data); + key->mctx = NULL; +} + +static inline isc_result_t +fromstruct_key(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_key); + + return (generic_fromstruct_key(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_key(ARGS_TOSTRUCT) { + dns_rdata_key_t *key = target; + + REQUIRE(key != NULL); + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_key); + + key->common.rdclass = rdata->rdclass; + key->common.rdtype = rdata->type; + ISC_LINK_INIT(&key->common, link); + + return (generic_tostruct_key(rdata, target, mctx)); +} + +static inline void +freestruct_key(ARGS_FREESTRUCT) { + dns_rdata_key_t *key = (dns_rdata_key_t *) source; + + REQUIRE(key != NULL); + REQUIRE(key->common.rdtype == dns_rdatatype_key); + + generic_freestruct_key(source); +} + +static inline isc_result_t +additionaldata_key(ARGS_ADDLDATA) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_key); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_key(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_key); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_key(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_key); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_key(ARGS_CHECKNAMES) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_key); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_key(ARGS_COMPARE) { + return (compare_key(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_KEY_25_C */ diff --git a/lib/dns/rdata/generic/key_25.h b/lib/dns/rdata/generic/key_25.h new file mode 100644 index 0000000..330363b --- /dev/null +++ b/lib/dns/rdata/generic/key_25.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_KEY_25_H +#define GENERIC_KEY_25_H 1 + + +/*! + * \brief Per RFC2535 */ + +typedef struct dns_rdata_key { + dns_rdatacommon_t common; + isc_mem_t * mctx; + uint16_t flags; + uint8_t protocol; + uint8_t algorithm; + uint16_t datalen; + unsigned char * data; +} dns_rdata_key_t; + + +#endif /* GENERIC_KEY_25_H */ diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c new file mode 100644 index 0000000..06b56c1 --- /dev/null +++ b/lib/dns/rdata/generic/keydata_65533.c @@ -0,0 +1,441 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_KEYDATA_65533_C +#define GENERIC_KEYDATA_65533_C 1 + +#include <isc/time.h> +#include <isc/stdtime.h> + +#include <dst/dst.h> + +#define RRTYPE_KEYDATA_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_keydata(ARGS_FROMTEXT) { + isc_result_t result; + isc_token_t token; + dns_secalg_t alg; + dns_secproto_t proto; + dns_keyflags_t flags; + uint32_t refresh, addhd, removehd; + + REQUIRE(type == dns_rdatatype_keydata); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* refresh timer */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh)); + RETERR(uint32_tobuffer(refresh, target)); + + /* add hold-down */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd)); + RETERR(uint32_tobuffer(addhd, target)); + + /* remove hold-down */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd)); + RETERR(uint32_tobuffer(removehd, target)); + + /* flags */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); + RETERR(uint16_tobuffer(flags, target)); + + /* protocol */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &proto, 1)); + + /* algorithm */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &alg, 1)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + result = isc_base64_tobuffer(lexer, target, -1); + if (result != ISC_R_SUCCESS) + return (result); + + /* Ensure there's at least enough data to compute a key ID for MD5 */ + if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 19) + return (ISC_R_UNEXPECTEDEND); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_keydata(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000")]; + unsigned int flags; + unsigned char algorithm; + unsigned long refresh, add, deltime; + char algbuf[DNS_NAME_FORMATSIZE]; + const char *keyinfo; + + REQUIRE(rdata->type == dns_rdatatype_keydata); + + if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16) + return (unknown_totext(rdata, tctx, target)); + + dns_rdata_toregion(rdata, &sr); + + /* refresh timer */ + refresh = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(refresh, target)); + RETERR(str_totext(" ", target)); + + /* add hold-down */ + add = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(add, target)); + RETERR(str_totext(" ", target)); + + /* remove hold-down */ + deltime = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(deltime, target)); + RETERR(str_totext(" ", target)); + + /* flags */ + flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u", flags); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + if ((flags & DNS_KEYFLAG_KSK) != 0) { + if (flags & DNS_KEYFLAG_REVOKE) + keyinfo = "revoked KSK"; + else + keyinfo = "KSK"; + } else + keyinfo = "ZSK"; + + /* protocol */ + snprintf(buf, sizeof(buf), "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* algorithm */ + algorithm = sr.base[0]; + snprintf(buf, sizeof(buf), "%u", algorithm); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + /* key */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) + RETERR(str_totext(tctx->linebreak, target)); + else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" ", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(")", target)); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { + isc_region_t tmpr; + char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + isc_time_t t; + + RETERR(str_totext(" ; ", target)); + RETERR(str_totext(keyinfo, target)); + dns_secalg_format((dns_secalg_t) algorithm, algbuf, + sizeof(algbuf)); + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(algbuf, target)); + RETERR(str_totext("; key id = ", target)); + dns_rdata_toregion(rdata, &tmpr); + /* Skip over refresh, addhd, and removehd */ + isc_region_consume(&tmpr, 12); + snprintf(buf, sizeof(buf), "%u", + dst_region_computeid(&tmpr, algorithm)); + RETERR(str_totext(buf, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + isc_stdtime_t now; + + isc_stdtime_get(&now); + + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; next refresh: ", target)); + isc_time_set(&t, refresh, 0); + isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf)); + RETERR(str_totext(rbuf, target)); + + if (add == 0U) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; no trust", target)); + } else { + RETERR(str_totext(tctx->linebreak, target)); + if (add < now) { + RETERR(str_totext("; trusted since: ", + target)); + } else { + RETERR(str_totext("; trust pending: ", + target)); + } + isc_time_set(&t, add, 0); + isc_time_formathttptimestamp(&t, abuf, + sizeof(abuf)); + RETERR(str_totext(abuf, target)); + } + + if (deltime != 0U) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; removal pending: ", + target)); + isc_time_set(&t, deltime, 0); + isc_time_formathttptimestamp(&t, dbuf, + sizeof(dbuf)); + RETERR(str_totext(dbuf, target)); + } + } + + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_keydata(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_keydata); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_keydata(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_keydata); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_keydata(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_keydata); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_keydata(ARGS_FROMSTRUCT) { + dns_rdata_keydata_t *keydata = source; + + REQUIRE(type == dns_rdatatype_keydata); + REQUIRE(source != NULL); + REQUIRE(keydata->common.rdtype == type); + REQUIRE(keydata->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + /* Refresh timer */ + RETERR(uint32_tobuffer(keydata->refresh, target)); + + /* Add hold-down */ + RETERR(uint32_tobuffer(keydata->addhd, target)); + + /* Remove hold-down */ + RETERR(uint32_tobuffer(keydata->removehd, target)); + + /* Flags */ + RETERR(uint16_tobuffer(keydata->flags, target)); + + /* Protocol */ + RETERR(uint8_tobuffer(keydata->protocol, target)); + + /* Algorithm */ + RETERR(uint8_tobuffer(keydata->algorithm, target)); + + /* Data */ + return (mem_tobuffer(target, keydata->data, keydata->datalen)); +} + +static inline isc_result_t +tostruct_keydata(ARGS_TOSTRUCT) { + dns_rdata_keydata_t *keydata = target; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_keydata); + REQUIRE(target != NULL); + + keydata->common.rdclass = rdata->rdclass; + keydata->common.rdtype = rdata->type; + ISC_LINK_INIT(&keydata->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* Refresh timer */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + keydata->refresh = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* Add hold-down */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + keydata->addhd = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* Remove hold-down */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + keydata->removehd = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* Flags */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + keydata->flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* Protocol */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + keydata->protocol = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Algorithm */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + keydata->algorithm = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Data */ + keydata->datalen = sr.length; + keydata->data = mem_maybedup(mctx, sr.base, keydata->datalen); + if (keydata->data == NULL) + return (ISC_R_NOMEMORY); + + keydata->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_keydata(ARGS_FREESTRUCT) { + dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *) source; + + REQUIRE(source != NULL); + REQUIRE(keydata->common.rdtype == dns_rdatatype_keydata); + + if (keydata->mctx == NULL) + return; + + if (keydata->data != NULL) + isc_mem_free(keydata->mctx, keydata->data); + keydata->mctx = NULL; +} + +static inline isc_result_t +additionaldata_keydata(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_keydata); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_keydata(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_keydata); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_keydata(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_keydata); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_keydata(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_keydata); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_keydata(ARGS_COMPARE) { + return (compare_keydata(rdata1, rdata2)); +} + +#endif /* GENERIC_KEYDATA_65533_C */ diff --git a/lib/dns/rdata/generic/keydata_65533.h b/lib/dns/rdata/generic/keydata_65533.h new file mode 100644 index 0000000..40061e1 --- /dev/null +++ b/lib/dns/rdata/generic/keydata_65533.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_KEYDATA_65533_H +#define GENERIC_KEYDATA_65533_H 1 + + +typedef struct dns_rdata_keydata { + dns_rdatacommon_t common; + isc_mem_t * mctx; + uint32_t refresh; /* Timer for refreshing data */ + uint32_t addhd; /* Hold-down timer for adding */ + uint32_t removehd; /* Hold-down timer for removing */ + uint16_t flags; /* Copy of DNSKEY_48 */ + uint8_t protocol; + uint8_t algorithm; + uint16_t datalen; + unsigned char * data; +} dns_rdata_keydata_t; + +#endif /* GENERIC_KEYDATA_65533_H */ diff --git a/lib/dns/rdata/generic/l32_105.c b/lib/dns/rdata/generic/l32_105.c new file mode 100644 index 0000000..7d92cc2 --- /dev/null +++ b/lib/dns/rdata/generic/l32_105.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_L32_105_C +#define RDATA_GENERIC_L32_105_C + +#include <string.h> + +#include <isc/net.h> + +#define RRTYPE_L32_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_l32(ARGS_FROMTEXT) { + isc_token_t token; + struct in_addr addr; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_l32); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1) + RETTOK(DNS_R_BADDOTTEDQUAD); + isc_buffer_availableregion(target, ®ion); + if (region.length < 4) + return (ISC_R_NOSPACE); + memmove(region.base, &addr, 4); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_l32(ARGS_TOTEXT) { + isc_region_t region; + char buf[sizeof("65000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_l32); + REQUIRE(rdata->length == 6); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + return (inet_totext(AF_INET, ®ion, target)); +} + +static inline isc_result_t +fromwire_l32(ARGS_FROMWIRE) { + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_l32); + + UNUSED(type); + UNUSED(options); + UNUSED(rdclass); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length != 6) + return (DNS_R_FORMERR); + isc_buffer_forward(source, sregion.length); + return (mem_tobuffer(target, sregion.base, sregion.length)); +} + +static inline isc_result_t +towire_l32(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_l32); + REQUIRE(rdata->length == 6); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_l32(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_l32); + REQUIRE(rdata1->length == 6); + REQUIRE(rdata2->length == 6); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_l32(ARGS_FROMSTRUCT) { + dns_rdata_l32_t *l32 = source; + uint32_t n; + + REQUIRE(type == dns_rdatatype_l32); + REQUIRE(source != NULL); + REQUIRE(l32->common.rdtype == type); + REQUIRE(l32->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(l32->pref, target)); + n = ntohl(l32->l32.s_addr); + return (uint32_tobuffer(n, target)); +} + +static inline isc_result_t +tostruct_l32(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_l32_t *l32 = target; + uint32_t n; + + REQUIRE(rdata->type == dns_rdatatype_l32); + REQUIRE(target != NULL); + REQUIRE(rdata->length == 6); + + UNUSED(mctx); + + l32->common.rdclass = rdata->rdclass; + l32->common.rdtype = rdata->type; + ISC_LINK_INIT(&l32->common, link); + + dns_rdata_toregion(rdata, ®ion); + l32->pref = uint16_fromregion(®ion); + n = uint32_fromregion(®ion); + l32->l32.s_addr = htonl(n); + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_l32(ARGS_FREESTRUCT) { + dns_rdata_l32_t *l32 = source; + + REQUIRE(source != NULL); + REQUIRE(l32->common.rdtype == dns_rdatatype_l32); + + return; +} + +static inline isc_result_t +additionaldata_l32(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_l32); + REQUIRE(rdata->length == 6); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_l32(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_l32); + REQUIRE(rdata->length == 6); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_l32(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_l32); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_l32(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_l32); + REQUIRE(rdata->length == 6); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_l32(ARGS_COMPARE) { + return (compare_l32(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_L32_105_C */ diff --git a/lib/dns/rdata/generic/l32_105.h b/lib/dns/rdata/generic/l32_105.h new file mode 100644 index 0000000..3fca0f2 --- /dev/null +++ b/lib/dns/rdata/generic/l32_105.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_L32_105_H +#define GENERIC_L32_105_H 1 + +typedef struct dns_rdata_l32 { + dns_rdatacommon_t common; + uint16_t pref; + struct in_addr l32; +} dns_rdata_l32_t; + +#endif /* GENERIC_L32_105_H */ diff --git a/lib/dns/rdata/generic/l64_106.c b/lib/dns/rdata/generic/l64_106.c new file mode 100644 index 0000000..277c6a9 --- /dev/null +++ b/lib/dns/rdata/generic/l64_106.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_L64_106_C +#define RDATA_GENERIC_L64_106_C + +#include <string.h> + +#include <isc/net.h> + +#define RRTYPE_L64_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_l64(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char locator[NS_LOCATORSZ]; + + REQUIRE(type == dns_rdatatype_l64); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (locator_pton(DNS_AS_STR(token), locator) != 1) + RETTOK(DNS_R_SYNTAX); + return (mem_tobuffer(target, locator, NS_LOCATORSZ)); +} + +static inline isc_result_t +totext_l64(ARGS_TOTEXT) { + isc_region_t region; + char buf[sizeof("xxxx:xxxx:xxxx:xxxx")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_l64); + REQUIRE(rdata->length == 10); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + snprintf(buf, sizeof(buf), "%x:%x:%x:%x", + region.base[0]<<8 | region.base[1], + region.base[2]<<8 | region.base[3], + region.base[4]<<8 | region.base[5], + region.base[6]<<8 | region.base[7]); + return (str_totext(buf, target)); +} + +static inline isc_result_t +fromwire_l64(ARGS_FROMWIRE) { + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_l64); + + UNUSED(type); + UNUSED(options); + UNUSED(rdclass); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length != 10) + return (DNS_R_FORMERR); + isc_buffer_forward(source, sregion.length); + return (mem_tobuffer(target, sregion.base, sregion.length)); +} + +static inline isc_result_t +towire_l64(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_l64); + REQUIRE(rdata->length == 10); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_l64(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_l64); + REQUIRE(rdata1->length == 10); + REQUIRE(rdata2->length == 10); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_l64(ARGS_FROMSTRUCT) { + dns_rdata_l64_t *l64 = source; + + REQUIRE(type == dns_rdatatype_l64); + REQUIRE(source != NULL); + REQUIRE(l64->common.rdtype == type); + REQUIRE(l64->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(l64->pref, target)); + return (mem_tobuffer(target, l64->l64, sizeof(l64->l64))); +} + +static inline isc_result_t +tostruct_l64(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_l64_t *l64 = target; + + REQUIRE(rdata->type == dns_rdatatype_l64); + REQUIRE(target != NULL); + REQUIRE(rdata->length == 10); + + UNUSED(mctx); + + l64->common.rdclass = rdata->rdclass; + l64->common.rdtype = rdata->type; + ISC_LINK_INIT(&l64->common, link); + + dns_rdata_toregion(rdata, ®ion); + l64->pref = uint16_fromregion(®ion); + memmove(l64->l64, region.base, region.length); + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_l64(ARGS_FREESTRUCT) { + dns_rdata_l64_t *l64 = source; + + REQUIRE(source != NULL); + REQUIRE(l64->common.rdtype == dns_rdatatype_l64); + + return; +} + +static inline isc_result_t +additionaldata_l64(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_l64); + REQUIRE(rdata->length == 10); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_l64(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_l64); + REQUIRE(rdata->length == 10); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_l64(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_l64); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_l64(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_l64); + REQUIRE(rdata->length == 10); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_l64(ARGS_COMPARE) { + return (compare_l64(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_L64_106_C */ diff --git a/lib/dns/rdata/generic/l64_106.h b/lib/dns/rdata/generic/l64_106.h new file mode 100644 index 0000000..968a138 --- /dev/null +++ b/lib/dns/rdata/generic/l64_106.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_L64_106_H +#define GENERIC_L64_106_H 1 + +typedef struct dns_rdata_l64 { + dns_rdatacommon_t common; + uint16_t pref; + unsigned char l64[8]; +} dns_rdata_l64_t; + +#endif /* GENERIC_L64_106_H */ diff --git a/lib/dns/rdata/generic/loc_29.c b/lib/dns/rdata/generic/loc_29.c new file mode 100644 index 0000000..50c00ff --- /dev/null +++ b/lib/dns/rdata/generic/loc_29.c @@ -0,0 +1,811 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1876 */ + +#ifndef RDATA_GENERIC_LOC_29_C +#define RDATA_GENERIC_LOC_29_C + +#define RRTYPE_LOC_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_loc(ARGS_FROMTEXT) { + isc_token_t token; + int d1, m1, s1; + int d2, m2, s2; + unsigned char size; + unsigned char hp; + unsigned char vp; + unsigned char version; + bool east = false; + bool north = false; + long tmp; + long m; + long cm; + long poweroften[8] = { 1, 10, 100, 1000, + 10000, 100000, 1000000, 10000000 }; + int man; + int exp; + char *e; + int i; + unsigned long latitude; + unsigned long longitude; + unsigned long altitude; + + REQUIRE(type == dns_rdatatype_loc); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + + /* + * Defaults. + */ + m1 = s1 = 0; + m2 = s2 = 0; + size = 0x12; /* 1.00m */ + hp = 0x16; /* 10000.00 m */ + vp = 0x13; /* 10.00 m */ + version = 0; + + /* + * Degrees. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 90U) + RETTOK(ISC_R_RANGE); + d1 = (int)token.value.as_ulong; + /* + * Minutes. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcasecmp(DNS_AS_STR(token), "N") == 0) + north = true; + if (north || strcasecmp(DNS_AS_STR(token), "S") == 0) + goto getlong; + m1 = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + if (m1 < 0 || m1 > 59) + RETTOK(ISC_R_RANGE); + if (d1 == 90 && m1 != 0) + RETTOK(ISC_R_RANGE); + + /* + * Seconds. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcasecmp(DNS_AS_STR(token), "N") == 0) + north = true; + if (north || strcasecmp(DNS_AS_STR(token), "S") == 0) + goto getlong; + s1 = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0 && *e != '.') + RETTOK(DNS_R_SYNTAX); + if (s1 < 0 || s1 > 59) + RETTOK(ISC_R_RANGE); + if (*e == '.') { + const char *l; + e++; + for (i = 0; i < 3; i++) { + if (*e == 0) + break; + if ((tmp = decvalue(*e++)) < 0) + RETTOK(DNS_R_SYNTAX); + s1 *= 10; + s1 += tmp; + } + for (; i < 3; i++) + s1 *= 10; + l = e; + while (*e != 0) { + if (decvalue(*e++) < 0) + RETTOK(DNS_R_SYNTAX); + } + if (*l != '\0' && callbacks != NULL) { + const char *file = isc_lex_getsourcename(lexer); + unsigned long line = isc_lex_getsourceline(lexer); + + if (file == NULL) + file = "UNKNOWN"; + (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra " + "precision digits ignored", + "dns_rdata_fromtext", file, line, + DNS_AS_STR(token)); + } + } else + s1 *= 1000; + if (d1 == 90 && s1 != 0) + RETTOK(ISC_R_RANGE); + + /* + * Direction. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcasecmp(DNS_AS_STR(token), "N") == 0) + north = true; + if (!north && strcasecmp(DNS_AS_STR(token), "S") != 0) + RETTOK(DNS_R_SYNTAX); + + getlong: + /* + * Degrees. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 180U) + RETTOK(ISC_R_RANGE); + d2 = (int)token.value.as_ulong; + + /* + * Minutes. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcasecmp(DNS_AS_STR(token), "E") == 0) + east = true; + if (east || strcasecmp(DNS_AS_STR(token), "W") == 0) + goto getalt; + m2 = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + if (m2 < 0 || m2 > 59) + RETTOK(ISC_R_RANGE); + if (d2 == 180 && m2 != 0) + RETTOK(ISC_R_RANGE); + + /* + * Seconds. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcasecmp(DNS_AS_STR(token), "E") == 0) + east = true; + if (east || strcasecmp(DNS_AS_STR(token), "W") == 0) + goto getalt; + s2 = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0 && *e != '.') + RETTOK(DNS_R_SYNTAX); + if (s2 < 0 || s2 > 59) + RETTOK(ISC_R_RANGE); + if (*e == '.') { + const char *l; + e++; + for (i = 0; i < 3; i++) { + if (*e == 0) + break; + if ((tmp = decvalue(*e++)) < 0) + RETTOK(DNS_R_SYNTAX); + s2 *= 10; + s2 += tmp; + } + for (; i < 3; i++) + s2 *= 10; + l = e; + while (*e != 0) { + if (decvalue(*e++) < 0) + RETTOK(DNS_R_SYNTAX); + } + if (*l != '\0' && callbacks != NULL) { + const char *file = isc_lex_getsourcename(lexer); + unsigned long line = isc_lex_getsourceline(lexer); + + if (file == NULL) + file = "UNKNOWN"; + (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra " + "precision digits ignored", + "dns_rdata_fromtext", + file, line, DNS_AS_STR(token)); + } + } else + s2 *= 1000; + if (d2 == 180 && s2 != 0) + RETTOK(ISC_R_RANGE); + + /* + * Direction. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strcasecmp(DNS_AS_STR(token), "E") == 0) + east = true; + if (!east && strcasecmp(DNS_AS_STR(token), "W") != 0) + RETTOK(DNS_R_SYNTAX); + + getalt: + /* + * Altitude. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + m = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0 && *e != '.' && *e != 'm') + RETTOK(DNS_R_SYNTAX); + if (m < -100000 || m > 42849672) + RETTOK(ISC_R_RANGE); + cm = 0; + if (*e == '.') { + e++; + for (i = 0; i < 2; i++) { + if (*e == 0 || *e == 'm') + break; + if ((tmp = decvalue(*e++)) < 0) + return (DNS_R_SYNTAX); + cm *= 10; + if (m < 0) + cm -= tmp; + else + cm += tmp; + } + for (; i < 2; i++) + cm *= 10; + } + if (*e == 'm') + e++; + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + if (m == -100000 && cm != 0) + RETTOK(ISC_R_RANGE); + if (m == 42849672 && cm > 95) + RETTOK(ISC_R_RANGE); + /* + * Adjust base. + */ + altitude = m + 100000; + altitude *= 100; + altitude += cm; + + /* + * Size: optional. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + true)); + if (token.type == isc_tokentype_eol || + token.type == isc_tokentype_eof) { + isc_lex_ungettoken(lexer, &token); + goto encode; + } + m = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0 && *e != '.' && *e != 'm') + RETTOK(DNS_R_SYNTAX); + if (m < 0 || m > 90000000) + RETTOK(ISC_R_RANGE); + cm = 0; + if (*e == '.') { + e++; + for (i = 0; i < 2; i++) { + if (*e == 0 || *e == 'm') + break; + if ((tmp = decvalue(*e++)) < 0) + RETTOK(DNS_R_SYNTAX); + cm *= 10; + cm += tmp; + } + for (; i < 2; i++) + cm *= 10; + } + if (*e == 'm') + e++; + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + /* + * We don't just multiply out as we will overflow. + */ + if (m > 0) { + for (exp = 0; exp < 7; exp++) + if (m < poweroften[exp+1]) + break; + man = m / poweroften[exp]; + exp += 2; + } else { + if (cm >= 10) { + man = cm / 10; + exp = 1; + } else { + man = cm; + exp = 0; + } + } + size = (man << 4) + exp; + + /* + * Horizontal precision: optional. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + true)); + if (token.type == isc_tokentype_eol || + token.type == isc_tokentype_eof) { + isc_lex_ungettoken(lexer, &token); + goto encode; + } + m = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0 && *e != '.' && *e != 'm') + RETTOK(DNS_R_SYNTAX); + if (m < 0 || m > 90000000) + RETTOK(ISC_R_RANGE); + cm = 0; + if (*e == '.') { + e++; + for (i = 0; i < 2; i++) { + if (*e == 0 || *e == 'm') + break; + if ((tmp = decvalue(*e++)) < 0) + RETTOK(DNS_R_SYNTAX); + cm *= 10; + cm += tmp; + } + for (; i < 2; i++) + cm *= 10; + } + if (*e == 'm') + e++; + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + /* + * We don't just multiply out as we will overflow. + */ + if (m > 0) { + for (exp = 0; exp < 7; exp++) + if (m < poweroften[exp+1]) + break; + man = m / poweroften[exp]; + exp += 2; + } else if (cm >= 10) { + man = cm / 10; + exp = 1; + } else { + man = cm; + exp = 0; + } + hp = (man << 4) + exp; + + /* + * Vertical precision: optional. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + true)); + if (token.type == isc_tokentype_eol || + token.type == isc_tokentype_eof) { + isc_lex_ungettoken(lexer, &token); + goto encode; + } + m = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0 && *e != '.' && *e != 'm') + RETTOK(DNS_R_SYNTAX); + if (m < 0 || m > 90000000) + RETTOK(ISC_R_RANGE); + cm = 0; + if (*e == '.') { + e++; + for (i = 0; i < 2; i++) { + if (*e == 0 || *e == 'm') + break; + if ((tmp = decvalue(*e++)) < 0) + RETTOK(DNS_R_SYNTAX); + cm *= 10; + cm += tmp; + } + for (; i < 2; i++) + cm *= 10; + } + if (*e == 'm') + e++; + if (*e != 0) + RETTOK(DNS_R_SYNTAX); + /* + * We don't just multiply out as we will overflow. + */ + if (m > 0) { + for (exp = 0; exp < 7; exp++) + if (m < poweroften[exp+1]) + break; + man = m / poweroften[exp]; + exp += 2; + } else if (cm >= 10) { + man = cm / 10; + exp = 1; + } else { + man = cm; + exp = 0; + } + vp = (man << 4) + exp; + + encode: + RETERR(mem_tobuffer(target, &version, 1)); + RETERR(mem_tobuffer(target, &size, 1)); + RETERR(mem_tobuffer(target, &hp, 1)); + RETERR(mem_tobuffer(target, &vp, 1)); + if (north) + latitude = 0x80000000 + ( d1 * 3600 + m1 * 60 ) * 1000 + s1; + else + latitude = 0x80000000 - ( d1 * 3600 + m1 * 60 ) * 1000 - s1; + RETERR(uint32_tobuffer(latitude, target)); + + if (east) + longitude = 0x80000000 + ( d2 * 3600 + m2 * 60 ) * 1000 + s2; + else + longitude = 0x80000000 - ( d2 * 3600 + m2 * 60 ) * 1000 - s2; + RETERR(uint32_tobuffer(longitude, target)); + + return (uint32_tobuffer(altitude, target)); +} + +static inline isc_result_t +totext_loc(ARGS_TOTEXT) { + int d1, m1, s1, fs1; + int d2, m2, s2, fs2; + unsigned long latitude; + unsigned long longitude; + unsigned long altitude; + bool north; + bool east; + bool below; + isc_region_t sr; + char buf[sizeof("89 59 59.999 N 179 59 59.999 E " + "-42849672.95m 90000000m 90000000m 90000000m")]; + char sbuf[sizeof("90000000m")]; + char hbuf[sizeof("90000000m")]; + char vbuf[sizeof("90000000m")]; + unsigned char size, hp, vp; + unsigned long poweroften[8] = { 1, 10, 100, 1000, + 10000, 100000, 1000000, 10000000 }; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_loc); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + if (sr.base[0] != 0) + return (ISC_R_NOTIMPLEMENTED); + + REQUIRE(rdata->length == 16); + + size = sr.base[1]; + INSIST((size&0x0f) < 10 && (size>>4) < 10); + if ((size&0x0f)> 1) { + snprintf(sbuf, sizeof(sbuf), + "%lum", (size>>4) * poweroften[(size&0x0f)-2]); + } else { + snprintf(sbuf, sizeof(sbuf), + "0.%02lum", (size>>4) * poweroften[(size&0x0f)]); + } + hp = sr.base[2]; + INSIST((hp&0x0f) < 10 && (hp>>4) < 10); + if ((hp&0x0f)> 1) { + snprintf(hbuf, sizeof(hbuf), + "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]); + } else { + snprintf(hbuf, sizeof(hbuf), + "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]); + } + vp = sr.base[3]; + INSIST((vp&0x0f) < 10 && (vp>>4) < 10); + if ((vp&0x0f)> 1) { + snprintf(vbuf, sizeof(vbuf), + "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]); + } else { + snprintf(vbuf, sizeof(vbuf), + "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]); + } + isc_region_consume(&sr, 4); + + latitude = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + if (latitude >= 0x80000000) { + north = true; + latitude -= 0x80000000; + } else { + north = false; + latitude = 0x80000000 - latitude; + } + fs1 = (int)(latitude % 1000); + latitude /= 1000; + s1 = (int)(latitude % 60); + latitude /= 60; + m1 = (int)(latitude % 60); + latitude /= 60; + d1 = (int)latitude; + INSIST(latitude <= 90U); + + longitude = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + if (longitude >= 0x80000000) { + east = true; + longitude -= 0x80000000; + } else { + east = false; + longitude = 0x80000000 - longitude; + } + fs2 = (int)(longitude % 1000); + longitude /= 1000; + s2 = (int)(longitude % 60); + longitude /= 60; + m2 = (int)(longitude % 60); + longitude /= 60; + d2 = (int)longitude; + INSIST(longitude <= 180U); + + altitude = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + if (altitude < 10000000U) { + below = true; + altitude = 10000000 - altitude; + } else { + below =false; + altitude -= 10000000; + } + + snprintf(buf, sizeof(buf), + "%d %d %d.%03d %s %d %d %d.%03d %s %s%lu.%02lum %s %s %s", + d1, m1, s1, fs1, north ? "N" : "S", + d2, m2, s2, fs2, east ? "E" : "W", + below ? "-" : "", altitude/100, altitude % 100, + sbuf, hbuf, vbuf); + + return (str_totext(buf, target)); +} + +static inline isc_result_t +fromwire_loc(ARGS_FROMWIRE) { + isc_region_t sr; + unsigned char c; + unsigned long latitude; + unsigned long longitude; + + REQUIRE(type == dns_rdatatype_loc); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + if (sr.base[0] != 0) { + /* Treat as unknown. */ + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); + } + if (sr.length < 16) + return (ISC_R_UNEXPECTEDEND); + + /* + * Size. + */ + c = sr.base[1]; + if (c != 0) + if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0) + return (ISC_R_RANGE); + + /* + * Horizontal precision. + */ + c = sr.base[2]; + if (c != 0) + if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0) + return (ISC_R_RANGE); + + /* + * Vertical precision. + */ + c = sr.base[3]; + if (c != 0) + if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0) + return (ISC_R_RANGE); + isc_region_consume(&sr, 4); + + /* + * Latitude. + */ + latitude = uint32_fromregion(&sr); + if (latitude < (0x80000000UL - 90 * 3600000) || + latitude > (0x80000000UL + 90 * 3600000)) + return (ISC_R_RANGE); + isc_region_consume(&sr, 4); + + /* + * Longitude. + */ + longitude = uint32_fromregion(&sr); + if (longitude < (0x80000000UL - 180 * 3600000) || + longitude > (0x80000000UL + 180 * 3600000)) + return (ISC_R_RANGE); + + /* + * Altitude. + * All values possible. + */ + + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, 16); + return (mem_tobuffer(target, sr.base, 16)); +} + +static inline isc_result_t +towire_loc(ARGS_TOWIRE) { + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_loc); + REQUIRE(rdata->length != 0); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_loc(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_loc); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_loc(ARGS_FROMSTRUCT) { + dns_rdata_loc_t *loc = source; + uint8_t c; + + REQUIRE(type == dns_rdatatype_loc); + REQUIRE(source != NULL); + REQUIRE(loc->common.rdtype == type); + REQUIRE(loc->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + if (loc->v.v0.version != 0) + return (ISC_R_NOTIMPLEMENTED); + RETERR(uint8_tobuffer(loc->v.v0.version, target)); + + c = loc->v.v0.size; + if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0) + return (ISC_R_RANGE); + RETERR(uint8_tobuffer(loc->v.v0.size, target)); + + c = loc->v.v0.horizontal; + if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0) + return (ISC_R_RANGE); + RETERR(uint8_tobuffer(loc->v.v0.horizontal, target)); + + c = loc->v.v0.vertical; + if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0) + return (ISC_R_RANGE); + RETERR(uint8_tobuffer(loc->v.v0.vertical, target)); + + if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) || + loc->v.v0.latitude > (0x80000000UL + 90 * 3600000)) + return (ISC_R_RANGE); + RETERR(uint32_tobuffer(loc->v.v0.latitude, target)); + + if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) || + loc->v.v0.longitude > (0x80000000UL + 180 * 3600000)) + return (ISC_R_RANGE); + RETERR(uint32_tobuffer(loc->v.v0.longitude, target)); + return (uint32_tobuffer(loc->v.v0.altitude, target)); +} + +static inline isc_result_t +tostruct_loc(ARGS_TOSTRUCT) { + dns_rdata_loc_t *loc = target; + isc_region_t r; + uint8_t version; + + REQUIRE(rdata->type == dns_rdatatype_loc); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + UNUSED(mctx); + + dns_rdata_toregion(rdata, &r); + version = uint8_fromregion(&r); + if (version != 0) + return (ISC_R_NOTIMPLEMENTED); + + loc->common.rdclass = rdata->rdclass; + loc->common.rdtype = rdata->type; + ISC_LINK_INIT(&loc->common, link); + + loc->v.v0.version = version; + isc_region_consume(&r, 1); + loc->v.v0.size = uint8_fromregion(&r); + isc_region_consume(&r, 1); + loc->v.v0.horizontal = uint8_fromregion(&r); + isc_region_consume(&r, 1); + loc->v.v0.vertical = uint8_fromregion(&r); + isc_region_consume(&r, 1); + loc->v.v0.latitude = uint32_fromregion(&r); + isc_region_consume(&r, 4); + loc->v.v0.longitude = uint32_fromregion(&r); + isc_region_consume(&r, 4); + loc->v.v0.altitude = uint32_fromregion(&r); + isc_region_consume(&r, 4); + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_loc(ARGS_FREESTRUCT) { + dns_rdata_loc_t *loc = source; + + REQUIRE(source != NULL); + REQUIRE(loc->common.rdtype == dns_rdatatype_loc); + + UNUSED(source); + UNUSED(loc); +} + +static inline isc_result_t +additionaldata_loc(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_loc); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_loc(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_loc); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_loc(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_loc); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_loc(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_loc); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_loc(ARGS_COMPARE) { + return (compare_loc(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_LOC_29_C */ diff --git a/lib/dns/rdata/generic/loc_29.h b/lib/dns/rdata/generic/loc_29.h new file mode 100644 index 0000000..c879581 --- /dev/null +++ b/lib/dns/rdata/generic/loc_29.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_LOC_29_H +#define GENERIC_LOC_29_H 1 + + +/*! + * \brief Per RFC1876 */ + +typedef struct dns_rdata_loc_0 { + uint8_t version; /* must be first and zero */ + uint8_t size; + uint8_t horizontal; + uint8_t vertical; + uint32_t latitude; + uint32_t longitude; + uint32_t altitude; +} dns_rdata_loc_0_t; + +typedef struct dns_rdata_loc { + dns_rdatacommon_t common; + union { + dns_rdata_loc_0_t v0; + } v; +} dns_rdata_loc_t; + +#endif /* GENERIC_LOC_29_H */ diff --git a/lib/dns/rdata/generic/lp_107.c b/lib/dns/rdata/generic/lp_107.c new file mode 100644 index 0000000..49bc799 --- /dev/null +++ b/lib/dns/rdata/generic/lp_107.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_LP_107_C +#define RDATA_GENERIC_LP_107_C + +#include <string.h> + +#include <isc/net.h> + +#define RRTYPE_LP_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_lp(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_lp); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + return (dns_name_fromtext(&name, &buffer, origin, options, target)); +} + +static inline isc_result_t +totext_lp(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_lp); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_lp(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_lp); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length < 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sregion.base, 2)); + isc_buffer_forward(source, 2); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_lp(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_lp); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_lp(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_lp); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_lp(ARGS_FROMSTRUCT) { + dns_rdata_lp_t *lp = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_lp); + REQUIRE(source != NULL); + REQUIRE(lp->common.rdtype == type); + REQUIRE(lp->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(lp->pref, target)); + dns_name_toregion(&lp->lp, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_lp(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_lp_t *lp = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_lp); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + lp->common.rdclass = rdata->rdclass; + lp->common.rdtype = rdata->type; + ISC_LINK_INIT(&lp->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + lp->pref = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + dns_name_init(&lp->lp, NULL); + RETERR(name_duporclone(&name, mctx, &lp->lp)); + lp->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_lp(ARGS_FREESTRUCT) { + dns_rdata_lp_t *lp = source; + + REQUIRE(source != NULL); + REQUIRE(lp->common.rdtype == dns_rdatatype_lp); + + if (lp->mctx == NULL) + return; + + dns_name_free(&lp->lp, lp->mctx); + lp->mctx = NULL; +} + +static inline isc_result_t +additionaldata_lp(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_lp); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + + result = (add)(arg, &name, dns_rdatatype_l32); + if (result != ISC_R_SUCCESS) + return (result); + return ((add)(arg, &name, dns_rdatatype_l64)); +} + +static inline isc_result_t +digest_lp(ARGS_DIGEST) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_lp); + + dns_rdata_toregion(rdata, ®ion); + return ((digest)(arg, ®ion)); +} + +static inline bool +checkowner_lp(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_lp); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(name); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_lp(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_lp); + + UNUSED(bad); + UNUSED(owner); + + return (true); +} + +static inline int +casecompare_lp(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_lp); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + order = memcmp(rdata1->data, rdata2->data, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 2); + isc_region_consume(®ion2, 2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +#endif /* RDATA_GENERIC_LP_107_C */ diff --git a/lib/dns/rdata/generic/lp_107.h b/lib/dns/rdata/generic/lp_107.h new file mode 100644 index 0000000..4ccffac --- /dev/null +++ b/lib/dns/rdata/generic/lp_107.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_LP_107_H +#define GENERIC_LP_107_H 1 + +typedef struct dns_rdata_lp { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t pref; + dns_name_t lp; +} dns_rdata_lp_t; + +#endif /* GENERIC_LP_107_H */ diff --git a/lib/dns/rdata/generic/mb_7.c b/lib/dns/rdata/generic/mb_7.c new file mode 100644 index 0000000..299f89d --- /dev/null +++ b/lib/dns/rdata/generic/mb_7.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MB_7_C +#define RDATA_GENERIC_MB_7_C + +#define RRTYPE_MB_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_mb(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_mb); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_mb(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_mb); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_mb(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_mb); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_mb(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mb); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_mb(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_mb); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_mb(ARGS_FROMSTRUCT) { + dns_rdata_mb_t *mb = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_mb); + REQUIRE(source != NULL); + REQUIRE(mb->common.rdtype == type); + REQUIRE(mb->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&mb->mb, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_mb(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_mb_t *mb = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mb); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + mb->common.rdclass = rdata->rdclass; + mb->common.rdtype = rdata->type; + ISC_LINK_INIT(&mb->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&mb->mb, NULL); + RETERR(name_duporclone(&name, mctx, &mb->mb)); + mb->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_mb(ARGS_FREESTRUCT) { + dns_rdata_mb_t *mb = source; + + REQUIRE(source != NULL); + + if (mb->mctx == NULL) + return; + + dns_name_free(&mb->mb, mb->mctx); + mb->mctx = NULL; +} + +static inline isc_result_t +additionaldata_mb(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mb); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_mb(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mb); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_mb(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_mb); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (dns_name_ismailbox(name)); +} + +static inline bool +checknames_mb(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_mb); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_mb(ARGS_COMPARE) { + return (compare_mb(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MB_7_C */ diff --git a/lib/dns/rdata/generic/mb_7.h b/lib/dns/rdata/generic/mb_7.h new file mode 100644 index 0000000..59f4115 --- /dev/null +++ b/lib/dns/rdata/generic/mb_7.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MB_7_H +#define GENERIC_MB_7_H 1 + + +typedef struct dns_rdata_mb { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t mb; +} dns_rdata_mb_t; + +#endif /* GENERIC_MB_7_H */ diff --git a/lib/dns/rdata/generic/md_3.c b/lib/dns/rdata/generic/md_3.c new file mode 100644 index 0000000..9eefe69 --- /dev/null +++ b/lib/dns/rdata/generic/md_3.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MD_3_C +#define RDATA_GENERIC_MD_3_C + +#define RRTYPE_MD_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_md(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_md); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_md(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_md); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_md(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_md); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_md(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_md); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_md(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_md); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_md(ARGS_FROMSTRUCT) { + dns_rdata_md_t *md = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_md); + REQUIRE(source != NULL); + REQUIRE(md->common.rdtype == type); + REQUIRE(md->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&md->md, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_md(ARGS_TOSTRUCT) { + dns_rdata_md_t *md = target; + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_md); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + md->common.rdclass = rdata->rdclass; + md->common.rdtype = rdata->type; + ISC_LINK_INIT(&md->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, &r); + dns_name_fromregion(&name, &r); + dns_name_init(&md->md, NULL); + RETERR(name_duporclone(&name, mctx, &md->md)); + md->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_md(ARGS_FREESTRUCT) { + dns_rdata_md_t *md = source; + + REQUIRE(source != NULL); + REQUIRE(md->common.rdtype == dns_rdatatype_md); + + if (md->mctx == NULL) + return; + + dns_name_free(&md->md, md->mctx); + md->mctx = NULL; +} + +static inline isc_result_t +additionaldata_md(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_md); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_md(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_md); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_md(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_md); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_md(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_md); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_md(ARGS_COMPARE) { + return (compare_md(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MD_3_C */ diff --git a/lib/dns/rdata/generic/md_3.h b/lib/dns/rdata/generic/md_3.h new file mode 100644 index 0000000..396c3c9 --- /dev/null +++ b/lib/dns/rdata/generic/md_3.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MD_3_H +#define GENERIC_MD_3_H 1 + + +typedef struct dns_rdata_md { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t md; +} dns_rdata_md_t; + + +#endif /* GENERIC_MD_3_H */ diff --git a/lib/dns/rdata/generic/mf_4.c b/lib/dns/rdata/generic/mf_4.c new file mode 100644 index 0000000..5965981 --- /dev/null +++ b/lib/dns/rdata/generic/mf_4.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MF_4_C +#define RDATA_GENERIC_MF_4_C + +#define RRTYPE_MF_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_mf(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_mf); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_mf(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_mf); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_mf(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_mf); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_mf(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mf); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_mf(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_mf); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_mf(ARGS_FROMSTRUCT) { + dns_rdata_mf_t *mf = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_mf); + REQUIRE(source != NULL); + REQUIRE(mf->common.rdtype == type); + REQUIRE(mf->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&mf->mf, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_mf(ARGS_TOSTRUCT) { + dns_rdata_mf_t *mf = target; + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mf); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + mf->common.rdclass = rdata->rdclass; + mf->common.rdtype = rdata->type; + ISC_LINK_INIT(&mf->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, &r); + dns_name_fromregion(&name, &r); + dns_name_init(&mf->mf, NULL); + RETERR(name_duporclone(&name, mctx, &mf->mf)); + mf->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_mf(ARGS_FREESTRUCT) { + dns_rdata_mf_t *mf = source; + + REQUIRE(source != NULL); + REQUIRE(mf->common.rdtype == dns_rdatatype_mf); + + if (mf->mctx == NULL) + return; + dns_name_free(&mf->mf, mf->mctx); + mf->mctx = NULL; +} + +static inline isc_result_t +additionaldata_mf(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mf); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_mf(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mf); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_mf(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_mf); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_mf(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_mf); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_mf(ARGS_COMPARE) { + return (compare_mf(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MF_4_C */ diff --git a/lib/dns/rdata/generic/mf_4.h b/lib/dns/rdata/generic/mf_4.h new file mode 100644 index 0000000..d882155 --- /dev/null +++ b/lib/dns/rdata/generic/mf_4.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MF_4_H +#define GENERIC_MF_4_H 1 + + +typedef struct dns_rdata_mf { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t mf; +} dns_rdata_mf_t; + +#endif /* GENERIC_MF_4_H */ diff --git a/lib/dns/rdata/generic/mg_8.c b/lib/dns/rdata/generic/mg_8.c new file mode 100644 index 0000000..45a38ce --- /dev/null +++ b/lib/dns/rdata/generic/mg_8.c @@ -0,0 +1,226 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MG_8_C +#define RDATA_GENERIC_MG_8_C + +#define RRTYPE_MG_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_mg(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_mg); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_mg(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_mg); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_mg(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_mg); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_mg(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mg); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_mg(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_mg); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_mg(ARGS_FROMSTRUCT) { + dns_rdata_mg_t *mg = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_mg); + REQUIRE(source != NULL); + REQUIRE(mg->common.rdtype == type); + REQUIRE(mg->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&mg->mg, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_mg(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_mg_t *mg = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mg); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + mg->common.rdclass = rdata->rdclass; + mg->common.rdtype = rdata->type; + ISC_LINK_INIT(&mg->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&mg->mg, NULL); + RETERR(name_duporclone(&name, mctx, &mg->mg)); + mg->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_mg(ARGS_FREESTRUCT) { + dns_rdata_mg_t *mg = source; + + REQUIRE(source != NULL); + REQUIRE(mg->common.rdtype == dns_rdatatype_mg); + + if (mg->mctx == NULL) + return; + dns_name_free(&mg->mg, mg->mctx); + mg->mctx = NULL; +} + +static inline isc_result_t +additionaldata_mg(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_mg); + + UNUSED(add); + UNUSED(arg); + UNUSED(rdata); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_mg(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mg); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_mg(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_mg); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (dns_name_ismailbox(name)); +} + +static inline bool +checknames_mg(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_mg); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_mg(ARGS_COMPARE) { + return (compare_mg(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MG_8_C */ diff --git a/lib/dns/rdata/generic/mg_8.h b/lib/dns/rdata/generic/mg_8.h new file mode 100644 index 0000000..0e0380e --- /dev/null +++ b/lib/dns/rdata/generic/mg_8.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MG_8_H +#define GENERIC_MG_8_H 1 + + +typedef struct dns_rdata_mg { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t mg; +} dns_rdata_mg_t; + +#endif /* GENERIC_MG_8_H */ diff --git a/lib/dns/rdata/generic/minfo_14.c b/lib/dns/rdata/generic/minfo_14.c new file mode 100644 index 0000000..23506e2 --- /dev/null +++ b/lib/dns/rdata/generic/minfo_14.c @@ -0,0 +1,321 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MINFO_14_C +#define RDATA_GENERIC_MINFO_14_C + +#define RRTYPE_MINFO_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_minfo(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + int i; + bool ok; + + REQUIRE(type == dns_rdatatype_minfo); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + if (origin == NULL) + origin = dns_rootname; + + for (i = 0; i < 2; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, + options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ismailbox(&name); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_minfo(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t rmail; + dns_name_t email; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_minfo); + REQUIRE(rdata->length != 0); + + dns_name_init(&rmail, NULL); + dns_name_init(&email, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + + dns_name_fromregion(&rmail, ®ion); + isc_region_consume(®ion, rmail.length); + + dns_name_fromregion(&email, ®ion); + isc_region_consume(®ion, email.length); + + sub = name_prefix(&rmail, tctx->origin, &prefix); + + RETERR(dns_name_totext(&prefix, sub, target)); + + RETERR(str_totext(" ", target)); + + sub = name_prefix(&email, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_minfo(ARGS_FROMWIRE) { + dns_name_t rmail; + dns_name_t email; + + REQUIRE(type == dns_rdatatype_minfo); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&rmail, NULL); + dns_name_init(&email, NULL); + + RETERR(dns_name_fromwire(&rmail, source, dctx, options, target)); + return (dns_name_fromwire(&email, source, dctx, options, target)); +} + +static inline isc_result_t +towire_minfo(ARGS_TOWIRE) { + isc_region_t region; + dns_name_t rmail; + dns_name_t email; + dns_offsets_t roffsets; + dns_offsets_t eoffsets; + + REQUIRE(rdata->type == dns_rdatatype_minfo); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&rmail, roffsets); + dns_name_init(&email, eoffsets); + + dns_rdata_toregion(rdata, ®ion); + + dns_name_fromregion(&rmail, ®ion); + isc_region_consume(®ion, name_length(&rmail)); + + RETERR(dns_name_towire(&rmail, cctx, target)); + + dns_name_fromregion(&rmail, ®ion); + isc_region_consume(®ion, rmail.length); + + return (dns_name_towire(&rmail, cctx, target)); +} + +static inline int +compare_minfo(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_minfo); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + return (order); +} + +static inline isc_result_t +fromstruct_minfo(ARGS_FROMSTRUCT) { + dns_rdata_minfo_t *minfo = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_minfo); + REQUIRE(source != NULL); + REQUIRE(minfo->common.rdtype == type); + REQUIRE(minfo->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&minfo->rmailbox, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + dns_name_toregion(&minfo->emailbox, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_minfo(ARGS_TOSTRUCT) { + dns_rdata_minfo_t *minfo = target; + isc_region_t region; + dns_name_t name; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_minfo); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + minfo->common.rdclass = rdata->rdclass; + minfo->common.rdtype = rdata->type; + ISC_LINK_INIT(&minfo->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&minfo->rmailbox, NULL); + RETERR(name_duporclone(&name, mctx, &minfo->rmailbox)); + isc_region_consume(®ion, name_length(&name)); + + dns_name_fromregion(&name, ®ion); + dns_name_init(&minfo->emailbox, NULL); + result = name_duporclone(&name, mctx, &minfo->emailbox); + if (result != ISC_R_SUCCESS) + goto cleanup; + minfo->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&minfo->rmailbox, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_minfo(ARGS_FREESTRUCT) { + dns_rdata_minfo_t *minfo = source; + + REQUIRE(source != NULL); + REQUIRE(minfo->common.rdtype == dns_rdatatype_minfo); + + if (minfo->mctx == NULL) + return; + + dns_name_free(&minfo->rmailbox, minfo->mctx); + dns_name_free(&minfo->emailbox, minfo->mctx); + minfo->mctx = NULL; +} + +static inline isc_result_t +additionaldata_minfo(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_minfo); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_minfo(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_minfo); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + result = dns_name_digest(&name, digest, arg); + if (result != ISC_R_SUCCESS) + return (result); + isc_region_consume(&r, name_length(&name)); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_minfo(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_minfo); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_minfo(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_minfo); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ismailbox(&name)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + isc_region_consume(®ion, name_length(&name)); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ismailbox(&name)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_minfo(ARGS_COMPARE) { + return (compare_minfo(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MINFO_14_C */ diff --git a/lib/dns/rdata/generic/minfo_14.h b/lib/dns/rdata/generic/minfo_14.h new file mode 100644 index 0000000..10080fb --- /dev/null +++ b/lib/dns/rdata/generic/minfo_14.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MINFO_14_H +#define GENERIC_MINFO_14_H 1 + + +typedef struct dns_rdata_minfo { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t rmailbox; + dns_name_t emailbox; +} dns_rdata_minfo_t; + +#endif /* GENERIC_MINFO_14_H */ diff --git a/lib/dns/rdata/generic/mr_9.c b/lib/dns/rdata/generic/mr_9.c new file mode 100644 index 0000000..edea7b1 --- /dev/null +++ b/lib/dns/rdata/generic/mr_9.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MR_9_C +#define RDATA_GENERIC_MR_9_C + +#define RRTYPE_MR_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_mr(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_mr); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_mr(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_mr); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_mr(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_mr); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_mr(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mr); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_mr(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_mr); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_mr(ARGS_FROMSTRUCT) { + dns_rdata_mr_t *mr = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_mr); + REQUIRE(source != NULL); + REQUIRE(mr->common.rdtype == type); + REQUIRE(mr->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&mr->mr, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_mr(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_mr_t *mr = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mr); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + mr->common.rdclass = rdata->rdclass; + mr->common.rdtype = rdata->type; + ISC_LINK_INIT(&mr->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&mr->mr, NULL); + RETERR(name_duporclone(&name, mctx, &mr->mr)); + mr->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_mr(ARGS_FREESTRUCT) { + dns_rdata_mr_t *mr = source; + + REQUIRE(source != NULL); + REQUIRE(mr->common.rdtype == dns_rdatatype_mr); + + if (mr->mctx == NULL) + return; + dns_name_free(&mr->mr, mr->mctx); + mr->mctx = NULL; +} + +static inline isc_result_t +additionaldata_mr(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_mr); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_mr(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mr); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_mr(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_mr); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_mr(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_mr); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_mr(ARGS_COMPARE) { + return (compare_mr(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MR_9_C */ diff --git a/lib/dns/rdata/generic/mr_9.h b/lib/dns/rdata/generic/mr_9.h new file mode 100644 index 0000000..888a82f --- /dev/null +++ b/lib/dns/rdata/generic/mr_9.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MR_9_H +#define GENERIC_MR_9_H 1 + + +typedef struct dns_rdata_mr { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t mr; +} dns_rdata_mr_t; + +#endif /* GENERIC_MR_9_H */ diff --git a/lib/dns/rdata/generic/mx_15.c b/lib/dns/rdata/generic/mx_15.c new file mode 100644 index 0000000..c333740 --- /dev/null +++ b/lib/dns/rdata/generic/mx_15.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_MX_15_C +#define RDATA_GENERIC_MX_15_C + +#include <string.h> + +#include <isc/net.h> + +#include <dns/fixedname.h> + +#define RRTYPE_MX_ATTRIBUTES (0) + +static bool +check_mx(isc_token_t *token) { + char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")]; + struct in_addr addr; + struct in6_addr addr6; + + if (strlcpy(tmp, DNS_AS_STR(*token), sizeof(tmp)) >= sizeof(tmp)) + return (true); + + if (tmp[strlen(tmp) - 1] == '.') + tmp[strlen(tmp) - 1] = '\0'; + if (inet_aton(tmp, &addr) == 1 || + inet_pton(AF_INET6, tmp, &addr6) == 1) + return (false); + + return (true); +} + +static inline isc_result_t +fromtext_mx(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + bool ok; + + REQUIRE(type == dns_rdatatype_mx); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + ok = true; + if ((options & DNS_RDATA_CHECKMX) != 0) + ok = check_mx(&token); + if (!ok && (options & DNS_RDATA_CHECKMXFAIL) != 0) + RETTOK(DNS_R_MXISADDRESS); + if (!ok && callbacks != NULL) + warn_badmx(&token, lexer, callbacks); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_mx(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_mx); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_mx(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_mx); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length < 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sregion.base, 2)); + isc_buffer_forward(source, 2); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_mx(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mx); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_rdata_toregion(rdata, ®ion); + RETERR(mem_tobuffer(target, region.base, 2)); + isc_region_consume(®ion, 2); + + dns_name_init(&name, offsets); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_mx(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_mx); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + order = memcmp(rdata1->data, rdata2->data, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 2); + isc_region_consume(®ion2, 2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_mx(ARGS_FROMSTRUCT) { + dns_rdata_mx_t *mx = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_mx); + REQUIRE(source != NULL); + REQUIRE(mx->common.rdtype == type); + REQUIRE(mx->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(mx->pref, target)); + dns_name_toregion(&mx->mx, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_mx(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_mx_t *mx = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mx); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + mx->common.rdclass = rdata->rdclass; + mx->common.rdtype = rdata->type; + ISC_LINK_INIT(&mx->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + mx->pref = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + dns_name_init(&mx->mx, NULL); + RETERR(name_duporclone(&name, mctx, &mx->mx)); + mx->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_mx(ARGS_FREESTRUCT) { + dns_rdata_mx_t *mx = source; + + REQUIRE(source != NULL); + REQUIRE(mx->common.rdtype == dns_rdatatype_mx); + + if (mx->mctx == NULL) + return; + + dns_name_free(&mx->mx, mx->mctx); + mx->mctx = NULL; +} + +static unsigned char port25_offset[] = { 0, 3 }; +static unsigned char port25_ndata[] = "\003_25\004_tcp"; +static dns_name_t port25 = + DNS_NAME_INITNONABSOLUTE(port25_ndata, port25_offset); + +static inline isc_result_t +additionaldata_mx(ARGS_ADDLDATA) { + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_mx); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + + if (dns_name_equal(&name, dns_rootname)) + return (ISC_R_SUCCESS); + + result = (add)(arg, &name, dns_rdatatype_a); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&fixed); + result = dns_name_concatenate(&port25, &name, + dns_fixedname_name(&fixed), NULL); + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + + return ((add)(arg, dns_fixedname_name(&fixed), dns_rdatatype_tlsa)); +} + +static inline isc_result_t +digest_mx(ARGS_DIGEST) { + isc_region_t r1, r2; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mx); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + isc_region_consume(&r2, 2); + r1.length = 2; + RETERR((digest)(arg, &r1)); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_mx(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_mx); + + UNUSED(type); + UNUSED(rdclass); + + return (dns_name_ishostname(name, wildcard)); +} + +static inline bool +checknames_mx(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_mx); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_mx(ARGS_COMPARE) { + return (compare_mx(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_MX_15_C */ diff --git a/lib/dns/rdata/generic/mx_15.h b/lib/dns/rdata/generic/mx_15.h new file mode 100644 index 0000000..ed96beb --- /dev/null +++ b/lib/dns/rdata/generic/mx_15.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_MX_15_H +#define GENERIC_MX_15_H 1 + + +typedef struct dns_rdata_mx { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t pref; + dns_name_t mx; +} dns_rdata_mx_t; + +#endif /* GENERIC_MX_15_H */ diff --git a/lib/dns/rdata/generic/naptr_35.c b/lib/dns/rdata/generic/naptr_35.c new file mode 100644 index 0000000..80c8f16 --- /dev/null +++ b/lib/dns/rdata/generic/naptr_35.c @@ -0,0 +1,662 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2915 */ + +#ifndef RDATA_GENERIC_NAPTR_35_C +#define RDATA_GENERIC_NAPTR_35_C + +#define RRTYPE_NAPTR_ATTRIBUTES (0) + +#include <isc/regex.h> + +/* + * Check the wire format of the Regexp field. + * Don't allow embeded NUL's. + */ +static inline isc_result_t +txt_valid_regex(const unsigned char *txt) { + unsigned int nsub = 0; + char regex[256]; + char *cp; + bool flags = false; + bool replace = false; + unsigned char c; + unsigned char delim; + unsigned int len; + int n; + + len = *txt++; + if (len == 0U) + return (ISC_R_SUCCESS); + + delim = *txt++; + len--; + + /* + * Digits, backslash and flags can't be delimiters. + */ + switch (delim) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '\\': case 'i': case 0: + return (DNS_R_SYNTAX); + } + + cp = regex; + while (len-- > 0) { + c = *txt++; + if (c == 0) + return (DNS_R_SYNTAX); + if (c == delim && !replace) { + replace = true; + continue; + } else if (c == delim && !flags) { + flags = true; + continue; + } else if (c == delim) + return (DNS_R_SYNTAX); + /* + * Flags are not escaped. + */ + if (flags) { + switch (c) { + case 'i': + continue; + default: + return (DNS_R_SYNTAX); + } + } + if (!replace) + *cp++ = c; + if (c == '\\') { + if (len == 0) + return (DNS_R_SYNTAX); + c = *txt++; + if (c == 0) + return (DNS_R_SYNTAX); + len--; + if (replace) + switch (c) { + case '0': return (DNS_R_SYNTAX); + case '1': if (nsub < 1) nsub = 1; break; + case '2': if (nsub < 2) nsub = 2; break; + case '3': if (nsub < 3) nsub = 3; break; + case '4': if (nsub < 4) nsub = 4; break; + case '5': if (nsub < 5) nsub = 5; break; + case '6': if (nsub < 6) nsub = 6; break; + case '7': if (nsub < 7) nsub = 7; break; + case '8': if (nsub < 8) nsub = 8; break; + case '9': if (nsub < 9) nsub = 9; break; + } + if (!replace) + *cp++ = c; + } + } + if (!flags) + return (DNS_R_SYNTAX); + *cp = '\0'; + n = isc_regex_validate(regex); + if (n < 0 || nsub > (unsigned int)n) + return (DNS_R_SYNTAX); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromtext_naptr(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + unsigned char *regex; + + REQUIRE(type == dns_rdatatype_naptr); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Order. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Preference. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Flags. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + + /* + * Service. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + + /* + * Regexp. + */ + regex = isc_buffer_used(target); + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false)); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + RETTOK(txt_valid_regex(regex)); + + /* + * Replacement. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_naptr(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_naptr); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + + /* + * Order. + */ + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Preference. + */ + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Flags. + */ + RETERR(txt_totext(®ion, true, target)); + RETERR(str_totext(" ", target)); + + /* + * Service. + */ + RETERR(txt_totext(®ion, true, target)); + RETERR(str_totext(" ", target)); + + /* + * Regexp. + */ + RETERR(txt_totext(®ion, true, target)); + RETERR(str_totext(" ", target)); + + /* + * Replacement. + */ + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_naptr(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sr; + unsigned char *regex; + + REQUIRE(type == dns_rdatatype_naptr); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + /* + * Order, preference. + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_buffer_forward(source, 4); + + /* + * Flags. + */ + RETERR(txt_fromwire(source, target)); + + /* + * Service. + */ + RETERR(txt_fromwire(source, target)); + + /* + * Regexp. + */ + regex = isc_buffer_used(target); + RETERR(txt_fromwire(source, target)); + RETERR(txt_valid_regex(regex)); + + /* + * Replacement. + */ + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_naptr(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_naptr); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + /* + * Order, preference. + */ + dns_rdata_toregion(rdata, &sr); + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_region_consume(&sr, 4); + + /* + * Flags. + */ + RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1)); + isc_region_consume(&sr, sr.base[0] + 1); + + /* + * Service. + */ + RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1)); + isc_region_consume(&sr, sr.base[0] + 1); + + /* + * Regexp. + */ + RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1)); + isc_region_consume(&sr, sr.base[0] + 1); + + /* + * Replacement. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_naptr(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order, len; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_naptr); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + /* + * Order, preference. + */ + order = memcmp(region1.base, region2.base, 4); + if (order != 0) + return (order < 0 ? -1 : 1); + isc_region_consume(®ion1, 4); + isc_region_consume(®ion2, 4); + + /* + * Flags. + */ + len = ISC_MIN(region1.base[0], region2.base[0]); + order = memcmp(region1.base, region2.base, len + 1); + if (order != 0) + return (order < 0 ? -1 : 1); + isc_region_consume(®ion1, region1.base[0] + 1); + isc_region_consume(®ion2, region2.base[0] + 1); + + /* + * Service. + */ + len = ISC_MIN(region1.base[0], region2.base[0]); + order = memcmp(region1.base, region2.base, len + 1); + if (order != 0) + return (order < 0 ? -1 : 1); + isc_region_consume(®ion1, region1.base[0] + 1); + isc_region_consume(®ion2, region2.base[0] + 1); + + /* + * Regexp. + */ + len = ISC_MIN(region1.base[0], region2.base[0]); + order = memcmp(region1.base, region2.base, len + 1); + if (order != 0) + return (order < 0 ? -1 : 1); + isc_region_consume(®ion1, region1.base[0] + 1); + isc_region_consume(®ion2, region2.base[0] + 1); + + /* + * Replacement. + */ + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_naptr(ARGS_FROMSTRUCT) { + dns_rdata_naptr_t *naptr = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_naptr); + REQUIRE(source != NULL); + REQUIRE(naptr->common.rdtype == type); + REQUIRE(naptr->common.rdclass == rdclass); + REQUIRE(naptr->flags != NULL || naptr->flags_len == 0); + REQUIRE(naptr->service != NULL || naptr->service_len == 0); + REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(naptr->order, target)); + RETERR(uint16_tobuffer(naptr->preference, target)); + RETERR(uint8_tobuffer(naptr->flags_len, target)); + RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len)); + RETERR(uint8_tobuffer(naptr->service_len, target)); + RETERR(mem_tobuffer(target, naptr->service, naptr->service_len)); + RETERR(uint8_tobuffer(naptr->regexp_len, target)); + RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len)); + dns_name_toregion(&naptr->replacement, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_naptr(ARGS_TOSTRUCT) { + dns_rdata_naptr_t *naptr = target; + isc_region_t r; + isc_result_t result; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_naptr); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + naptr->common.rdclass = rdata->rdclass; + naptr->common.rdtype = rdata->type; + ISC_LINK_INIT(&naptr->common, link); + + naptr->flags = NULL; + naptr->service = NULL; + naptr->regexp = NULL; + + dns_rdata_toregion(rdata, &r); + + naptr->order = uint16_fromregion(&r); + isc_region_consume(&r, 2); + + naptr->preference = uint16_fromregion(&r); + isc_region_consume(&r, 2); + + naptr->flags_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + INSIST(naptr->flags_len <= r.length); + naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len); + if (naptr->flags == NULL) + goto cleanup; + isc_region_consume(&r, naptr->flags_len); + + naptr->service_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + INSIST(naptr->service_len <= r.length); + naptr->service = mem_maybedup(mctx, r.base, naptr->service_len); + if (naptr->service == NULL) + goto cleanup; + isc_region_consume(&r, naptr->service_len); + + naptr->regexp_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + INSIST(naptr->regexp_len <= r.length); + naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len); + if (naptr->regexp == NULL) + goto cleanup; + isc_region_consume(&r, naptr->regexp_len); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + dns_name_init(&naptr->replacement, NULL); + result = name_duporclone(&name, mctx, &naptr->replacement); + if (result != ISC_R_SUCCESS) + goto cleanup; + naptr->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL && naptr->flags != NULL) + isc_mem_free(mctx, naptr->flags); + if (mctx != NULL && naptr->service != NULL) + isc_mem_free(mctx, naptr->service); + if (mctx != NULL && naptr->regexp != NULL) + isc_mem_free(mctx, naptr->regexp); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_naptr(ARGS_FREESTRUCT) { + dns_rdata_naptr_t *naptr = source; + + REQUIRE(source != NULL); + REQUIRE(naptr->common.rdtype == dns_rdatatype_naptr); + + if (naptr->mctx == NULL) + return; + + if (naptr->flags != NULL) + isc_mem_free(naptr->mctx, naptr->flags); + if (naptr->service != NULL) + isc_mem_free(naptr->mctx, naptr->service); + if (naptr->regexp != NULL) + isc_mem_free(naptr->mctx, naptr->regexp); + dns_name_free(&naptr->replacement, naptr->mctx); + naptr->mctx = NULL; +} + +static inline isc_result_t +additionaldata_naptr(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t sr; + dns_rdatatype_t atype; + unsigned int i, flagslen; + char *cp; + + REQUIRE(rdata->type == dns_rdatatype_naptr); + + /* + * Order, preference. + */ + dns_rdata_toregion(rdata, &sr); + isc_region_consume(&sr, 4); + + /* + * Flags. + */ + atype = 0; + flagslen = sr.base[0]; + cp = (char *)&sr.base[1]; + for (i = 0; i < flagslen; i++, cp++) { + if (*cp == 'S' || *cp == 's') { + atype = dns_rdatatype_srv; + break; + } + if (*cp == 'A' || *cp == 'a') { + atype = dns_rdatatype_a; + break; + } + } + isc_region_consume(&sr, flagslen + 1); + + /* + * Service. + */ + isc_region_consume(&sr, sr.base[0] + 1); + + /* + * Regexp. + */ + isc_region_consume(&sr, sr.base[0] + 1); + + /* + * Replacement. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + + if (atype != 0) + return ((add)(arg, &name, atype)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_naptr(ARGS_DIGEST) { + isc_region_t r1, r2; + unsigned int length, n; + isc_result_t result; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_naptr); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + length = 0; + + /* + * Order, preference. + */ + length += 4; + isc_region_consume(&r2, 4); + + /* + * Flags. + */ + n = r2.base[0] + 1; + length += n; + isc_region_consume(&r2, n); + + /* + * Service. + */ + n = r2.base[0] + 1; + length += n; + isc_region_consume(&r2, n); + + /* + * Regexp. + */ + n = r2.base[0] + 1; + length += n; + isc_region_consume(&r2, n); + + /* + * Digest the RR up to the replacement name. + */ + r1.length = length; + result = (digest)(arg, &r1); + if (result != ISC_R_SUCCESS) + return (result); + + /* + * Replacement. + */ + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_naptr(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_naptr); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_naptr(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_naptr); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_naptr(ARGS_COMPARE) { + return (compare_naptr(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_NAPTR_35_C */ diff --git a/lib/dns/rdata/generic/naptr_35.h b/lib/dns/rdata/generic/naptr_35.h new file mode 100644 index 0000000..e72b609 --- /dev/null +++ b/lib/dns/rdata/generic/naptr_35.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_NAPTR_35_H +#define GENERIC_NAPTR_35_H 1 + + +/*! + * \brief Per RFC2915 */ + +typedef struct dns_rdata_naptr { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t order; + uint16_t preference; + char *flags; + uint8_t flags_len; + char *service; + uint8_t service_len; + char *regexp; + uint8_t regexp_len; + dns_name_t replacement; +} dns_rdata_naptr_t; + +#endif /* GENERIC_NAPTR_35_H */ diff --git a/lib/dns/rdata/generic/nid_104.c b/lib/dns/rdata/generic/nid_104.c new file mode 100644 index 0000000..fee61fd --- /dev/null +++ b/lib/dns/rdata/generic/nid_104.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_NID_104_C +#define RDATA_GENERIC_NID_104_C + +#include <string.h> + +#include <isc/net.h> + +#define RRTYPE_NID_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_nid(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char locator[NS_LOCATORSZ]; + + REQUIRE(type == dns_rdatatype_nid); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (locator_pton(DNS_AS_STR(token), locator) != 1) + RETTOK(DNS_R_SYNTAX); + return (mem_tobuffer(target, locator, NS_LOCATORSZ)); +} + +static inline isc_result_t +totext_nid(ARGS_TOTEXT) { + isc_region_t region; + char buf[sizeof("xxxx:xxxx:xxxx:xxxx")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_nid); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + snprintf(buf, sizeof(buf), "%x:%x:%x:%x", + region.base[0]<<8 | region.base[1], + region.base[2]<<8 | region.base[3], + region.base[4]<<8 | region.base[5], + region.base[6]<<8 | region.base[7]); + return (str_totext(buf, target)); +} + +static inline isc_result_t +fromwire_nid(ARGS_FROMWIRE) { + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_nid); + + UNUSED(type); + UNUSED(options); + UNUSED(rdclass); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length != 10) + return (DNS_R_FORMERR); + isc_buffer_forward(source, sregion.length); + return (mem_tobuffer(target, sregion.base, sregion.length)); +} + +static inline isc_result_t +towire_nid(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_nid); + REQUIRE(rdata->length == 10); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_nid(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nid); + REQUIRE(rdata1->length == 10); + REQUIRE(rdata2->length == 10); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_nid(ARGS_FROMSTRUCT) { + dns_rdata_nid_t *nid = source; + + REQUIRE(type == dns_rdatatype_nid); + REQUIRE(source != NULL); + REQUIRE(nid->common.rdtype == type); + REQUIRE(nid->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(nid->pref, target)); + return (mem_tobuffer(target, nid->nid, sizeof(nid->nid))); +} + +static inline isc_result_t +tostruct_nid(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_nid_t *nid = target; + + REQUIRE(rdata->type == dns_rdatatype_nid); + REQUIRE(target != NULL); + REQUIRE(rdata->length == 10); + + UNUSED(mctx); + + nid->common.rdclass = rdata->rdclass; + nid->common.rdtype = rdata->type; + ISC_LINK_INIT(&nid->common, link); + + dns_rdata_toregion(rdata, ®ion); + nid->pref = uint16_fromregion(®ion); + memmove(nid->nid, region.base, region.length); + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_nid(ARGS_FREESTRUCT) { + dns_rdata_nid_t *nid = source; + + REQUIRE(source != NULL); + REQUIRE(nid->common.rdtype == dns_rdatatype_nid); + + return; +} + +static inline isc_result_t +additionaldata_nid(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_nid); + REQUIRE(rdata->length == 10); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_nid(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nid); + REQUIRE(rdata->length == 10); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_nid(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_nid); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_nid(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nid); + REQUIRE(rdata->length == 10); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_nid(ARGS_COMPARE) { + return (compare_nid(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_NID_104_C */ diff --git a/lib/dns/rdata/generic/nid_104.h b/lib/dns/rdata/generic/nid_104.h new file mode 100644 index 0000000..9362e2b --- /dev/null +++ b/lib/dns/rdata/generic/nid_104.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_NID_104_H +#define GENERIC_NID_104_H 1 + +typedef struct dns_rdata_nid { + dns_rdatacommon_t common; + uint16_t pref; + unsigned char nid[8]; +} dns_rdata_nid_t; + +#endif /* GENERIC_NID_104_H */ diff --git a/lib/dns/rdata/generic/ninfo_56.c b/lib/dns/rdata/generic/ninfo_56.c new file mode 100644 index 0000000..fe8957a --- /dev/null +++ b/lib/dns/rdata/generic/ninfo_56.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_NINFO_56_C +#define RDATA_GENERIC_NINFO_56_C + +#define RRTYPE_NINFO_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_ninfo(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_ninfo); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + return (generic_fromtext_txt(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_ninfo(ARGS_TOTEXT) { + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_ninfo); + + return (generic_totext_txt(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_ninfo(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_ninfo); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + return (generic_fromwire_txt(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_ninfo(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_ninfo); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_ninfo(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ninfo); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_ninfo(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_ninfo); + + return (generic_fromstruct_txt(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_ninfo(ARGS_TOSTRUCT) { + dns_rdata_ninfo_t *txt = target; + + REQUIRE(rdata->type == dns_rdatatype_ninfo); + + txt->common.rdclass = rdata->rdclass; + txt->common.rdtype = rdata->type; + ISC_LINK_INIT(&txt->common, link); + + return (generic_tostruct_txt(rdata, target, mctx)); +} + +static inline void +freestruct_ninfo(ARGS_FREESTRUCT) { + dns_rdata_ninfo_t *ninfo = source; + + REQUIRE(source != NULL); + REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo); + + generic_freestruct_txt(source); +} + +static inline isc_result_t +additionaldata_ninfo(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_ninfo); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_ninfo(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_ninfo); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_ninfo(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_ninfo); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_ninfo(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_ninfo); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_ninfo(ARGS_COMPARE) { + return (compare_ninfo(rdata1, rdata2)); +} + +isc_result_t +dns_rdata_ninfo_first(dns_rdata_ninfo_t *ninfo) { + + REQUIRE(ninfo != NULL); + REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo); + + return (generic_txt_first(ninfo)); +} + +isc_result_t +dns_rdata_ninfo_next(dns_rdata_ninfo_t *ninfo) { + + REQUIRE(ninfo != NULL); + REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo); + + return (generic_txt_next(ninfo)); +} + +isc_result_t +dns_rdata_ninfo_current(dns_rdata_ninfo_t *ninfo, + dns_rdata_ninfo_string_t *string) +{ + + REQUIRE(ninfo != NULL); + REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo); + + return (generic_txt_current(ninfo, string)); +} +#endif /* RDATA_GENERIC_NINFO_56_C */ diff --git a/lib/dns/rdata/generic/ninfo_56.h b/lib/dns/rdata/generic/ninfo_56.h new file mode 100644 index 0000000..68e9212 --- /dev/null +++ b/lib/dns/rdata/generic/ninfo_56.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_NINFO_56_H +#define GENERIC_NINFO_56_H 1 + +typedef struct dns_rdata_txt_string dns_rdata_ninfo_string_t; + +typedef struct dns_rdata_txt dns_rdata_ninfo_t; + +/* + * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done + * via rdatastructpre.h and rdatastructsuf.h. + */ + +isc_result_t +dns_rdata_ninfo_first(dns_rdata_ninfo_t *); + +isc_result_t +dns_rdata_ninfo_next(dns_rdata_ninfo_t *); + +isc_result_t +dns_rdata_ninfo_current(dns_rdata_ninfo_t *, dns_rdata_ninfo_string_t *); + +#endif /* GENERIC_NINFO_16_H */ diff --git a/lib/dns/rdata/generic/ns_2.c b/lib/dns/rdata/generic/ns_2.c new file mode 100644 index 0000000..7f3979f --- /dev/null +++ b/lib/dns/rdata/generic/ns_2.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_NS_2_C +#define RDATA_GENERIC_NS_2_C + +#define RRTYPE_NS_ATTRIBUTES (DNS_RDATATYPEATTR_ZONECUTAUTH) + +static inline isc_result_t +fromtext_ns(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + bool ok; + + REQUIRE(type == dns_rdatatype_ns); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token,isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_ns(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_ns); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_ns(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_ns); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_ns(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_ns); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_ns(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ns); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_ns(ARGS_FROMSTRUCT) { + dns_rdata_ns_t *ns = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_ns); + REQUIRE(source != NULL); + REQUIRE(ns->common.rdtype == type); + REQUIRE(ns->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&ns->name, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_ns(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_ns_t *ns = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_ns); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + ns->common.rdclass = rdata->rdclass; + ns->common.rdtype = rdata->type; + ISC_LINK_INIT(&ns->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&ns->name, NULL); + RETERR(name_duporclone(&name, mctx, &ns->name)); + ns->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_ns(ARGS_FREESTRUCT) { + dns_rdata_ns_t *ns = source; + + REQUIRE(source != NULL); + + if (ns->mctx == NULL) + return; + + dns_name_free(&ns->name, ns->mctx); + ns->mctx = NULL; +} + +static inline isc_result_t +additionaldata_ns(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_ns); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_ns(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_ns); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_ns(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_ns); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_ns(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_ns); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_ns(ARGS_COMPARE) { + return (compare_ns(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_NS_2_C */ diff --git a/lib/dns/rdata/generic/ns_2.h b/lib/dns/rdata/generic/ns_2.h new file mode 100644 index 0000000..db9b6c0 --- /dev/null +++ b/lib/dns/rdata/generic/ns_2.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_NS_2_H +#define GENERIC_NS_2_H 1 + + +typedef struct dns_rdata_ns { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t name; +} dns_rdata_ns_t; + + +#endif /* GENERIC_NS_2_H */ diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c new file mode 100644 index 0000000..1aedf22 --- /dev/null +++ b/lib/dns/rdata/generic/nsec3_50.c @@ -0,0 +1,402 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Copyright (C) 2004 Nominet, Ltd. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* RFC 5155 */ + +#ifndef RDATA_GENERIC_NSEC3_50_C +#define RDATA_GENERIC_NSEC3_50_C + +#include <isc/iterated_hash.h> +#include <isc/base32.h> + +#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC + +static inline isc_result_t +fromtext_nsec3(ARGS_FROMTEXT) { + isc_token_t token; + unsigned int flags; + unsigned char hashalg; + isc_buffer_t b; + unsigned char buf[256]; + + REQUIRE(type == dns_rdatatype_nsec3); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + UNUSED(origin); + UNUSED(options); + + /* Hash. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion)); + RETERR(uint8_tobuffer(hashalg, target)); + + /* Flags. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + flags = token.value.as_ulong; + if (flags > 255U) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(flags, target)); + + /* Iterations. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* salt */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (token.value.as_textregion.length > (255*2)) + RETTOK(DNS_R_TEXTTOOLONG); + if (strcmp(DNS_AS_STR(token), "-") == 0) { + RETERR(uint8_tobuffer(0, target)); + } else { + RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target)); + RETERR(isc_hex_decodestring(DNS_AS_STR(token), target)); + } + + /* + * Next hash a single base32hex word. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + isc_buffer_init(&b, buf, sizeof(buf)); + RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b)); + if (isc_buffer_usedlength(&b) > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target)); + RETERR(mem_tobuffer(target, &buf, isc_buffer_usedlength(&b))); + + return (typemap_fromtext(lexer, target, true)); +} + +static inline isc_result_t +totext_nsec3(ARGS_TOTEXT) { + isc_region_t sr; + unsigned int i, j; + unsigned char hash; + unsigned char flags; + char buf[sizeof("TYPE65535")]; + uint32_t iterations; + + REQUIRE(rdata->type == dns_rdatatype_nsec3); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* Hash */ + hash = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u ", hash); + RETERR(str_totext(buf, target)); + + /* Flags */ + flags = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u ", flags); + RETERR(str_totext(buf, target)); + + /* Iterations */ + iterations = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%u ", iterations); + RETERR(str_totext(buf, target)); + + /* Salt */ + j = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + INSIST(j <= sr.length); + + if (j != 0) { + i = sr.length; + sr.length = j; + RETERR(isc_hex_totext(&sr, 1, "", target)); + sr.length = i - j; + } else + RETERR(str_totext("-", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + + /* Next hash */ + j = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + INSIST(j <= sr.length); + + i = sr.length; + sr.length = j; + RETERR(isc_base32hexnp_totext(&sr, 1, "", target)); + sr.length = i - j; + + /* + * Don't leave a trailing space when there's no typemap present. + */ + if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) { + RETERR(str_totext(" ", target)); + } + RETERR(typemap_totext(&sr, tctx, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_nsec3(ARGS_FROMWIRE) { + isc_region_t sr, rr; + unsigned int saltlen, hashlen; + + REQUIRE(type == dns_rdatatype_nsec3); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(options); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sr); + rr = sr; + + /* hash(1), flags(1), iteration(2), saltlen(1) */ + if (sr.length < 5U) + RETERR(DNS_R_FORMERR); + saltlen = sr.base[4]; + isc_region_consume(&sr, 5); + + if (sr.length < saltlen) + RETERR(DNS_R_FORMERR); + isc_region_consume(&sr, saltlen); + + if (sr.length < 1U) + RETERR(DNS_R_FORMERR); + hashlen = sr.base[0]; + isc_region_consume(&sr, 1); + + if (sr.length < hashlen) + RETERR(DNS_R_FORMERR); + isc_region_consume(&sr, hashlen); + + RETERR(typemap_test(&sr, true)); + + RETERR(mem_tobuffer(target, rr.base, rr.length)); + isc_buffer_forward(source, rr.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_nsec3(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_nsec3); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_nsec3(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nsec3); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_nsec3(ARGS_FROMSTRUCT) { + dns_rdata_nsec3_t *nsec3 = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_nsec3); + REQUIRE(source != NULL); + REQUIRE(nsec3->common.rdtype == type); + REQUIRE(nsec3->common.rdclass == rdclass); + REQUIRE(nsec3->typebits != NULL || nsec3->len == 0); + REQUIRE(nsec3->hash == dns_hash_sha1); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(nsec3->hash, target)); + RETERR(uint8_tobuffer(nsec3->flags, target)); + RETERR(uint16_tobuffer(nsec3->iterations, target)); + RETERR(uint8_tobuffer(nsec3->salt_length, target)); + RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length)); + RETERR(uint8_tobuffer(nsec3->next_length, target)); + RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length)); + + region.base = nsec3->typebits; + region.length = nsec3->len; + RETERR(typemap_test(®ion, true)); + return (mem_tobuffer(target, nsec3->typebits, nsec3->len)); +} + +static inline isc_result_t +tostruct_nsec3(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_nsec3_t *nsec3 = target; + + REQUIRE(rdata->type == dns_rdatatype_nsec3); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + nsec3->common.rdclass = rdata->rdclass; + nsec3->common.rdtype = rdata->type; + ISC_LINK_INIT(&nsec3->common, link); + + region.base = rdata->data; + region.length = rdata->length; + nsec3->hash = uint8_consume_fromregion(®ion); + nsec3->flags = uint8_consume_fromregion(®ion); + nsec3->iterations = uint16_consume_fromregion(®ion); + + nsec3->salt_length = uint8_consume_fromregion(®ion); + nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length); + if (nsec3->salt == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(®ion, nsec3->salt_length); + + nsec3->next_length = uint8_consume_fromregion(®ion); + nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length); + if (nsec3->next == NULL) + goto cleanup; + isc_region_consume(®ion, nsec3->next_length); + + nsec3->len = region.length; + nsec3->typebits = mem_maybedup(mctx, region.base, region.length); + if (nsec3->typebits == NULL) + goto cleanup; + + nsec3->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (nsec3->next != NULL) + isc_mem_free(mctx, nsec3->next); + isc_mem_free(mctx, nsec3->salt); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_nsec3(ARGS_FREESTRUCT) { + dns_rdata_nsec3_t *nsec3 = source; + + REQUIRE(source != NULL); + REQUIRE(nsec3->common.rdtype == dns_rdatatype_nsec3); + + if (nsec3->mctx == NULL) + return; + + if (nsec3->salt != NULL) + isc_mem_free(nsec3->mctx, nsec3->salt); + if (nsec3->next != NULL) + isc_mem_free(nsec3->mctx, nsec3->next); + if (nsec3->typebits != NULL) + isc_mem_free(nsec3->mctx, nsec3->typebits); + nsec3->mctx = NULL; +} + +static inline isc_result_t +additionaldata_nsec3(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nsec3); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_nsec3(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nsec3); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_nsec3(ARGS_CHECKOWNER) { + unsigned char owner[NSEC3_MAX_HASH_LENGTH]; + isc_buffer_t buffer; + dns_label_t label; + + REQUIRE(type == dns_rdatatype_nsec3); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + /* + * First label is a base32hex string without padding. + */ + dns_name_getlabel(name, 0, &label); + isc_region_consume(&label, 1); + isc_buffer_init(&buffer, owner, sizeof(owner)); + if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS) + return (true); + + return (false); +} + +static inline bool +checknames_nsec3(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nsec3); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_nsec3(ARGS_COMPARE) { + return (compare_nsec3(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_NSEC3_50_C */ diff --git a/lib/dns/rdata/generic/nsec3_50.h b/lib/dns/rdata/generic/nsec3_50.h new file mode 100644 index 0000000..36b9695 --- /dev/null +++ b/lib/dns/rdata/generic/nsec3_50.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_NSEC3_50_H +#define GENERIC_NSEC3_50_H 1 + + +/*! + * \brief Per RFC 5155 */ + +#include <isc/iterated_hash.h> + +typedef struct dns_rdata_nsec3 { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_hash_t hash; + unsigned char flags; + dns_iterations_t iterations; + unsigned char salt_length; + unsigned char next_length; + uint16_t len; + unsigned char *salt; + unsigned char *next; + unsigned char *typebits; +} dns_rdata_nsec3_t; + +/* + * The corresponding NSEC3 interval is OPTOUT indicating possible + * insecure delegations. + */ +#define DNS_NSEC3FLAG_OPTOUT 0x01U + +/*% + * The following flags are used in the private-type record (implemented in + * lib/dns/private.c) which is used to store NSEC3PARAM data during the + * time when it is not legal to have an actual NSEC3PARAM record in the + * zone. They are defined here because the private-type record uses the + * same flags field for the OPTOUT flag above and for the private flags + * below. XXX: This should be considered for refactoring. + */ + +/*% + * Non-standard, private type only. + * + * Create a corresponding NSEC3 chain. + * Once the NSEC3 chain is complete this flag will be removed to signal + * that there is a complete chain. + * + * This flag is automatically set when a NSEC3PARAM record is added to + * the zone via UPDATE. + * + * NSEC3PARAM records containing this flag should never be published, + * but if they are, they should be ignored by RFC 5155 compliant + * nameservers. + */ +#define DNS_NSEC3FLAG_CREATE 0x80U + +/*% + * Non-standard, private type only. + * + * The corresponding NSEC3 set is to be removed once the NSEC chain + * has been generated. + * + * This flag is automatically set when the last active NSEC3PARAM record + * is removed from the zone via UPDATE. + * + * NSEC3PARAM records containing this flag should never be published, + * but if they are, they should be ignored by RFC 5155 compliant + * nameservers. + */ +#define DNS_NSEC3FLAG_REMOVE 0x40U + +/*% + * Non-standard, private type only. + * + * When set with the CREATE flag, a corresponding NSEC3 chain will be + * created when the zone becomes capable of supporting one (i.e., when it + * has a DNSKEY RRset containing at least one NSEC3-capable algorithm). + * Without this flag, NSEC3 chain creation would be attempted immediately, + * fail, and the private type record would be removed. With it, the NSEC3 + * parameters are stored until they can be used. When the zone has the + * necessary prerequisites for NSEC3, then the INITIAL flag can be cleared, + * and the record will be cleaned up normally. + * + * NSEC3PARAM records containing this flag should never be published, but + * if they are, they should be ignored by RFC 5155 compliant nameservers. + */ +#define DNS_NSEC3FLAG_INITIAL 0x20U + +/*% + * Non-standard, private type only. + * + * Prevent the creation of a NSEC chain before the last NSEC3 chain + * is removed. This will normally only be set when the zone is + * transitioning from secure with NSEC3 chains to insecure. + * + * NSEC3PARAM records containing this flag should never be published, + * but if they are, they should be ignored by RFC 5155 compliant + * nameservers. + */ +#define DNS_NSEC3FLAG_NONSEC 0x10U + +#endif /* GENERIC_NSEC3_50_H */ diff --git a/lib/dns/rdata/generic/nsec3param_51.c b/lib/dns/rdata/generic/nsec3param_51.c new file mode 100644 index 0000000..8a24dee --- /dev/null +++ b/lib/dns/rdata/generic/nsec3param_51.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Copyright (C) 2004 Nominet, Ltd. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* RFC 5155 */ + +#ifndef RDATA_GENERIC_NSEC3PARAM_51_C +#define RDATA_GENERIC_NSEC3PARAM_51_C + +#include <isc/iterated_hash.h> +#include <isc/base32.h> + +#define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) + +static inline isc_result_t +fromtext_nsec3param(ARGS_FROMTEXT) { + isc_token_t token; + unsigned int flags = 0; + unsigned char hashalg; + + REQUIRE(type == dns_rdatatype_nsec3param); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + UNUSED(origin); + UNUSED(options); + + /* Hash. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion)); + RETERR(uint8_tobuffer(hashalg, target)); + + /* Flags. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + flags = token.value.as_ulong; + if (flags > 255U) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(flags, target)); + + /* Iterations. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* Salt. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (token.value.as_textregion.length > (255*2)) + RETTOK(DNS_R_TEXTTOOLONG); + if (strcmp(DNS_AS_STR(token), "-") == 0) { + RETERR(uint8_tobuffer(0, target)); + } else { + RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target)); + RETERR(isc_hex_decodestring(DNS_AS_STR(token), target)); + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_nsec3param(ARGS_TOTEXT) { + isc_region_t sr; + unsigned int i, j; + unsigned char hash; + unsigned char flags; + char buf[sizeof("65535 ")]; + uint32_t iterations; + + REQUIRE(rdata->type == dns_rdatatype_nsec3param); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + hash = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + flags = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + iterations = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + snprintf(buf, sizeof(buf), "%u ", hash); + RETERR(str_totext(buf, target)); + + snprintf(buf, sizeof(buf), "%u ", flags); + RETERR(str_totext(buf, target)); + + snprintf(buf, sizeof(buf), "%u ", iterations); + RETERR(str_totext(buf, target)); + + j = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + INSIST(j <= sr.length); + + if (j != 0) { + i = sr.length; + sr.length = j; + RETERR(isc_hex_totext(&sr, 1, "", target)); + sr.length = i - j; + } else + RETERR(str_totext("-", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_nsec3param(ARGS_FROMWIRE) { + isc_region_t sr, rr; + unsigned int saltlen; + + REQUIRE(type == dns_rdatatype_nsec3param); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(options); + UNUSED(dctx); + + isc_buffer_activeregion(source, &sr); + rr = sr; + + /* hash(1), flags(1), iterations(2), saltlen(1) */ + if (sr.length < 5U) + RETERR(DNS_R_FORMERR); + saltlen = sr.base[4]; + isc_region_consume(&sr, 5); + + if (sr.length < saltlen) + RETERR(DNS_R_FORMERR); + isc_region_consume(&sr, saltlen); + RETERR(mem_tobuffer(target, rr.base, rr.length)); + isc_buffer_forward(source, rr.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_nsec3param(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_nsec3param); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_nsec3param(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nsec3param); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_nsec3param(ARGS_FROMSTRUCT) { + dns_rdata_nsec3param_t *nsec3param = source; + + REQUIRE(type == dns_rdatatype_nsec3param); + REQUIRE(source != NULL); + REQUIRE(nsec3param->common.rdtype == type); + REQUIRE(nsec3param->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(nsec3param->hash, target)); + RETERR(uint8_tobuffer(nsec3param->flags, target)); + RETERR(uint16_tobuffer(nsec3param->iterations, target)); + RETERR(uint8_tobuffer(nsec3param->salt_length, target)); + RETERR(mem_tobuffer(target, nsec3param->salt, + nsec3param->salt_length)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +tostruct_nsec3param(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_nsec3param_t *nsec3param = target; + + REQUIRE(rdata->type == dns_rdatatype_nsec3param); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + nsec3param->common.rdclass = rdata->rdclass; + nsec3param->common.rdtype = rdata->type; + ISC_LINK_INIT(&nsec3param->common, link); + + region.base = rdata->data; + region.length = rdata->length; + nsec3param->hash = uint8_consume_fromregion(®ion); + nsec3param->flags = uint8_consume_fromregion(®ion); + nsec3param->iterations = uint16_consume_fromregion(®ion); + + nsec3param->salt_length = uint8_consume_fromregion(®ion); + nsec3param->salt = mem_maybedup(mctx, region.base, + nsec3param->salt_length); + if (nsec3param->salt == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(®ion, nsec3param->salt_length); + + nsec3param->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_nsec3param(ARGS_FREESTRUCT) { + dns_rdata_nsec3param_t *nsec3param = source; + + REQUIRE(source != NULL); + REQUIRE(nsec3param->common.rdtype == dns_rdatatype_nsec3param); + + if (nsec3param->mctx == NULL) + return; + + if (nsec3param->salt != NULL) + isc_mem_free(nsec3param->mctx, nsec3param->salt); + nsec3param->mctx = NULL; +} + +static inline isc_result_t +additionaldata_nsec3param(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nsec3param); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_nsec3param(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nsec3param); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_nsec3param(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_nsec3param); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_nsec3param(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nsec3param); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_nsec3param(ARGS_COMPARE) { + return (compare_nsec3param(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_NSEC3PARAM_51_C */ diff --git a/lib/dns/rdata/generic/nsec3param_51.h b/lib/dns/rdata/generic/nsec3param_51.h new file mode 100644 index 0000000..b8bc375 --- /dev/null +++ b/lib/dns/rdata/generic/nsec3param_51.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_NSEC3PARAM_51_H +#define GENERIC_NSEC3PARAM_51_H 1 + + +/*! + * \brief Per RFC 5155 */ + +#include <isc/iterated_hash.h> + +typedef struct dns_rdata_nsec3param { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_hash_t hash; + unsigned char flags; /* DNS_NSEC3FLAG_* */ + dns_iterations_t iterations; + unsigned char salt_length; + unsigned char *salt; +} dns_rdata_nsec3param_t; + +#endif /* GENERIC_NSEC3PARAM_51_H */ diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c new file mode 100644 index 0000000..05e575b --- /dev/null +++ b/lib/dns/rdata/generic/nsec_47.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC 3845 */ + +#ifndef RDATA_GENERIC_NSEC_47_C +#define RDATA_GENERIC_NSEC_47_C + +/* + * The attributes do not include DNS_RDATATYPEATTR_SINGLETON + * because we must be able to handle a parent/child NSEC pair. + */ +#define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) + +static inline isc_result_t +fromtext_nsec(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_nsec); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Next domain. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + return (typemap_fromtext(lexer, target, false)); +} + +static inline isc_result_t +totext_nsec(ARGS_TOTEXT) { + isc_region_t sr; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_nsec); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, &sr); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + RETERR(dns_name_totext(&name, false, target)); + /* + * Don't leave a trailing space when there's no typemap present. + */ + if (sr.length > 0) { + RETERR(str_totext(" ", target)); + } + return (typemap_totext(&sr, NULL, target)); +} + +static /* inline */ isc_result_t +fromwire_nsec(ARGS_FROMWIRE) { + isc_region_t sr; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_nsec); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + isc_buffer_activeregion(source, &sr); + RETERR(typemap_test(&sr, false)); + RETERR(mem_tobuffer(target, sr.base, sr.length)); + isc_buffer_forward(source, sr.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_nsec(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_nsec); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, &sr); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + RETERR(dns_name_towire(&name, cctx, target)); + + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_nsec(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nsec); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_nsec(ARGS_FROMSTRUCT) { + dns_rdata_nsec_t *nsec = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_nsec); + REQUIRE(source != NULL); + REQUIRE(nsec->common.rdtype == type); + REQUIRE(nsec->common.rdclass == rdclass); + REQUIRE(nsec->typebits != NULL || nsec->len == 0); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&nsec->next, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + + region.base = nsec->typebits; + region.length = nsec->len; + RETERR(typemap_test(®ion, false)); + return (mem_tobuffer(target, nsec->typebits, nsec->len)); +} + +static inline isc_result_t +tostruct_nsec(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_nsec_t *nsec = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_nsec); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + nsec->common.rdclass = rdata->rdclass; + nsec->common.rdtype = rdata->type; + ISC_LINK_INIT(&nsec->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + dns_name_init(&nsec->next, NULL); + RETERR(name_duporclone(&name, mctx, &nsec->next)); + + nsec->len = region.length; + nsec->typebits = mem_maybedup(mctx, region.base, region.length); + if (nsec->typebits == NULL) + goto cleanup; + + nsec->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&nsec->next, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_nsec(ARGS_FREESTRUCT) { + dns_rdata_nsec_t *nsec = source; + + REQUIRE(source != NULL); + REQUIRE(nsec->common.rdtype == dns_rdatatype_nsec); + + if (nsec->mctx == NULL) + return; + + dns_name_free(&nsec->next, nsec->mctx); + if (nsec->typebits != NULL) + isc_mem_free(nsec->mctx, nsec->typebits); + nsec->mctx = NULL; +} + +static inline isc_result_t +additionaldata_nsec(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nsec); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_nsec(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nsec); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_nsec(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_nsec); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_nsec(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nsec); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_nsec(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nsec); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + return (isc_region_compare(®ion1, ®ion2)); +} +#endif /* RDATA_GENERIC_NSEC_47_C */ diff --git a/lib/dns/rdata/generic/nsec_47.h b/lib/dns/rdata/generic/nsec_47.h new file mode 100644 index 0000000..b597864 --- /dev/null +++ b/lib/dns/rdata/generic/nsec_47.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_NSEC_47_H +#define GENERIC_NSEC_47_H 1 + + +/*! + * \brief Per RFC 3845 */ + +typedef struct dns_rdata_nsec { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t next; + unsigned char *typebits; + uint16_t len; +} dns_rdata_nsec_t; + +#endif /* GENERIC_NSEC_47_H */ diff --git a/lib/dns/rdata/generic/null_10.c b/lib/dns/rdata/generic/null_10.c new file mode 100644 index 0000000..624adad --- /dev/null +++ b/lib/dns/rdata/generic/null_10.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_NULL_10_C +#define RDATA_GENERIC_NULL_10_C + +#define RRTYPE_NULL_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_null(ARGS_FROMTEXT) { + REQUIRE(type == dns_rdatatype_null); + + UNUSED(rdclass); + UNUSED(type); + UNUSED(lexer); + UNUSED(origin); + UNUSED(options); + UNUSED(target); + UNUSED(callbacks); + + return (DNS_R_SYNTAX); +} + +static inline isc_result_t +totext_null(ARGS_TOTEXT) { + REQUIRE(rdata->type == dns_rdatatype_null); + + return (unknown_totext(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_null(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_null); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_null(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_null); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_null(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_null); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_null(ARGS_FROMSTRUCT) { + dns_rdata_null_t *null = source; + + REQUIRE(type == dns_rdatatype_null); + REQUIRE(source != NULL); + REQUIRE(null->common.rdtype == type); + REQUIRE(null->common.rdclass == rdclass); + REQUIRE(null->data != NULL || null->length == 0); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, null->data, null->length)); +} + +static inline isc_result_t +tostruct_null(ARGS_TOSTRUCT) { + dns_rdata_null_t *null = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_null); + REQUIRE(target != NULL); + + null->common.rdclass = rdata->rdclass; + null->common.rdtype = rdata->type; + ISC_LINK_INIT(&null->common, link); + + dns_rdata_toregion(rdata, &r); + null->length = r.length; + null->data = mem_maybedup(mctx, r.base, r.length); + if (null->data == NULL) + return (ISC_R_NOMEMORY); + + null->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_null(ARGS_FREESTRUCT) { + dns_rdata_null_t *null = source; + + REQUIRE(source != NULL); + REQUIRE(null->common.rdtype == dns_rdatatype_null); + + if (null->mctx == NULL) + return; + + if (null->data != NULL) + isc_mem_free(null->mctx, null->data); + null->mctx = NULL; +} + +static inline isc_result_t +additionaldata_null(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_null); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_null(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_null); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_null(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_null); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_null(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_null); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_null(ARGS_COMPARE) { + return (compare_null(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_NULL_10_C */ diff --git a/lib/dns/rdata/generic/null_10.h b/lib/dns/rdata/generic/null_10.h new file mode 100644 index 0000000..0b01dd8 --- /dev/null +++ b/lib/dns/rdata/generic/null_10.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_NULL_10_H +#define GENERIC_NULL_10_H 1 + + +typedef struct dns_rdata_null { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t length; + unsigned char *data; +} dns_rdata_null_t; + + +#endif /* GENERIC_NULL_10_H */ diff --git a/lib/dns/rdata/generic/nxt_30.c b/lib/dns/rdata/generic/nxt_30.c new file mode 100644 index 0000000..91a95b7 --- /dev/null +++ b/lib/dns/rdata/generic/nxt_30.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_NXT_30_C +#define RDATA_GENERIC_NXT_30_C + +/* + * The attributes do not include DNS_RDATATYPEATTR_SINGLETON + * because we must be able to handle a parent/child NXT pair. + */ +#define RRTYPE_NXT_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_nxt(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + char *e; + unsigned char bm[8*1024]; /* 64k bits */ + dns_rdatatype_t covered; + dns_rdatatype_t maxcovered = 0; + bool first = true; + long n; + + REQUIRE(type == dns_rdatatype_nxt); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Next domain. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + memset(bm, 0, sizeof(bm)); + do { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, true)); + if (token.type != isc_tokentype_string) + break; + n = strtol(DNS_AS_STR(token), &e, 10); + if (e != DNS_AS_STR(token) && *e == '\0') { + covered = (dns_rdatatype_t)n; + } else if (dns_rdatatype_fromtext(&covered, + &token.value.as_textregion) == DNS_R_UNKNOWN) + RETTOK(DNS_R_UNKNOWN); + /* + * NXT is only specified for types 1..127. + */ + if (covered < 1 || covered > 127) + return (ISC_R_RANGE); + if (first || covered > maxcovered) + maxcovered = covered; + first = false; + bm[covered/8] |= (0x80>>(covered%8)); + } while (1); + isc_lex_ungettoken(lexer, &token); + if (first) + return (ISC_R_SUCCESS); + n = (maxcovered + 8) / 8; + return (mem_tobuffer(target, bm, n)); +} + +static inline isc_result_t +totext_nxt(ARGS_TOTEXT) { + isc_region_t sr; + unsigned int i, j; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_nxt); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_rdata_toregion(rdata, &sr); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + for (i = 0; i < sr.length; i++) { + if (sr.base[i] != 0) + for (j = 0; j < 8; j++) + if ((sr.base[i] & (0x80 >> j)) != 0) { + dns_rdatatype_t t = i * 8 + j; + RETERR(str_totext(" ", target)); + if (dns_rdatatype_isknown(t)) { + RETERR(dns_rdatatype_totext(t, + target)); + } else { + char buf[sizeof("65535")]; + snprintf(buf, sizeof(buf), + "%u", t); + RETERR(str_totext(buf, + target)); + } + } + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_nxt(ARGS_FROMWIRE) { + isc_region_t sr; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_nxt); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + isc_buffer_activeregion(source, &sr); + if (sr.length > 0 && (sr.base[0] & 0x80) == 0 && + ((sr.length > 16) || sr.base[sr.length - 1] == 0)) + return (DNS_R_BADBITMAP); + RETERR(mem_tobuffer(target, sr.base, sr.length)); + isc_buffer_forward(source, sr.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_nxt(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_nxt); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, &sr); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + RETERR(dns_name_towire(&name, cctx, target)); + + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_nxt(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nxt); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_nxt(ARGS_FROMSTRUCT) { + dns_rdata_nxt_t *nxt = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_nxt); + REQUIRE(source != NULL); + REQUIRE(nxt->common.rdtype == type); + REQUIRE(nxt->common.rdclass == rdclass); + REQUIRE(nxt->typebits != NULL || nxt->len == 0); + if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) { + REQUIRE(nxt->len <= 16); + REQUIRE(nxt->typebits[nxt->len - 1] != 0); + } + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&nxt->next, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + + return (mem_tobuffer(target, nxt->typebits, nxt->len)); +} + +static inline isc_result_t +tostruct_nxt(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_nxt_t *nxt = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_nxt); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + nxt->common.rdclass = rdata->rdclass; + nxt->common.rdtype = rdata->type; + ISC_LINK_INIT(&nxt->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + dns_name_init(&nxt->next, NULL); + RETERR(name_duporclone(&name, mctx, &nxt->next)); + + nxt->len = region.length; + nxt->typebits = mem_maybedup(mctx, region.base, region.length); + if (nxt->typebits == NULL) + goto cleanup; + + nxt->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&nxt->next, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_nxt(ARGS_FREESTRUCT) { + dns_rdata_nxt_t *nxt = source; + + REQUIRE(source != NULL); + REQUIRE(nxt->common.rdtype == dns_rdatatype_nxt); + + if (nxt->mctx == NULL) + return; + + dns_name_free(&nxt->next, nxt->mctx); + if (nxt->typebits != NULL) + isc_mem_free(nxt->mctx, nxt->typebits); + nxt->mctx = NULL; +} + +static inline isc_result_t +additionaldata_nxt(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nxt); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_nxt(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_nxt); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + result = dns_name_digest(&name, digest, arg); + if (result != ISC_R_SUCCESS) + return (result); + isc_region_consume(&r, name_length(&name)); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_nxt(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_nxt); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_nxt(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nxt); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_nxt(ARGS_COMPARE) { + return (compare_nxt(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_NXT_30_C */ diff --git a/lib/dns/rdata/generic/nxt_30.h b/lib/dns/rdata/generic/nxt_30.h new file mode 100644 index 0000000..63bbc0f --- /dev/null +++ b/lib/dns/rdata/generic/nxt_30.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_NXT_30_H +#define GENERIC_NXT_30_H 1 + + +/*! + * \brief RFC2535 */ + +typedef struct dns_rdata_nxt { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t next; + unsigned char *typebits; + uint16_t len; +} dns_rdata_nxt_t; + +#endif /* GENERIC_NXT_30_H */ diff --git a/lib/dns/rdata/generic/openpgpkey_61.c b/lib/dns/rdata/generic/openpgpkey_61.c new file mode 100644 index 0000000..52c87d4 --- /dev/null +++ b/lib/dns/rdata/generic/openpgpkey_61.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_OPENPGPKEY_61_C +#define RDATA_GENERIC_OPENPGPKEY_61_C + +#define RRTYPE_OPENPGPKEY_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_openpgpkey(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_openpgpkey); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + UNUSED(options); + UNUSED(origin); + + /* + * Keyring. + */ + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_openpgpkey(ARGS_TOTEXT) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_openpgpkey); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* + * Keyring + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext("( ", target)); + + if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + } else + RETERR(str_totext("[omitted]", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_openpgpkey(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_openpgpkey); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + /* + * Keyring. + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_openpgpkey(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_openpgpkey); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_openpgpkey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_openpgpkey); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_openpgpkey(ARGS_FROMSTRUCT) { + dns_rdata_openpgpkey_t *sig = source; + + REQUIRE(type == dns_rdatatype_openpgpkey); + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == type); + REQUIRE(sig->common.rdclass == rdclass); + REQUIRE(sig->keyring != NULL && sig->length != 0); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Keyring. + */ + return (mem_tobuffer(target, sig->keyring, sig->length)); +} + +static inline isc_result_t +tostruct_openpgpkey(ARGS_TOSTRUCT) { + isc_region_t sr; + dns_rdata_openpgpkey_t *sig = target; + + REQUIRE(rdata->type == dns_rdatatype_openpgpkey); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + sig->common.rdclass = rdata->rdclass; + sig->common.rdtype = rdata->type; + ISC_LINK_INIT(&sig->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Keyring. + */ + sig->length = sr.length; + sig->keyring = mem_maybedup(mctx, sr.base, sig->length); + if (sig->keyring == NULL) + goto cleanup; + + sig->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_openpgpkey(ARGS_FREESTRUCT) { + dns_rdata_openpgpkey_t *sig = (dns_rdata_openpgpkey_t *) source; + + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == dns_rdatatype_openpgpkey); + + if (sig->mctx == NULL) + return; + + if (sig->keyring != NULL) + isc_mem_free(sig->mctx, sig->keyring); + sig->mctx = NULL; +} + +static inline isc_result_t +additionaldata_openpgpkey(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_openpgpkey); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_openpgpkey(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_openpgpkey); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_openpgpkey(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_openpgpkey); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_openpgpkey(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_openpgpkey); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_openpgpkey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_openpgpkey); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + return (isc_region_compare(&r1, &r2)); +} + +#endif /* RDATA_GENERIC_OPENPGPKEY_61_C */ diff --git a/lib/dns/rdata/generic/openpgpkey_61.h b/lib/dns/rdata/generic/openpgpkey_61.h new file mode 100644 index 0000000..7c68e7f --- /dev/null +++ b/lib/dns/rdata/generic/openpgpkey_61.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_OPENPGPKEY_61_H +#define GENERIC_OPENPGPKEY_61_H 1 + +typedef struct dns_rdata_openpgpkey { + dns_rdatacommon_t common; + isc_mem_t * mctx; + uint16_t length; + unsigned char * keyring; +} dns_rdata_openpgpkey_t; + +#endif /* GENERIC_OPENPGPKEY_61_H */ diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c new file mode 100644 index 0000000..b102cf2 --- /dev/null +++ b/lib/dns/rdata/generic/opt_41.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2671 */ + +#ifndef RDATA_GENERIC_OPT_41_C +#define RDATA_GENERIC_OPT_41_C + +#define RRTYPE_OPT_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON | \ + DNS_RDATATYPEATTR_META | \ + DNS_RDATATYPEATTR_NOTQUESTION) + +static inline isc_result_t +fromtext_opt(ARGS_FROMTEXT) { + /* + * OPT records do not have a text format. + */ + + REQUIRE(type == dns_rdatatype_opt); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(lexer); + UNUSED(origin); + UNUSED(options); + UNUSED(target); + UNUSED(callbacks); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline isc_result_t +totext_opt(ARGS_TOTEXT) { + isc_region_t r; + isc_region_t or; + uint16_t option; + uint16_t length; + char buf[sizeof("64000 64000")]; + + /* + * OPT records do not have a text format. + */ + + REQUIRE(rdata->type == dns_rdatatype_opt); + + dns_rdata_toregion(rdata, &r); + while (r.length > 0) { + option = uint16_fromregion(&r); + isc_region_consume(&r, 2); + length = uint16_fromregion(&r); + isc_region_consume(&r, 2); + snprintf(buf, sizeof(buf), "%u %u", option, length); + RETERR(str_totext(buf, target)); + INSIST(r.length >= length); + if (length > 0) { + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + or = r; + or.length = length; + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&or, 60, "", target)); + else + RETERR(isc_base64_totext(&or, tctx->width - 2, + tctx->linebreak, + target)); + isc_region_consume(&r, length); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + } + if (r.length > 0) + RETERR(str_totext(" ", target)); + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_opt(ARGS_FROMWIRE) { + isc_region_t sregion; + isc_region_t tregion; + uint16_t opt; + uint16_t length; + unsigned int total; + + REQUIRE(type == dns_rdatatype_opt); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length == 0) + return (ISC_R_SUCCESS); + total = 0; + while (sregion.length != 0) { + if (sregion.length < 4) + return (ISC_R_UNEXPECTEDEND); + opt = uint16_fromregion(&sregion); + isc_region_consume(&sregion, 2); + length = uint16_fromregion(&sregion); + isc_region_consume(&sregion, 2); + total += 4; + if (sregion.length < length) + return (ISC_R_UNEXPECTEDEND); + switch (opt) { + case DNS_OPT_CLIENT_SUBNET: { + uint16_t family; + uint8_t addrlen; + uint8_t scope; + uint8_t addrbytes; + + if (length < 4) + return (DNS_R_OPTERR); + family = uint16_fromregion(&sregion); + isc_region_consume(&sregion, 2); + addrlen = uint8_fromregion(&sregion); + isc_region_consume(&sregion, 1); + scope = uint8_fromregion(&sregion); + isc_region_consume(&sregion, 1); + + switch (family) { + case 0: + /* + * XXXMUKS: In queries and replies, if + * FAMILY is set to 0, SOURCE + * PREFIX-LENGTH and SCOPE PREFIX-LENGTH + * must be 0 and ADDRESS should not be + * present as the address and prefix + * lengths don't make sense because the + * family is unknown. + */ + if (addrlen != 0U || scope != 0U) + return (DNS_R_OPTERR); + break; + case 1: + if (addrlen > 32U || scope > 32U) + return (DNS_R_OPTERR); + break; + case 2: + if (addrlen > 128U || scope > 128U) + return (DNS_R_OPTERR); + break; + default: + return (DNS_R_OPTERR); + } + addrbytes = (addrlen + 7) / 8; + if (addrbytes + 4 != length) + return (DNS_R_OPTERR); + + if (addrbytes != 0U && (addrlen % 8) != 0) { + uint8_t bits = ~0U << (8 - (addrlen % 8)); + bits &= sregion.base[addrbytes - 1]; + if (bits != sregion.base[addrbytes - 1]) + return (DNS_R_OPTERR); + } + isc_region_consume(&sregion, addrbytes); + break; + } + case DNS_OPT_EXPIRE: + /* + * Request has zero length. Response is 32 bits. + */ + if (length != 0 && length != 4) + return (DNS_R_OPTERR); + isc_region_consume(&sregion, length); + break; + case DNS_OPT_COOKIE: + if (length != 8 && (length < 16 || length > 40)) + return (DNS_R_OPTERR); + isc_region_consume(&sregion, length); + break; + case DNS_OPT_KEY_TAG: + if (length == 0 || (length % 2) != 0) + return (DNS_R_OPTERR); + isc_region_consume(&sregion, length); + break; + default: + isc_region_consume(&sregion, length); + break; + } + total += length; + } + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + if (tregion.length < total) + return (ISC_R_NOSPACE); + memmove(tregion.base, sregion.base, total); + isc_buffer_forward(source, total); + isc_buffer_add(target, total); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_opt(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_opt); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_opt(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_opt); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_opt(ARGS_FROMSTRUCT) { + dns_rdata_opt_t *opt = source; + isc_region_t region; + uint16_t length; + + REQUIRE(type == dns_rdatatype_opt); + REQUIRE(source != NULL); + REQUIRE(opt->common.rdtype == type); + REQUIRE(opt->common.rdclass == rdclass); + REQUIRE(opt->options != NULL || opt->length == 0); + + UNUSED(type); + UNUSED(rdclass); + + region.base = opt->options; + region.length = opt->length; + while (region.length >= 4) { + isc_region_consume(®ion, 2); /* opt */ + length = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + if (region.length < length) + return (ISC_R_UNEXPECTEDEND); + isc_region_consume(®ion, length); + } + if (region.length != 0) + return (ISC_R_UNEXPECTEDEND); + + return (mem_tobuffer(target, opt->options, opt->length)); +} + +static inline isc_result_t +tostruct_opt(ARGS_TOSTRUCT) { + dns_rdata_opt_t *opt = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_opt); + REQUIRE(target != NULL); + + opt->common.rdclass = rdata->rdclass; + opt->common.rdtype = rdata->type; + ISC_LINK_INIT(&opt->common, link); + + dns_rdata_toregion(rdata, &r); + opt->length = r.length; + opt->options = mem_maybedup(mctx, r.base, r.length); + if (opt->options == NULL) + return (ISC_R_NOMEMORY); + + opt->offset = 0; + opt->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_opt(ARGS_FREESTRUCT) { + dns_rdata_opt_t *opt = source; + + REQUIRE(source != NULL); + REQUIRE(opt->common.rdtype == dns_rdatatype_opt); + + if (opt->mctx == NULL) + return; + + if (opt->options != NULL) + isc_mem_free(opt->mctx, opt->options); + opt->mctx = NULL; +} + +static inline isc_result_t +additionaldata_opt(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_opt); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_opt(ARGS_DIGEST) { + + /* + * OPT records are not digested. + */ + + REQUIRE(rdata->type == dns_rdatatype_opt); + + UNUSED(rdata); + UNUSED(digest); + UNUSED(arg); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline bool +checkowner_opt(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_opt); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (dns_name_equal(name, dns_rootname)); +} + +static inline bool +checknames_opt(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_opt); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_opt(ARGS_COMPARE) { + return (compare_opt(rdata1, rdata2)); +} + +isc_result_t +dns_rdata_opt_first(dns_rdata_opt_t *opt) { + + REQUIRE(opt != NULL); + REQUIRE(opt->common.rdtype == dns_rdatatype_opt); + REQUIRE(opt->options != NULL || opt->length == 0); + + if (opt->length == 0) + return (ISC_R_NOMORE); + + opt->offset = 0; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_opt_next(dns_rdata_opt_t *opt) { + isc_region_t r; + uint16_t length; + + REQUIRE(opt != NULL); + REQUIRE(opt->common.rdtype == dns_rdatatype_opt); + REQUIRE(opt->options != NULL && opt->length != 0); + REQUIRE(opt->offset < opt->length); + + INSIST(opt->offset + 4 <= opt->length); + r.base = opt->options + opt->offset + 2; + r.length = opt->length - opt->offset - 2; + length = uint16_fromregion(&r); + INSIST(opt->offset + 4 + length <= opt->length); + opt->offset = opt->offset + 4 + length; + if (opt->offset == opt->length) + return (ISC_R_NOMORE); + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_opt_current(dns_rdata_opt_t *opt, dns_rdata_opt_opcode_t *opcode) { + isc_region_t r; + + REQUIRE(opt != NULL); + REQUIRE(opcode != NULL); + REQUIRE(opt->common.rdtype == dns_rdatatype_opt); + REQUIRE(opt->options != NULL); + REQUIRE(opt->offset < opt->length); + + INSIST(opt->offset + 4 <= opt->length); + r.base = opt->options + opt->offset; + r.length = opt->length - opt->offset; + + opcode->opcode = uint16_fromregion(&r); + isc_region_consume(&r, 2); + opcode->length = uint16_fromregion(&r); + isc_region_consume(&r, 2); + opcode->data = r.base; + INSIST(opt->offset + 4 + opcode->length <= opt->length); + + return (ISC_R_SUCCESS); +} + +#endif /* RDATA_GENERIC_OPT_41_C */ diff --git a/lib/dns/rdata/generic/opt_41.h b/lib/dns/rdata/generic/opt_41.h new file mode 100644 index 0000000..5b31f4d --- /dev/null +++ b/lib/dns/rdata/generic/opt_41.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_OPT_41_H +#define GENERIC_OPT_41_H 1 + + +/*! + * \brief Per RFC2671 */ + +typedef struct dns_rdata_opt_opcode { + uint16_t opcode; + uint16_t length; + unsigned char *data; +} dns_rdata_opt_opcode_t; + +typedef struct dns_rdata_opt { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *options; + uint16_t length; + /* private */ + uint16_t offset; +} dns_rdata_opt_t; + +/* + * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done + * via rdatastructpre.h and rdatastructsuf.h. + */ + +isc_result_t +dns_rdata_opt_first(dns_rdata_opt_t *); + +isc_result_t +dns_rdata_opt_next(dns_rdata_opt_t *); + +isc_result_t +dns_rdata_opt_current(dns_rdata_opt_t *, dns_rdata_opt_opcode_t *); + +#endif /* GENERIC_OPT_41_H */ diff --git a/lib/dns/rdata/generic/proforma.c b/lib/dns/rdata/generic/proforma.c new file mode 100644 index 0000000..c31b29f --- /dev/null +++ b/lib/dns/rdata/generic/proforma.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef RDATA_GENERIC_#_#_C +#define RDATA_GENERIC_#_#_C + +#define RRTYPE_#_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_#(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_proforma.c#); + REQUIRE(rdclass == #); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline isc_result_t +totext_#(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata->rdclass == #); + REQUIRE(rdata->length != 0); /* XXX */ + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline isc_result_t +fromwire_#(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_proforma.c#); + REQUIRE(rdclass == #); + + /* NONE or GLOBAL14 */ + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline isc_result_t +towire_#(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata->rdclass == #); + REQUIRE(rdata->length != 0); /* XXX */ + + /* NONE or GLOBAL14 */ + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline int +compare_#(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == dns_rdatatype_proforma.crdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata1->rdclass == #); + REQUIRE(rdata1->length != 0); /* XXX */ + REQUIRE(rdata2->length != 0); /* XXX */ + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_#(ARGS_FROMSTRUCT) { + dns_rdata_#_t *# = source; + + REQUIRE(type == dns_rdatatype_proforma.c#); + REQUIRE(rdclass == #); + REQUIRE(source != NULL); + REQUIRE(#->common.rdtype == dns_rdatatype_proforma.ctype); + REQUIRE(#->common.rdclass == rdclass); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline isc_result_t +tostruct_#(ARGS_TOSTRUCT) { + + REQUIRE(rdata->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata->rdclass == #); + REQUIRE(rdata->length != 0); /* XXX */ + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline void +freestruct_#(ARGS_FREESTRUCT) { + dns_rdata_#_t *# = source; + + REQUIRE(source != NULL); + REQUIRE(#->common.rdtype == dns_rdatatype_proforma.c#); + REQUIRE(#->common.rdclass == #); + +} + +static inline isc_result_t +additionaldata_#(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata->rdclass == #); + + (void)add; + (void)arg; + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_#(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata->rdclass == #); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_#(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_proforma.c#); + REQUIRE(rdclass == #); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_#(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata->rdclass == #); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_#(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == dns_rdatatype_proforma.crdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_proforma.c#); + REQUIRE(rdata1->rdclass == #); + REQUIRE(rdata1->length != 0); /* XXX */ + REQUIRE(rdata2->length != 0); /* XXX */ + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +#endif /* RDATA_GENERIC_#_#_C */ diff --git a/lib/dns/rdata/generic/proforma.h b/lib/dns/rdata/generic/proforma.h new file mode 100644 index 0000000..cb49ee4 --- /dev/null +++ b/lib/dns/rdata/generic/proforma.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_PROFORMA_H +#define GENERIC_PROFORMA_H 1 + + +typedef struct dns_rdata_# { + dns_rdatacommon_t common; + isc_mem_t *mctx; /* if required */ + /* type & class specific elements */ +} dns_rdata_#_t; + +#endif /* GENERIC_PROFORMA_H */ diff --git a/lib/dns/rdata/generic/ptr_12.c b/lib/dns/rdata/generic/ptr_12.c new file mode 100644 index 0000000..a2f5ef1 --- /dev/null +++ b/lib/dns/rdata/generic/ptr_12.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_PTR_12_C +#define RDATA_GENERIC_PTR_12_C + +#define RRTYPE_PTR_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_ptr(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_ptr); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + if (rdclass == dns_rdataclass_in && + (options & DNS_RDATA_CHECKNAMES) != 0 && + (options & DNS_RDATA_CHECKREVERSE) != 0) { + bool ok; + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_ptr(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_ptr); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_ptr(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_ptr); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_ptr(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_ptr); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_ptr(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ptr); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_ptr(ARGS_FROMSTRUCT) { + dns_rdata_ptr_t *ptr = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_ptr); + REQUIRE(source != NULL); + REQUIRE(ptr->common.rdtype == type); + REQUIRE(ptr->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&ptr->ptr, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_ptr(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_ptr_t *ptr = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_ptr); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + ptr->common.rdclass = rdata->rdclass; + ptr->common.rdtype = rdata->type; + ISC_LINK_INIT(&ptr->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&ptr->ptr, NULL); + RETERR(name_duporclone(&name, mctx, &ptr->ptr)); + ptr->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_ptr(ARGS_FREESTRUCT) { + dns_rdata_ptr_t *ptr = source; + + REQUIRE(source != NULL); + REQUIRE(ptr->common.rdtype == dns_rdatatype_ptr); + + if (ptr->mctx == NULL) + return; + + dns_name_free(&ptr->ptr, ptr->mctx); + ptr->mctx = NULL; +} + +static inline isc_result_t +additionaldata_ptr(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_ptr); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_ptr(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_ptr); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_ptr(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_ptr); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA"; +static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 }; +static const dns_name_t ip6_arpa = + DNS_NAME_INITABSOLUTE(ip6_arpa_data, ip6_arpa_offsets); + +static unsigned char ip6_int_data[] = "\003IP6\003INT"; +static unsigned char ip6_int_offsets[] = { 0, 4, 8 }; +static const dns_name_t ip6_int = + DNS_NAME_INITABSOLUTE(ip6_int_data, ip6_int_offsets); + +static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA"; +static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 }; +static const dns_name_t in_addr_arpa = + DNS_NAME_INITABSOLUTE(in_addr_arpa_data, in_addr_arpa_offsets); + +static inline bool +checknames_ptr(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_ptr); + + if (rdata->rdclass != dns_rdataclass_in) + return (true); + + if (dns_name_isdnssd(owner)) + return (true); + + if (dns_name_issubdomain(owner, &in_addr_arpa) || + dns_name_issubdomain(owner, &ip6_arpa) || + dns_name_issubdomain(owner, &ip6_int)) { + dns_rdata_toregion(rdata, ®ion); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + } + return (true); +} + +static inline int +casecompare_ptr(ARGS_COMPARE) { + return (compare_ptr(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_PTR_12_C */ diff --git a/lib/dns/rdata/generic/ptr_12.h b/lib/dns/rdata/generic/ptr_12.h new file mode 100644 index 0000000..d71ebd9 --- /dev/null +++ b/lib/dns/rdata/generic/ptr_12.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_PTR_12_H +#define GENERIC_PTR_12_H 1 + + +typedef struct dns_rdata_ptr { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t ptr; +} dns_rdata_ptr_t; + +#endif /* GENERIC_PTR_12_H */ diff --git a/lib/dns/rdata/generic/rkey_57.c b/lib/dns/rdata/generic/rkey_57.c new file mode 100644 index 0000000..2475a48 --- /dev/null +++ b/lib/dns/rdata/generic/rkey_57.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_RKEY_57_C +#define RDATA_GENERIC_RKEY_57_C + +#define RRTYPE_RKEY_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_rkey(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_rkey); + + return (generic_fromtext_key(rdclass, type, lexer, origin, + options, target, callbacks)); +} + +static inline isc_result_t +totext_rkey(ARGS_TOTEXT) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_rkey); + + return (generic_totext_key(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_rkey(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_rkey); + + return (generic_fromwire_key(rdclass, type, source, dctx, + options, target)); +} + +static inline isc_result_t +towire_rkey(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_rkey); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_rkey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_rkey); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_rkey(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_rkey); + + return (generic_fromstruct_key(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_rkey(ARGS_TOSTRUCT) { + dns_rdata_rkey_t *rkey = target; + + REQUIRE(rkey != NULL); + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_rkey); + + rkey->common.rdclass = rdata->rdclass; + rkey->common.rdtype = rdata->type; + ISC_LINK_INIT(&rkey->common, link); + + return (generic_tostruct_key(rdata, target, mctx)); +} + +static inline void +freestruct_rkey(ARGS_FREESTRUCT) { + dns_rdata_rkey_t *rkey = (dns_rdata_rkey_t *) source; + + REQUIRE(rkey != NULL); + REQUIRE(rkey->common.rdtype == dns_rdatatype_rkey); + + generic_freestruct_key(source); +} + +static inline isc_result_t +additionaldata_rkey(ARGS_ADDLDATA) { + + REQUIRE(rdata->type == dns_rdatatype_rkey); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_rkey(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_rkey); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_rkey(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_rkey); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_rkey(ARGS_CHECKNAMES) { + + REQUIRE(rdata != NULL); + REQUIRE(rdata->type == dns_rdatatype_rkey); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_rkey(ARGS_COMPARE) { + + /* + * Treat ALG 253 (private DNS) subtype name case sensistively. + */ + return (compare_rkey(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_RKEY_57_C */ diff --git a/lib/dns/rdata/generic/rkey_57.h b/lib/dns/rdata/generic/rkey_57.h new file mode 100644 index 0000000..000a725 --- /dev/null +++ b/lib/dns/rdata/generic/rkey_57.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_RKEY_57_H +#define GENERIC_RKEY_57_H 1 + +typedef struct dns_rdata_key dns_rdata_rkey_t; + +#endif /* GENERIC_RKEY_57_H */ diff --git a/lib/dns/rdata/generic/rp_17.c b/lib/dns/rdata/generic/rp_17.c new file mode 100644 index 0000000..2e91565 --- /dev/null +++ b/lib/dns/rdata/generic/rp_17.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC1183 */ + +#ifndef RDATA_GENERIC_RP_17_C +#define RDATA_GENERIC_RP_17_C + +#define RRTYPE_RP_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_rp(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + int i; + bool ok; + + REQUIRE(type == dns_rdatatype_rp); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + if (origin == NULL) + origin = dns_rootname; + + for (i = 0; i < 2; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, + options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0 && i == 0) + ok = dns_name_ismailbox(&name); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_rp(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t rmail; + dns_name_t email; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_rp); + REQUIRE(rdata->length != 0); + + dns_name_init(&rmail, NULL); + dns_name_init(&email, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + + dns_name_fromregion(&rmail, ®ion); + isc_region_consume(®ion, rmail.length); + + dns_name_fromregion(&email, ®ion); + isc_region_consume(®ion, email.length); + + sub = name_prefix(&rmail, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + RETERR(str_totext(" ", target)); + + sub = name_prefix(&email, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_rp(ARGS_FROMWIRE) { + dns_name_t rmail; + dns_name_t email; + + REQUIRE(type == dns_rdatatype_rp); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&rmail, NULL); + dns_name_init(&email, NULL); + + RETERR(dns_name_fromwire(&rmail, source, dctx, options, target)); + return (dns_name_fromwire(&email, source, dctx, options, target)); +} + +static inline isc_result_t +towire_rp(ARGS_TOWIRE) { + isc_region_t region; + dns_name_t rmail; + dns_name_t email; + dns_offsets_t roffsets; + dns_offsets_t eoffsets; + + REQUIRE(rdata->type == dns_rdatatype_rp); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_name_init(&rmail, roffsets); + dns_name_init(&email, eoffsets); + + dns_rdata_toregion(rdata, ®ion); + + dns_name_fromregion(&rmail, ®ion); + isc_region_consume(®ion, rmail.length); + + RETERR(dns_name_towire(&rmail, cctx, target)); + + dns_name_fromregion(&rmail, ®ion); + isc_region_consume(®ion, rmail.length); + + return (dns_name_towire(&rmail, cctx, target)); +} + +static inline int +compare_rp(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_rp); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_rp(ARGS_FROMSTRUCT) { + dns_rdata_rp_t *rp = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_rp); + REQUIRE(source != NULL); + REQUIRE(rp->common.rdtype == type); + REQUIRE(rp->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&rp->mail, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + dns_name_toregion(&rp->text, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_rp(ARGS_TOSTRUCT) { + isc_result_t result; + isc_region_t region; + dns_rdata_rp_t *rp = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rp); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + rp->common.rdclass = rdata->rdclass; + rp->common.rdtype = rdata->type; + ISC_LINK_INIT(&rp->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&rp->mail, NULL); + RETERR(name_duporclone(&name, mctx, &rp->mail)); + isc_region_consume(®ion, name_length(&name)); + dns_name_fromregion(&name, ®ion); + dns_name_init(&rp->text, NULL); + result = name_duporclone(&name, mctx, &rp->text); + if (result != ISC_R_SUCCESS) + goto cleanup; + + rp->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&rp->mail, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_rp(ARGS_FREESTRUCT) { + dns_rdata_rp_t *rp = source; + + REQUIRE(source != NULL); + REQUIRE(rp->common.rdtype == dns_rdatatype_rp); + + if (rp->mctx == NULL) + return; + + dns_name_free(&rp->mail, rp->mctx); + dns_name_free(&rp->text, rp->mctx); + rp->mctx = NULL; +} + +static inline isc_result_t +additionaldata_rp(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_rp); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_rp(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rp); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + + dns_name_fromregion(&name, &r); + RETERR(dns_name_digest(&name, digest, arg)); + isc_region_consume(&r, name_length(&name)); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_rp(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_rp); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_rp(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rp); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ismailbox(&name)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_rp(ARGS_COMPARE) { + return (compare_rp(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_RP_17_C */ diff --git a/lib/dns/rdata/generic/rp_17.h b/lib/dns/rdata/generic/rp_17.h new file mode 100644 index 0000000..31b5768 --- /dev/null +++ b/lib/dns/rdata/generic/rp_17.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_RP_17_H +#define GENERIC_RP_17_H 1 + + +/*! + * \brief Per RFC1183 */ + +typedef struct dns_rdata_rp { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t mail; + dns_name_t text; +} dns_rdata_rp_t; + + +#endif /* GENERIC_RP_17_H */ diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c new file mode 100644 index 0000000..fb945ff --- /dev/null +++ b/lib/dns/rdata/generic/rrsig_46.c @@ -0,0 +1,613 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_RRSIG_46_C +#define RDATA_GENERIC_RRSIG_46_C + +#define RRTYPE_RRSIG_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) + +static inline isc_result_t +fromtext_rrsig(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char c; + long i; + dns_rdatatype_t covered; + char *e; + isc_result_t result; + dns_name_t name; + isc_buffer_t buffer; + uint32_t time_signed, time_expire; + + REQUIRE(type == dns_rdatatype_rrsig); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Type covered. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + i = strtol(DNS_AS_STR(token), &e, 10); + if (i < 0 || i > 65535) + RETTOK(ISC_R_RANGE); + if (*e != 0) + RETTOK(result); + covered = (dns_rdatatype_t)i; + } + RETERR(uint16_tobuffer(covered, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Labels. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + c = (unsigned char)token.value.as_ulong; + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Original ttl. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* + * Signature expiration. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strlen(DNS_AS_STR(token)) <= 10U && + *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') { + char *end; + unsigned long u; + uint64_t u64; + + u64 = u = strtoul(DNS_AS_STR(token), &end, 10); + if (u == ULONG_MAX || *end != 0) + RETTOK(DNS_R_SYNTAX); + if (u64 > 0xffffffffUL) + RETTOK(ISC_R_RANGE); + time_expire = u; + } else + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire)); + RETERR(uint32_tobuffer(time_expire, target)); + + /* + * Time signed. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (strlen(DNS_AS_STR(token)) <= 10U && + *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') { + char *end; + unsigned long u; + uint64_t u64; + + u64 = u = strtoul(DNS_AS_STR(token), &end, 10); + if (u == ULONG_MAX || *end != 0) + RETTOK(DNS_R_SYNTAX); + if (u64 > 0xffffffffUL) + RETTOK(ISC_R_RANGE); + time_signed = u; + } else + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed)); + RETERR(uint32_tobuffer(time_signed, target)); + + /* + * Key footprint. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Signer. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + /* + * Sig. + */ + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_rrsig(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("4294967295")]; /* Also TYPE65000. */ + dns_rdatatype_t covered; + unsigned long ttl; + unsigned long when; + unsigned long exp; + unsigned long foot; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rrsig); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* + * Type covered. + */ + covered = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + /* + * XXXAG We should have something like dns_rdatatype_isknown() + * that does the right thing with type 0. + */ + if (dns_rdatatype_isknown(covered) && covered != 0) { + RETERR(dns_rdatatype_totext(covered, target)); + } else { + snprintf(buf, sizeof(buf), "TYPE%u", covered); + RETERR(str_totext(buf, target)); + } + RETERR(str_totext(" ", target)); + + /* + * Algorithm. + */ + snprintf(buf, sizeof(buf), "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Labels. + */ + snprintf(buf, sizeof(buf), "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Ttl. + */ + ttl = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + snprintf(buf, sizeof(buf), "%lu", ttl); + RETERR(str_totext(buf, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + + /* + * Sig exp. + */ + exp = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(exp, target)); + RETERR(str_totext(" ", target)); + + /* + * Time signed. + */ + when = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(when, target)); + RETERR(str_totext(" ", target)); + + /* + * Footprint. + */ + foot = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%lu", foot); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Signer. + */ + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + RETERR(dns_name_totext(&name, false, target)); + + /* + * Sig. + */ + RETERR(str_totext(tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + } else + RETERR(str_totext("[omitted]", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_rrsig(ARGS_FROMWIRE) { + isc_region_t sr; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_rrsig); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + isc_buffer_activeregion(source, &sr); + /* + * type covered: 2 + * algorithm: 1 + * labels: 1 + * original ttl: 4 + * signature expiration: 4 + * time signed: 4 + * key footprint: 2 + */ + if (sr.length < 18) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, 18); + RETERR(mem_tobuffer(target, sr.base, 18)); + + /* + * Signer. + */ + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + /* + * Sig. + */ + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_rrsig(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_rrsig); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_rdata_toregion(rdata, &sr); + /* + * type covered: 2 + * algorithm: 1 + * labels: 1 + * original ttl: 4 + * signature expiration: 4 + * time signed: 4 + * key footprint: 2 + */ + RETERR(mem_tobuffer(target, sr.base, 18)); + isc_region_consume(&sr, 18); + + /* + * Signer. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + RETERR(dns_name_towire(&name, cctx, target)); + + /* + * Signature. + */ + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_rrsig(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_rrsig); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_rrsig(ARGS_FROMSTRUCT) { + dns_rdata_rrsig_t *sig = source; + + REQUIRE(type == dns_rdatatype_rrsig); + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == type); + REQUIRE(sig->common.rdclass == rdclass); + REQUIRE(sig->signature != NULL || sig->siglen == 0); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Type covered. + */ + RETERR(uint16_tobuffer(sig->covered, target)); + + /* + * Algorithm. + */ + RETERR(uint8_tobuffer(sig->algorithm, target)); + + /* + * Labels. + */ + RETERR(uint8_tobuffer(sig->labels, target)); + + /* + * Original TTL. + */ + RETERR(uint32_tobuffer(sig->originalttl, target)); + + /* + * Expire time. + */ + RETERR(uint32_tobuffer(sig->timeexpire, target)); + + /* + * Time signed. + */ + RETERR(uint32_tobuffer(sig->timesigned, target)); + + /* + * Key ID. + */ + RETERR(uint16_tobuffer(sig->keyid, target)); + + /* + * Signer name. + */ + RETERR(name_tobuffer(&sig->signer, target)); + + /* + * Signature. + */ + return (mem_tobuffer(target, sig->signature, sig->siglen)); +} + +static inline isc_result_t +tostruct_rrsig(ARGS_TOSTRUCT) { + isc_region_t sr; + dns_rdata_rrsig_t *sig = target; + dns_name_t signer; + + REQUIRE(rdata->type == dns_rdatatype_rrsig); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + sig->common.rdclass = rdata->rdclass; + sig->common.rdtype = rdata->type; + ISC_LINK_INIT(&sig->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Type covered. + */ + sig->covered = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Algorithm. + */ + sig->algorithm = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Labels. + */ + sig->labels = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Original TTL. + */ + sig->originalttl = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Expire time. + */ + sig->timeexpire = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Time signed. + */ + sig->timesigned = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Key ID. + */ + sig->keyid = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + dns_name_init(&signer, NULL); + dns_name_fromregion(&signer, &sr); + dns_name_init(&sig->signer, NULL); + RETERR(name_duporclone(&signer, mctx, &sig->signer)); + isc_region_consume(&sr, name_length(&sig->signer)); + + /* + * Signature. + */ + sig->siglen = sr.length; + sig->signature = mem_maybedup(mctx, sr.base, sig->siglen); + if (sig->signature == NULL) + goto cleanup; + + + sig->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&sig->signer, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_rrsig(ARGS_FREESTRUCT) { + dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *) source; + + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == dns_rdatatype_rrsig); + + if (sig->mctx == NULL) + return; + + dns_name_free(&sig->signer, sig->mctx); + if (sig->signature != NULL) + isc_mem_free(sig->mctx, sig->signature); + sig->mctx = NULL; +} + +static inline isc_result_t +additionaldata_rrsig(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_rrsig); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_rrsig(ARGS_DIGEST) { + + REQUIRE(rdata->type == dns_rdatatype_rrsig); + + UNUSED(rdata); + UNUSED(digest); + UNUSED(arg); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline dns_rdatatype_t +covers_rrsig(dns_rdata_t *rdata) { + dns_rdatatype_t type; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_rrsig); + + dns_rdata_toregion(rdata, &r); + type = uint16_fromregion(&r); + + return (type); +} + +static inline bool +checkowner_rrsig(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_rrsig); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_rrsig(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_rrsig); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_rrsig(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_rrsig); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + INSIST(r1.length > 18); + INSIST(r2.length > 18); + r1.length = 18; + r2.length = 18; + order = isc_region_compare(&r1, &r2); + if (order != 0) + return (order); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + isc_region_consume(&r1, 18); + isc_region_consume(&r2, 18); + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + + return (isc_region_compare(&r1, &r2)); +} + +#endif /* RDATA_GENERIC_RRSIG_46_C */ diff --git a/lib/dns/rdata/generic/rrsig_46.h b/lib/dns/rdata/generic/rrsig_46.h new file mode 100644 index 0000000..6dfbd42 --- /dev/null +++ b/lib/dns/rdata/generic/rrsig_46.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_DNSSIG_46_H +#define GENERIC_DNSSIG_46_H 1 + + +/*! + * \brief Per RFC2535 */ +typedef struct dns_rdata_rrsig { + dns_rdatacommon_t common; + isc_mem_t * mctx; + dns_rdatatype_t covered; + dns_secalg_t algorithm; + uint8_t labels; + uint32_t originalttl; + uint32_t timeexpire; + uint32_t timesigned; + uint16_t keyid; + dns_name_t signer; + uint16_t siglen; + unsigned char * signature; +} dns_rdata_rrsig_t; + + +#endif /* GENERIC_DNSSIG_46_H */ diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c new file mode 100644 index 0000000..e6450cb --- /dev/null +++ b/lib/dns/rdata/generic/rt_21.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1183 */ + +#ifndef RDATA_GENERIC_RT_21_C +#define RDATA_GENERIC_RT_21_C + +#define RRTYPE_RT_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_rt(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + bool ok; + + REQUIRE(type == dns_rdatatype_rt); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_rt(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_rt); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_rt(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sregion; + isc_region_t tregion; + + REQUIRE(type == dns_rdatatype_rt); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + if (tregion.length < 2) + return (ISC_R_NOSPACE); + if (sregion.length < 2) + return (ISC_R_UNEXPECTEDEND); + memmove(tregion.base, sregion.base, 2); + isc_buffer_forward(source, 2); + isc_buffer_add(target, 2); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_rt(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + isc_region_t tr; + + REQUIRE(rdata->type == dns_rdatatype_rt); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + isc_buffer_availableregion(target, &tr); + dns_rdata_toregion(rdata, ®ion); + if (tr.length < 2) + return (ISC_R_NOSPACE); + memmove(tr.base, region.base, 2); + isc_region_consume(®ion, 2); + isc_buffer_add(target, 2); + + dns_name_init(&name, offsets); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_rt(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_rt); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + order = memcmp(rdata1->data, rdata2->data, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 2); + isc_region_consume(®ion2, 2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_rt(ARGS_FROMSTRUCT) { + dns_rdata_rt_t *rt = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_rt); + REQUIRE(source != NULL); + REQUIRE(rt->common.rdtype == type); + REQUIRE(rt->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(rt->preference, target)); + dns_name_toregion(&rt->host, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_rt(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_rt_t *rt = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rt); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + rt->common.rdclass = rdata->rdclass; + rt->common.rdtype = rdata->type; + ISC_LINK_INIT(&rt->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + rt->preference = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + dns_name_init(&rt->host, NULL); + RETERR(name_duporclone(&name, mctx, &rt->host)); + + rt->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_rt(ARGS_FREESTRUCT) { + dns_rdata_rt_t *rt = source; + + REQUIRE(source != NULL); + REQUIRE(rt->common.rdtype == dns_rdatatype_rt); + + if (rt->mctx == NULL) + return; + + dns_name_free(&rt->host, rt->mctx); + rt->mctx = NULL; +} + +static inline isc_result_t +additionaldata_rt(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_rt); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + + result = (add)(arg, &name, dns_rdatatype_x25); + if (result != ISC_R_SUCCESS) + return (result); + result = (add)(arg, &name, dns_rdatatype_isdn); + if (result != ISC_R_SUCCESS) + return (result); + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_rt(ARGS_DIGEST) { + isc_region_t r1, r2; + isc_result_t result; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rt); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + isc_region_consume(&r2, 2); + r1.length = 2; + result = (digest)(arg, &r1); + if (result != ISC_R_SUCCESS) + return (result); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_rt(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_rt); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_rt(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_rt); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_rt(ARGS_COMPARE) { + return (compare_rt(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_RT_21_C */ diff --git a/lib/dns/rdata/generic/rt_21.h b/lib/dns/rdata/generic/rt_21.h new file mode 100644 index 0000000..a9082c7 --- /dev/null +++ b/lib/dns/rdata/generic/rt_21.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_RT_21_H +#define GENERIC_RT_21_H 1 + + +/*! + * \brief Per RFC1183 */ + +typedef struct dns_rdata_rt { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t preference; + dns_name_t host; +} dns_rdata_rt_t; + +#endif /* GENERIC_RT_21_H */ diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c new file mode 100644 index 0000000..ca0ce4e --- /dev/null +++ b/lib/dns/rdata/generic/sig_24.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_SIG_24_C +#define RDATA_GENERIC_SIG_24_C + +#define RRTYPE_SIG_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_sig(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char c; + long i; + dns_rdatatype_t covered; + char *e; + isc_result_t result; + dns_name_t name; + isc_buffer_t buffer; + uint32_t time_signed, time_expire; + + REQUIRE(type == dns_rdatatype_sig); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Type covered. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + i = strtol(DNS_AS_STR(token), &e, 10); + if (i < 0 || i > 65535) + RETTOK(ISC_R_RANGE); + if (*e != 0) + RETTOK(result); + covered = (dns_rdatatype_t)i; + } + RETERR(uint16_tobuffer(covered, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Labels. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + c = (unsigned char)token.value.as_ulong; + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Original ttl. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* + * Signature expiration. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire)); + RETERR(uint32_tobuffer(time_expire, target)); + + /* + * Time signed. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed)); + RETERR(uint32_tobuffer(time_signed, target)); + + /* + * Key footprint. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Signer. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + /* + * Sig. + */ + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_sig(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("4294967295")]; + dns_rdatatype_t covered; + unsigned long ttl; + unsigned long when; + unsigned long exp; + unsigned long foot; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_sig); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* + * Type covered. + */ + covered = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + /* + * XXXAG We should have something like dns_rdatatype_isknown() + * that does the right thing with type 0. + */ + if (dns_rdatatype_isknown(covered) && covered != 0) { + RETERR(dns_rdatatype_totext(covered, target)); + } else { + snprintf(buf, sizeof(buf), "%u", covered); + RETERR(str_totext(buf, target)); + } + RETERR(str_totext(" ", target)); + + /* + * Algorithm. + */ + snprintf(buf, sizeof(buf), "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Labels. + */ + snprintf(buf, sizeof(buf), "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Ttl. + */ + ttl = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + snprintf(buf, sizeof(buf), "%lu", ttl); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Sig exp. + */ + exp = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(exp, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + + /* + * Time signed. + */ + when = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(when, target)); + RETERR(str_totext(" ", target)); + + /* + * Footprint. + */ + foot = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%lu", foot); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Signer. + */ + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + /* + * Sig. + */ + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_sig(ARGS_FROMWIRE) { + isc_region_t sr; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_sig); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + isc_buffer_activeregion(source, &sr); + /* + * type covered: 2 + * algorithm: 1 + * labels: 1 + * original ttl: 4 + * signature expiration: 4 + * time signed: 4 + * key footprint: 2 + */ + if (sr.length < 18) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, 18); + RETERR(mem_tobuffer(target, sr.base, 18)); + + /* + * Signer. + */ + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + /* + * Sig. + */ + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_sig(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_sig); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_rdata_toregion(rdata, &sr); + /* + * type covered: 2 + * algorithm: 1 + * labels: 1 + * original ttl: 4 + * signature expiration: 4 + * time signed: 4 + * key footprint: 2 + */ + RETERR(mem_tobuffer(target, sr.base, 18)); + isc_region_consume(&sr, 18); + + /* + * Signer. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + isc_region_consume(&sr, name_length(&name)); + RETERR(dns_name_towire(&name, cctx, target)); + + /* + * Signature. + */ + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_sig(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_sig); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + INSIST(r1.length > 18); + INSIST(r2.length > 18); + r1.length = 18; + r2.length = 18; + order = isc_region_compare(&r1, &r2); + if (order != 0) + return (order); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + isc_region_consume(&r1, 18); + isc_region_consume(&r2, 18); + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_sig(ARGS_FROMSTRUCT) { + dns_rdata_sig_t *sig = source; + + REQUIRE(type == dns_rdatatype_sig); + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == type); + REQUIRE(sig->common.rdclass == rdclass); + REQUIRE(sig->signature != NULL || sig->siglen == 0); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Type covered. + */ + RETERR(uint16_tobuffer(sig->covered, target)); + + /* + * Algorithm. + */ + RETERR(uint8_tobuffer(sig->algorithm, target)); + + /* + * Labels. + */ + RETERR(uint8_tobuffer(sig->labels, target)); + + /* + * Original TTL. + */ + RETERR(uint32_tobuffer(sig->originalttl, target)); + + /* + * Expire time. + */ + RETERR(uint32_tobuffer(sig->timeexpire, target)); + + /* + * Time signed. + */ + RETERR(uint32_tobuffer(sig->timesigned, target)); + + /* + * Key ID. + */ + RETERR(uint16_tobuffer(sig->keyid, target)); + + /* + * Signer name. + */ + RETERR(name_tobuffer(&sig->signer, target)); + + /* + * Signature. + */ + return (mem_tobuffer(target, sig->signature, sig->siglen)); +} + +static inline isc_result_t +tostruct_sig(ARGS_TOSTRUCT) { + isc_region_t sr; + dns_rdata_sig_t *sig = target; + dns_name_t signer; + + REQUIRE(rdata->type == dns_rdatatype_sig); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + sig->common.rdclass = rdata->rdclass; + sig->common.rdtype = rdata->type; + ISC_LINK_INIT(&sig->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Type covered. + */ + sig->covered = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Algorithm. + */ + sig->algorithm = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Labels. + */ + sig->labels = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Original TTL. + */ + sig->originalttl = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Expire time. + */ + sig->timeexpire = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Time signed. + */ + sig->timesigned = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Key ID. + */ + sig->keyid = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + dns_name_init(&signer, NULL); + dns_name_fromregion(&signer, &sr); + dns_name_init(&sig->signer, NULL); + RETERR(name_duporclone(&signer, mctx, &sig->signer)); + isc_region_consume(&sr, name_length(&sig->signer)); + + /* + * Signature. + */ + sig->siglen = sr.length; + sig->signature = mem_maybedup(mctx, sr.base, sig->siglen); + if (sig->signature == NULL) + goto cleanup; + + + sig->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&sig->signer, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_sig(ARGS_FREESTRUCT) { + dns_rdata_sig_t *sig = (dns_rdata_sig_t *) source; + + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == dns_rdatatype_sig); + + if (sig->mctx == NULL) + return; + + dns_name_free(&sig->signer, sig->mctx); + if (sig->signature != NULL) + isc_mem_free(sig->mctx, sig->signature); + sig->mctx = NULL; +} + +static inline isc_result_t +additionaldata_sig(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_sig); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_sig(ARGS_DIGEST) { + + REQUIRE(rdata->type == dns_rdatatype_sig); + + UNUSED(rdata); + UNUSED(digest); + UNUSED(arg); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline dns_rdatatype_t +covers_sig(dns_rdata_t *rdata) { + dns_rdatatype_t type; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_sig); + + dns_rdata_toregion(rdata, &r); + type = uint16_fromregion(&r); + + return (type); +} + +static inline bool +checkowner_sig(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_sig); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_sig(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_sig); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_sig(ARGS_COMPARE) { + return (compare_sig(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_SIG_24_C */ diff --git a/lib/dns/rdata/generic/sig_24.h b/lib/dns/rdata/generic/sig_24.h new file mode 100644 index 0000000..a3882d9 --- /dev/null +++ b/lib/dns/rdata/generic/sig_24.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_SIG_24_H +#define GENERIC_SIG_24_H 1 + + +/*! + * \brief Per RFC2535 */ + +typedef struct dns_rdata_sig_t { + dns_rdatacommon_t common; + isc_mem_t * mctx; + dns_rdatatype_t covered; + dns_secalg_t algorithm; + uint8_t labels; + uint32_t originalttl; + uint32_t timeexpire; + uint32_t timesigned; + uint16_t keyid; + dns_name_t signer; + uint16_t siglen; + unsigned char * signature; +} dns_rdata_sig_t; + + +#endif /* GENERIC_SIG_24_H */ diff --git a/lib/dns/rdata/generic/sink_40.c b/lib/dns/rdata/generic/sink_40.c new file mode 100644 index 0000000..1289414 --- /dev/null +++ b/lib/dns/rdata/generic/sink_40.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_SINK_40_C +#define RDATA_GENERIC_SINK_40_C + +#include <dst/dst.h> + +#define RRTYPE_SINK_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_sink(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_sink); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* meaning */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* coding */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* subcoding */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + return(isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_sink(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("255 255 255")]; + uint8_t meaning, coding, subcoding; + + REQUIRE(rdata->type == dns_rdatatype_sink); + REQUIRE(rdata->length >= 3); + + dns_rdata_toregion(rdata, &sr); + + /* Meaning, Coding and Subcoding */ + meaning = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + coding = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + subcoding = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u %u %u", meaning, coding, subcoding); + RETERR(str_totext(buf, target)); + + if (sr.length == 0U) + return (ISC_R_SUCCESS); + + /* data */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + + RETERR(str_totext(tctx->linebreak, target)); + + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_sink(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_sink); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 3) + return (ISC_R_UNEXPECTEDEND); + + RETERR(mem_tobuffer(target, sr.base, sr.length)); + isc_buffer_forward(source, sr.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_sink(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_sink); + REQUIRE(rdata->length >= 3); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_sink(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_sink); + REQUIRE(rdata1->length >= 3); + REQUIRE(rdata2->length >= 3); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_sink(ARGS_FROMSTRUCT) { + dns_rdata_sink_t *sink = source; + + REQUIRE(type == dns_rdatatype_sink); + REQUIRE(source != NULL); + REQUIRE(sink->common.rdtype == type); + REQUIRE(sink->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + /* Meaning */ + RETERR(uint8_tobuffer(sink->meaning, target)); + + /* Coding */ + RETERR(uint8_tobuffer(sink->coding, target)); + + /* Subcoding */ + RETERR(uint8_tobuffer(sink->subcoding, target)); + + /* Data */ + return (mem_tobuffer(target, sink->data, sink->datalen)); +} + +static inline isc_result_t +tostruct_sink(ARGS_TOSTRUCT) { + dns_rdata_sink_t *sink = target; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_sink); + REQUIRE(target != NULL); + REQUIRE(rdata->length >= 3); + + sink->common.rdclass = rdata->rdclass; + sink->common.rdtype = rdata->type; + ISC_LINK_INIT(&sink->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* Meaning */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + sink->meaning = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Coding */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + sink->coding = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Subcoding */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + sink->subcoding = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Data */ + sink->datalen = sr.length; + sink->data = mem_maybedup(mctx, sr.base, sink->datalen); + if (sink->data == NULL) + return (ISC_R_NOMEMORY); + + sink->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_sink(ARGS_FREESTRUCT) { + dns_rdata_sink_t *sink = (dns_rdata_sink_t *) source; + + REQUIRE(source != NULL); + REQUIRE(sink->common.rdtype == dns_rdatatype_sink); + + if (sink->mctx == NULL) + return; + + if (sink->data != NULL) + isc_mem_free(sink->mctx, sink->data); + sink->mctx = NULL; +} + +static inline isc_result_t +additionaldata_sink(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_sink); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_sink(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_sink); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_sink(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_sink); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_sink(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_sink); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_sink(ARGS_COMPARE) { + return (compare_sink(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_SINK_40_C */ diff --git a/lib/dns/rdata/generic/sink_40.h b/lib/dns/rdata/generic/sink_40.h new file mode 100644 index 0000000..4e6e01e --- /dev/null +++ b/lib/dns/rdata/generic/sink_40.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_SINK_40_H +#define GENERIC_SINK_40_H 1 + +typedef struct dns_rdata_sink_t { + dns_rdatacommon_t common; + isc_mem_t * mctx; + uint8_t meaning; + uint8_t coding; + uint8_t subcoding; + uint16_t datalen; + unsigned char * data; +} dns_rdata_sink_t; + +#endif /* GENERIC_SINK_40_H */ diff --git a/lib/dns/rdata/generic/smimea_53.c b/lib/dns/rdata/generic/smimea_53.c new file mode 100644 index 0000000..efd7f01 --- /dev/null +++ b/lib/dns/rdata/generic/smimea_53.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_SMIMEA_53_C +#define RDATA_GENERIC_SMIMEA_53_C + +#define RRTYPE_SMIMEA_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_smimea(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_smimea); + + return (generic_fromtext_tlsa(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_smimea(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_smimea); + + return (generic_totext_tlsa(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_smimea(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_smimea); + + return (generic_fromwire_tlsa(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_smimea(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_smimea); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_smimea(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_smimea); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_smimea(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_smimea); + + return (generic_fromstruct_tlsa(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_smimea(ARGS_TOSTRUCT) { + dns_rdata_smimea_t *smimea = target; + + REQUIRE(rdata->type == dns_rdatatype_smimea); + REQUIRE(target != NULL); + + smimea->common.rdclass = rdata->rdclass; + smimea->common.rdtype = rdata->type; + ISC_LINK_INIT(&smimea->common, link); + + return (generic_tostruct_tlsa(rdata, target, mctx)); +} + +static inline void +freestruct_smimea(ARGS_FREESTRUCT) { + dns_rdata_smimea_t *smimea = source; + + REQUIRE(source != NULL); + REQUIRE(smimea->common.rdtype == dns_rdatatype_smimea); + + generic_freestruct_tlsa(source); +} + +static inline isc_result_t +additionaldata_smimea(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_smimea); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_smimea(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_smimea); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_smimea(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_smimea); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_smimea(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_smimea); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_smimea(ARGS_COMPARE) { + return (compare_smimea(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_SMIMEA_53_C */ diff --git a/lib/dns/rdata/generic/smimea_53.h b/lib/dns/rdata/generic/smimea_53.h new file mode 100644 index 0000000..cabec2b --- /dev/null +++ b/lib/dns/rdata/generic/smimea_53.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_SMIMEA_53_H +#define GENERIC_SMIMEA_53_H 1 + +typedef struct dns_rdata_tlsa dns_rdata_smimea_t; + +#endif /* GENERIC_SMIMEA_53_H */ diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c new file mode 100644 index 0000000..c21d64b --- /dev/null +++ b/lib/dns/rdata/generic/soa_6.c @@ -0,0 +1,438 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_SOA_6_C +#define RDATA_GENERIC_SOA_6_C + +#define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON) + +static inline isc_result_t +fromtext_soa(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + int i; + uint32_t n; + bool ok; + + REQUIRE(type == dns_rdatatype_soa); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + if (origin == NULL) + origin = dns_rootname; + + for (i = 0; i < 2; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, + options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + switch (i) { + case 0: + ok = dns_name_ishostname(&name, false); + break; + case 1: + ok = dns_name_ismailbox(&name); + break; + + } + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + } + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + for (i = 0; i < 4; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + false)); + RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n)); + RETERR(uint32_tobuffer(n, target)); + } + + return (ISC_R_SUCCESS); +} + +static const char *soa_fieldnames[5] = { + "serial", "refresh", "retry", "expire", "minimum" +}; + +static inline isc_result_t +totext_soa(ARGS_TOTEXT) { + isc_region_t dregion; + dns_name_t mname; + dns_name_t rname; + dns_name_t prefix; + bool sub; + int i; + bool multiline; + bool comm; + + REQUIRE(rdata->type == dns_rdatatype_soa); + REQUIRE(rdata->length != 0); + + multiline = (tctx->flags & DNS_STYLEFLAG_MULTILINE); + comm = (multiline) ? + (tctx->flags & DNS_STYLEFLAG_RRCOMMENT) : + false; + + dns_name_init(&mname, NULL); + dns_name_init(&rname, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, &dregion); + + dns_name_fromregion(&mname, &dregion); + isc_region_consume(&dregion, name_length(&mname)); + + dns_name_fromregion(&rname, &dregion); + isc_region_consume(&dregion, name_length(&rname)); + + sub = name_prefix(&mname, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + RETERR(str_totext(" ", target)); + + sub = name_prefix(&rname, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + if (multiline) + RETERR(str_totext(" (" , target)); + RETERR(str_totext(tctx->linebreak, target)); + + for (i = 0; i < 5; i++) { + char buf[sizeof("0123456789 ; ")]; + unsigned long num; + num = uint32_fromregion(&dregion); + isc_region_consume(&dregion, 4); + snprintf(buf, sizeof(buf), comm ? "%-10lu ; " : "%lu", num); + RETERR(str_totext(buf, target)); + if (comm) { + RETERR(str_totext(soa_fieldnames[i], target)); + /* Print times in week/day/hour/minute/second form */ + if (i >= 1) { + RETERR(str_totext(" (", target)); + RETERR(dns_ttl_totext(num, true, target)); + RETERR(str_totext(")", target)); + } + RETERR(str_totext(tctx->linebreak, target)); + } else if (i < 4) { + RETERR(str_totext(tctx->linebreak, target)); + } + } + + if (multiline) + RETERR(str_totext(")", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_soa(ARGS_FROMWIRE) { + dns_name_t mname; + dns_name_t rname; + isc_region_t sregion; + isc_region_t tregion; + + REQUIRE(type == dns_rdatatype_soa); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&mname, NULL); + dns_name_init(&rname, NULL); + + RETERR(dns_name_fromwire(&mname, source, dctx, options, target)); + RETERR(dns_name_fromwire(&rname, source, dctx, options, target)); + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + + if (sregion.length < 20) + return (ISC_R_UNEXPECTEDEND); + if (tregion.length < 20) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 20); + isc_buffer_forward(source, 20); + isc_buffer_add(target, 20); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_soa(ARGS_TOWIRE) { + isc_region_t sregion; + isc_region_t tregion; + dns_name_t mname; + dns_name_t rname; + dns_offsets_t moffsets; + dns_offsets_t roffsets; + + REQUIRE(rdata->type == dns_rdatatype_soa); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + + dns_name_init(&mname, moffsets); + dns_name_init(&rname, roffsets); + + dns_rdata_toregion(rdata, &sregion); + + dns_name_fromregion(&mname, &sregion); + isc_region_consume(&sregion, name_length(&mname)); + RETERR(dns_name_towire(&mname, cctx, target)); + + dns_name_fromregion(&rname, &sregion); + isc_region_consume(&sregion, name_length(&rname)); + RETERR(dns_name_towire(&rname, cctx, target)); + + isc_buffer_availableregion(target, &tregion); + if (tregion.length < 20) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 20); + isc_buffer_add(target, 20); + return (ISC_R_SUCCESS); +} + +static inline int +compare_soa(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_soa); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_soa(ARGS_FROMSTRUCT) { + dns_rdata_soa_t *soa = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_soa); + REQUIRE(source != NULL); + REQUIRE(soa->common.rdtype == type); + REQUIRE(soa->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&soa->origin, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + dns_name_toregion(&soa->contact, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + RETERR(uint32_tobuffer(soa->serial, target)); + RETERR(uint32_tobuffer(soa->refresh, target)); + RETERR(uint32_tobuffer(soa->retry, target)); + RETERR(uint32_tobuffer(soa->expire, target)); + return (uint32_tobuffer(soa->minimum, target)); +} + +static inline isc_result_t +tostruct_soa(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_soa_t *soa = target; + dns_name_t name; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_soa); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + soa->common.rdclass = rdata->rdclass; + soa->common.rdtype = rdata->type; + ISC_LINK_INIT(&soa->common, link); + + + dns_rdata_toregion(rdata, ®ion); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + dns_name_init(&soa->origin, NULL); + RETERR(name_duporclone(&name, mctx, &soa->origin)); + + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + dns_name_init(&soa->contact, NULL); + result = name_duporclone(&name, mctx, &soa->contact); + if (result != ISC_R_SUCCESS) + goto cleanup; + + soa->serial = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + soa->refresh = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + soa->retry = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + soa->expire = uint32_fromregion(®ion); + isc_region_consume(®ion, 4); + + soa->minimum = uint32_fromregion(®ion); + + soa->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&soa->origin, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_soa(ARGS_FREESTRUCT) { + dns_rdata_soa_t *soa = source; + + REQUIRE(source != NULL); + REQUIRE(soa->common.rdtype == dns_rdatatype_soa); + + if (soa->mctx == NULL) + return; + + dns_name_free(&soa->origin, soa->mctx); + dns_name_free(&soa->contact, soa->mctx); + soa->mctx = NULL; +} + +static inline isc_result_t +additionaldata_soa(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_soa); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_soa(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_soa); + + dns_rdata_toregion(rdata, &r); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + RETERR(dns_name_digest(&name, digest, arg)); + isc_region_consume(&r, name_length(&name)); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + RETERR(dns_name_digest(&name, digest, arg)); + isc_region_consume(&r, name_length(&name)); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_soa(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_soa); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_soa(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_soa); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + isc_region_consume(®ion, name_length(&name)); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ismailbox(&name)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_soa(ARGS_COMPARE) { + return (compare_soa(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_SOA_6_C */ diff --git a/lib/dns/rdata/generic/soa_6.h b/lib/dns/rdata/generic/soa_6.h new file mode 100644 index 0000000..c9be985 --- /dev/null +++ b/lib/dns/rdata/generic/soa_6.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_SOA_6_H +#define GENERIC_SOA_6_H 1 + + +typedef struct dns_rdata_soa { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t origin; + dns_name_t contact; + uint32_t serial; /*%< host order */ + uint32_t refresh; /*%< host order */ + uint32_t retry; /*%< host order */ + uint32_t expire; /*%< host order */ + uint32_t minimum; /*%< host order */ +} dns_rdata_soa_t; + + +#endif /* GENERIC_SOA_6_H */ diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c new file mode 100644 index 0000000..c41edf6 --- /dev/null +++ b/lib/dns/rdata/generic/spf_99.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_SPF_99_C +#define RDATA_GENERIC_SPF_99_C + +#define RRTYPE_SPF_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_spf(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_spf); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + return (generic_fromtext_txt(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_spf(ARGS_TOTEXT) { + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_spf); + + return (generic_totext_txt(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_spf(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_spf); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + return (generic_fromwire_txt(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_spf(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_spf); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_spf(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_spf); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_spf(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_spf); + + return (generic_fromstruct_txt(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_spf(ARGS_TOSTRUCT) { + dns_rdata_spf_t *spf = target; + + REQUIRE(rdata->type == dns_rdatatype_spf); + REQUIRE(target != NULL); + + spf->common.rdclass = rdata->rdclass; + spf->common.rdtype = rdata->type; + ISC_LINK_INIT(&spf->common, link); + + return (generic_tostruct_txt(rdata, target, mctx)); +} + +static inline void +freestruct_spf(ARGS_FREESTRUCT) { + dns_rdata_spf_t *txt = source; + + REQUIRE(source != NULL); + REQUIRE(txt->common.rdtype == dns_rdatatype_spf); + + generic_freestruct_txt(source); +} + +static inline isc_result_t +additionaldata_spf(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_spf); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_spf(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_spf); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_spf(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_spf); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_spf(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_spf); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_spf(ARGS_COMPARE) { + return (compare_spf(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_SPF_99_C */ diff --git a/lib/dns/rdata/generic/spf_99.h b/lib/dns/rdata/generic/spf_99.h new file mode 100644 index 0000000..f10b790 --- /dev/null +++ b/lib/dns/rdata/generic/spf_99.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_SPF_99_H +#define GENERIC_SPF_99_H 1 + + +typedef struct dns_rdata_spf_string { + uint8_t length; + unsigned char *data; +} dns_rdata_spf_string_t; + +typedef struct dns_rdata_spf { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *txt; + uint16_t txt_len; + /* private */ + uint16_t offset; +} dns_rdata_spf_t; + +/* + * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done + * via rdatastructpre.h and rdatastructsuf.h. + */ +#endif /* GENERIC_SPF_99_H */ diff --git a/lib/dns/rdata/generic/sshfp_44.c b/lib/dns/rdata/generic/sshfp_44.c new file mode 100644 index 0000000..1b5d7ca --- /dev/null +++ b/lib/dns/rdata/generic/sshfp_44.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC 4255 */ + +#ifndef RDATA_GENERIC_SSHFP_44_C +#define RDATA_GENERIC_SSHFP_44_C + +#define RRTYPE_SSHFP_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_sshfp(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_sshfp); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Digest type. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Digest. + */ + return (isc_hex_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_sshfp(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000 ")]; + unsigned int n; + + REQUIRE(rdata->type == dns_rdatatype_sshfp); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + /* + * Algorithm. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Digest type. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u", n); + RETERR(str_totext(buf, target)); + + /* + * Digest. + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_sshfp(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_sshfp); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_sshfp(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_sshfp); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_sshfp(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_sshfp); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_sshfp(ARGS_FROMSTRUCT) { + dns_rdata_sshfp_t *sshfp = source; + + REQUIRE(type == dns_rdatatype_sshfp); + REQUIRE(source != NULL); + REQUIRE(sshfp->common.rdtype == type); + REQUIRE(sshfp->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(sshfp->algorithm, target)); + RETERR(uint8_tobuffer(sshfp->digest_type, target)); + + return (mem_tobuffer(target, sshfp->digest, sshfp->length)); +} + +static inline isc_result_t +tostruct_sshfp(ARGS_TOSTRUCT) { + dns_rdata_sshfp_t *sshfp = target; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_sshfp); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + sshfp->common.rdclass = rdata->rdclass; + sshfp->common.rdtype = rdata->type; + ISC_LINK_INIT(&sshfp->common, link); + + dns_rdata_toregion(rdata, ®ion); + + sshfp->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + sshfp->digest_type = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + sshfp->length = region.length; + + sshfp->digest = mem_maybedup(mctx, region.base, region.length); + if (sshfp->digest == NULL) + return (ISC_R_NOMEMORY); + + sshfp->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_sshfp(ARGS_FREESTRUCT) { + dns_rdata_sshfp_t *sshfp = source; + + REQUIRE(sshfp != NULL); + REQUIRE(sshfp->common.rdtype == dns_rdatatype_sshfp); + + if (sshfp->mctx == NULL) + return; + + if (sshfp->digest != NULL) + isc_mem_free(sshfp->mctx, sshfp->digest); + sshfp->mctx = NULL; +} + +static inline isc_result_t +additionaldata_sshfp(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_sshfp); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_sshfp(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_sshfp); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_sshfp(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_sshfp); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_sshfp(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_sshfp); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_sshfp(ARGS_COMPARE) { + return (compare_sshfp(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_SSHFP_44_C */ diff --git a/lib/dns/rdata/generic/sshfp_44.h b/lib/dns/rdata/generic/sshfp_44.h new file mode 100644 index 0000000..ba1129a --- /dev/null +++ b/lib/dns/rdata/generic/sshfp_44.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! + * \brief Per RFC 4255 */ + +#ifndef GENERIC_SSHFP_44_H +#define GENERIC_SSHFP_44_H 1 + +typedef struct dns_rdata_sshfp { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint8_t algorithm; + uint8_t digest_type; + uint16_t length; + unsigned char *digest; +} dns_rdata_sshfp_t; + +#endif /* GENERIC_SSHFP_44_H */ diff --git a/lib/dns/rdata/generic/ta_32768.c b/lib/dns/rdata/generic/ta_32768.c new file mode 100644 index 0000000..12ec6e7 --- /dev/null +++ b/lib/dns/rdata/generic/ta_32768.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* http://www.watson.org/~weiler/INI1999-19.pdf */ + +#ifndef RDATA_GENERIC_TA_32768_C +#define RDATA_GENERIC_TA_32768_C + +#define RRTYPE_TA_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_ta(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_ta); + + return (generic_fromtext_ds(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_ta(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_ta); + + return (generic_totext_ds(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_ta(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_ta); + + return (generic_fromwire_ds(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_ta(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_ta); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_ta(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_ta); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_ta(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_ta); + + return (generic_fromstruct_ds(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_ta(ARGS_TOSTRUCT) { + dns_rdata_ds_t *ds = target; + + REQUIRE(rdata->type == dns_rdatatype_ta); + + /* + * Checked by generic_tostruct_ds(). + */ + ds->common.rdclass = rdata->rdclass; + ds->common.rdtype = rdata->type; + ISC_LINK_INIT(&ds->common, link); + + return (generic_tostruct_ds(rdata, target, mctx)); +} + +static inline void +freestruct_ta(ARGS_FREESTRUCT) { + dns_rdata_ta_t *ds = source; + + REQUIRE(ds != NULL); + REQUIRE(ds->common.rdtype == dns_rdatatype_ta); + + if (ds->mctx == NULL) + return; + + if (ds->digest != NULL) + isc_mem_free(ds->mctx, ds->digest); + ds->mctx = NULL; +} + +static inline isc_result_t +additionaldata_ta(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_ta); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_ta(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_ta); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_ta(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_ta); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_ta(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_ta); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_ta(ARGS_COMPARE) { + return (compare_ta(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_TA_32768_C */ diff --git a/lib/dns/rdata/generic/ta_32768.h b/lib/dns/rdata/generic/ta_32768.h new file mode 100644 index 0000000..1bd7a28 --- /dev/null +++ b/lib/dns/rdata/generic/ta_32768.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_TA_32768_H +#define GENERIC_TA_32768_H 1 + +/* + * TA records are identical to DS records. + */ +typedef struct dns_rdata_ds dns_rdata_ta_t; + +#endif /* GENERIC_TA_32768_H */ diff --git a/lib/dns/rdata/generic/talink_58.c b/lib/dns/rdata/generic/talink_58.c new file mode 100644 index 0000000..7f6bacb --- /dev/null +++ b/lib/dns/rdata/generic/talink_58.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_TALINK_58_C +#define RDATA_GENERIC_TALINK_58_C + +#define RRTYPE_TALINK_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_talink(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + int i; + + REQUIRE(type == dns_rdatatype_talink); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + if (origin == NULL) + origin = dns_rootname; + + for (i = 0; i < 2; i++) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, + options, target)); + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_talink(ARGS_TOTEXT) { + isc_region_t dregion; + dns_name_t prev; + dns_name_t next; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_talink); + REQUIRE(rdata->length != 0); + + dns_name_init(&prev, NULL); + dns_name_init(&next, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, &dregion); + + dns_name_fromregion(&prev, &dregion); + isc_region_consume(&dregion, name_length(&prev)); + + dns_name_fromregion(&next, &dregion); + isc_region_consume(&dregion, name_length(&next)); + + sub = name_prefix(&prev, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + RETERR(str_totext(" ", target)); + + sub = name_prefix(&next, tctx->origin, &prefix); + return(dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_talink(ARGS_FROMWIRE) { + dns_name_t prev; + dns_name_t next; + + REQUIRE(type == dns_rdatatype_talink); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&prev, NULL); + dns_name_init(&next, NULL); + + RETERR(dns_name_fromwire(&prev, source, dctx, options, target)); + return(dns_name_fromwire(&next, source, dctx, options, target)); +} + +static inline isc_result_t +towire_talink(ARGS_TOWIRE) { + isc_region_t sregion; + dns_name_t prev; + dns_name_t next; + dns_offsets_t moffsets; + dns_offsets_t roffsets; + + REQUIRE(rdata->type == dns_rdatatype_talink); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + + dns_name_init(&prev, moffsets); + dns_name_init(&next, roffsets); + + dns_rdata_toregion(rdata, &sregion); + + dns_name_fromregion(&prev, &sregion); + isc_region_consume(&sregion, name_length(&prev)); + RETERR(dns_name_towire(&prev, cctx, target)); + + dns_name_fromregion(&next, &sregion); + isc_region_consume(&sregion, name_length(&next)); + return(dns_name_towire(&next, cctx, target)); +} + +static inline int +compare_talink(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_talink); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_talink(ARGS_FROMSTRUCT) { + dns_rdata_talink_t *talink = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_talink); + REQUIRE(source != NULL); + REQUIRE(talink->common.rdtype == type); + REQUIRE(talink->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&talink->prev, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + dns_name_toregion(&talink->next, ®ion); + return(isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_talink(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_talink_t *talink = target; + dns_name_t name; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_talink); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + talink->common.rdclass = rdata->rdclass; + talink->common.rdtype = rdata->type; + ISC_LINK_INIT(&talink->common, link); + + dns_rdata_toregion(rdata, ®ion); + + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + dns_name_init(&talink->prev, NULL); + RETERR(name_duporclone(&name, mctx, &talink->prev)); + + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + dns_name_init(&talink->next, NULL); + result = name_duporclone(&name, mctx, &talink->next); + if (result != ISC_R_SUCCESS) + goto cleanup; + + talink->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&talink->prev, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_talink(ARGS_FREESTRUCT) { + dns_rdata_talink_t *talink = source; + + REQUIRE(source != NULL); + REQUIRE(talink->common.rdtype == dns_rdatatype_talink); + + if (talink->mctx == NULL) + return; + + dns_name_free(&talink->prev, talink->mctx); + dns_name_free(&talink->next, talink->mctx); + talink->mctx = NULL; +} + +static inline isc_result_t +additionaldata_talink(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_talink); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_talink(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_talink); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_talink(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_talink); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_talink(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_talink); + + UNUSED(bad); + UNUSED(owner); + + return (true); +} + +static inline int +casecompare_talink(ARGS_COMPARE) { + return (compare_talink(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_TALINK_58_C */ diff --git a/lib/dns/rdata/generic/talink_58.h b/lib/dns/rdata/generic/talink_58.h new file mode 100644 index 0000000..03166a2 --- /dev/null +++ b/lib/dns/rdata/generic/talink_58.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* http://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template */ + +#ifndef GENERIC_TALINK_58_H +#define GENERIC_TALINK_58_H 1 + +typedef struct dns_rdata_talink { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t prev; + dns_name_t next; +} dns_rdata_talink_t; + +#endif /* GENERIC_TALINK_58_H */ diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c new file mode 100644 index 0000000..7bbd1d3 --- /dev/null +++ b/lib/dns/rdata/generic/tkey_249.c @@ -0,0 +1,556 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* draft-ietf-dnsext-tkey-01.txt */ + +#ifndef RDATA_GENERIC_TKEY_249_C +#define RDATA_GENERIC_TKEY_249_C + +#define RRTYPE_TKEY_ATTRIBUTES (DNS_RDATATYPEATTR_META) + +static inline isc_result_t +fromtext_tkey(ARGS_FROMTEXT) { + isc_token_t token; + dns_rcode_t rcode; + dns_name_t name; + isc_buffer_t buffer; + long i; + char *e; + + REQUIRE(type == dns_rdatatype_tkey); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + + /* + * Inception. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* + * Expiration. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + RETERR(uint32_tobuffer(token.value.as_ulong, target)); + + /* + * Mode. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Error. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion) + != ISC_R_SUCCESS) + { + i = strtol(DNS_AS_STR(token), &e, 10); + if (*e != 0) + RETTOK(DNS_R_UNKNOWN); + if (i < 0 || i > 0xffff) + RETTOK(ISC_R_RANGE); + rcode = (dns_rcode_t)i; + } + RETERR(uint16_tobuffer(rcode, target)); + + /* + * Key Size. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Key Data. + */ + RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong)); + + /* + * Other Size. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Other Data. + */ + return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong)); +} + +static inline isc_result_t +totext_tkey(ARGS_TOTEXT) { + isc_region_t sr, dr; + char buf[sizeof("4294967295 ")]; + unsigned long n; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_tkey); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* + * Algorithm. + */ + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_name_fromregion(&name, &sr); + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + RETERR(str_totext(" ", target)); + isc_region_consume(&sr, name_length(&name)); + + /* + * Inception. + */ + n = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + snprintf(buf, sizeof(buf), "%lu ", n); + RETERR(str_totext(buf, target)); + + /* + * Expiration. + */ + n = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + snprintf(buf, sizeof(buf), "%lu ", n); + RETERR(str_totext(buf, target)); + + /* + * Mode. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%lu ", n); + RETERR(str_totext(buf, target)); + + /* + * Error. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS) + RETERR(str_totext(" ", target)); + else { + snprintf(buf, sizeof(buf), "%lu ", n); + RETERR(str_totext(buf, target)); + } + + /* + * Key Size. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%lu", n); + RETERR(str_totext(buf, target)); + + /* + * Key Data. + */ + REQUIRE(n <= sr.length); + dr = sr; + dr.length = n; + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&dr, 60, "", target)); + else + RETERR(isc_base64_totext(&dr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" ) ", target)); + else + RETERR(str_totext(" ", target)); + isc_region_consume(&sr, n); + + /* + * Other Size. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + snprintf(buf, sizeof(buf), "%lu", n); + RETERR(str_totext(buf, target)); + + /* + * Other Data. + */ + REQUIRE(n <= sr.length); + if (n != 0U) { + dr = sr; + dr.length = n; + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&dr, 60, "", target)); + else + RETERR(isc_base64_totext(&dr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_tkey(ARGS_FROMWIRE) { + isc_region_t sr; + unsigned long n; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_tkey); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + /* + * Algorithm. + */ + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + /* + * Inception: 4 + * Expiration: 4 + * Mode: 2 + * Error: 2 + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 12) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, 12)); + isc_region_consume(&sr, 12); + isc_buffer_forward(source, 12); + + /* + * Key Length + Key Data. + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + n = uint16_fromregion(&sr); + if (sr.length < n + 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, n + 2)); + isc_region_consume(&sr, n + 2); + isc_buffer_forward(source, n + 2); + + /* + * Other Length + Other Data. + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + n = uint16_fromregion(&sr); + if (sr.length < n + 2) + return (ISC_R_UNEXPECTEDEND); + isc_buffer_forward(source, n + 2); + return (mem_tobuffer(target, sr.base, n + 2)); +} + +static inline isc_result_t +towire_tkey(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + + REQUIRE(rdata->type == dns_rdatatype_tkey); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + /* + * Algorithm. + */ + dns_rdata_toregion(rdata, &sr); + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + RETERR(dns_name_towire(&name, cctx, target)); + isc_region_consume(&sr, name_length(&name)); + + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_tkey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_tkey); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + /* + * Algorithm. + */ + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + if ((order = dns_name_rdatacompare(&name1, &name2)) != 0) + return (order); + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_tkey(ARGS_FROMSTRUCT) { + dns_rdata_tkey_t *tkey = source; + + REQUIRE(type == dns_rdatatype_tkey); + REQUIRE(source != NULL); + REQUIRE(tkey->common.rdtype == type); + REQUIRE(tkey->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Algorithm Name. + */ + RETERR(name_tobuffer(&tkey->algorithm, target)); + + /* + * Inception: 32 bits. + */ + RETERR(uint32_tobuffer(tkey->inception, target)); + + /* + * Expire: 32 bits. + */ + RETERR(uint32_tobuffer(tkey->expire, target)); + + /* + * Mode: 16 bits. + */ + RETERR(uint16_tobuffer(tkey->mode, target)); + + /* + * Error: 16 bits. + */ + RETERR(uint16_tobuffer(tkey->error, target)); + + /* + * Key size: 16 bits. + */ + RETERR(uint16_tobuffer(tkey->keylen, target)); + + /* + * Key. + */ + RETERR(mem_tobuffer(target, tkey->key, tkey->keylen)); + + /* + * Other size: 16 bits. + */ + RETERR(uint16_tobuffer(tkey->otherlen, target)); + + /* + * Other data. + */ + return (mem_tobuffer(target, tkey->other, tkey->otherlen)); +} + +static inline isc_result_t +tostruct_tkey(ARGS_TOSTRUCT) { + dns_rdata_tkey_t *tkey = target; + dns_name_t alg; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_tkey); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + tkey->common.rdclass = rdata->rdclass; + tkey->common.rdtype = rdata->type; + ISC_LINK_INIT(&tkey->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Algorithm Name. + */ + dns_name_init(&alg, NULL); + dns_name_fromregion(&alg, &sr); + dns_name_init(&tkey->algorithm, NULL); + RETERR(name_duporclone(&alg, mctx, &tkey->algorithm)); + isc_region_consume(&sr, name_length(&tkey->algorithm)); + + /* + * Inception. + */ + tkey->inception = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Expire. + */ + tkey->expire = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* + * Mode. + */ + tkey->mode = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Error. + */ + tkey->error = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Key size. + */ + tkey->keylen = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Key. + */ + INSIST(tkey->keylen + 2U <= sr.length); + tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen); + if (tkey->key == NULL) + goto cleanup; + isc_region_consume(&sr, tkey->keylen); + + /* + * Other size. + */ + tkey->otherlen = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Other. + */ + INSIST(tkey->otherlen <= sr.length); + tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen); + if (tkey->other == NULL) + goto cleanup; + + tkey->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (mctx != NULL) + dns_name_free(&tkey->algorithm, mctx); + if (mctx != NULL && tkey->key != NULL) + isc_mem_free(mctx, tkey->key); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_tkey(ARGS_FREESTRUCT) { + dns_rdata_tkey_t *tkey = (dns_rdata_tkey_t *) source; + + REQUIRE(source != NULL); + + if (tkey->mctx == NULL) + return; + + dns_name_free(&tkey->algorithm, tkey->mctx); + if (tkey->key != NULL) + isc_mem_free(tkey->mctx, tkey->key); + if (tkey->other != NULL) + isc_mem_free(tkey->mctx, tkey->other); + tkey->mctx = NULL; +} + +static inline isc_result_t +additionaldata_tkey(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_tkey); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_tkey(ARGS_DIGEST) { + UNUSED(rdata); + UNUSED(digest); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_tkey); + + return (ISC_R_NOTIMPLEMENTED); +} + +static inline bool +checkowner_tkey(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_tkey); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_tkey(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_tkey); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_tkey(ARGS_COMPARE) { + return (compare_tkey(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_TKEY_249_C */ diff --git a/lib/dns/rdata/generic/tkey_249.h b/lib/dns/rdata/generic/tkey_249.h new file mode 100644 index 0000000..2fab087 --- /dev/null +++ b/lib/dns/rdata/generic/tkey_249.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_TKEY_249_H +#define GENERIC_TKEY_249_H 1 + + +/*! + * \brief Per draft-ietf-dnsind-tkey-00.txt */ + +typedef struct dns_rdata_tkey { + dns_rdatacommon_t common; + isc_mem_t * mctx; + dns_name_t algorithm; + uint32_t inception; + uint32_t expire; + uint16_t mode; + uint16_t error; + uint16_t keylen; + unsigned char * key; + uint16_t otherlen; + unsigned char * other; +} dns_rdata_tkey_t; + + +#endif /* GENERIC_TKEY_249_H */ diff --git a/lib/dns/rdata/generic/tlsa_52.c b/lib/dns/rdata/generic/tlsa_52.c new file mode 100644 index 0000000..1224dc1 --- /dev/null +++ b/lib/dns/rdata/generic/tlsa_52.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* rfc6698.txt */ + +#ifndef RDATA_GENERIC_TLSA_52_C +#define RDATA_GENERIC_TLSA_52_C + +#define RRTYPE_TLSA_ATTRIBUTES 0 + +static inline isc_result_t +generic_fromtext_tlsa(ARGS_FROMTEXT) { + isc_token_t token; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * Certificate Usage. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Selector. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Matching type. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Certificate Association Data. + */ + return (isc_hex_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +generic_totext_tlsa(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000 ")]; + unsigned int n; + + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + /* + * Certificate Usage. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Selector. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Matching type. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u", n); + RETERR(str_totext(buf, target)); + + /* + * Certificate Association Data. + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +generic_fromwire_tlsa(ARGS_FROMWIRE) { + isc_region_t sr; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + + if (sr.length < 3) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +fromtext_tlsa(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_tlsa); + + return (generic_fromtext_tlsa(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_tlsa(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_tlsa); + + return (generic_totext_tlsa(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_tlsa(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_tlsa); + + return (generic_fromwire_tlsa(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_tlsa(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_tlsa); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_tlsa(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_tlsa); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +generic_fromstruct_tlsa(ARGS_FROMSTRUCT) { + dns_rdata_tlsa_t *tlsa = source; + + REQUIRE(source != NULL); + REQUIRE(tlsa->common.rdtype == type); + REQUIRE(tlsa->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(tlsa->usage, target)); + RETERR(uint8_tobuffer(tlsa->selector, target)); + RETERR(uint8_tobuffer(tlsa->match, target)); + + return (mem_tobuffer(target, tlsa->data, tlsa->length)); +} + +static inline isc_result_t +generic_tostruct_tlsa(ARGS_TOSTRUCT) { + dns_rdata_tlsa_t *tlsa = target; + isc_region_t region; + + REQUIRE(rdata != NULL); + REQUIRE(rdata->length != 0); + + REQUIRE(tlsa != NULL); + REQUIRE(tlsa->common.rdclass == rdata->rdclass); + REQUIRE(tlsa->common.rdtype == rdata->type); + REQUIRE(!ISC_LINK_LINKED(&tlsa->common, link)); + + dns_rdata_toregion(rdata, ®ion); + + tlsa->usage = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + tlsa->selector = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + tlsa->match = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + tlsa->length = region.length; + + tlsa->data = mem_maybedup(mctx, region.base, region.length); + if (tlsa->data == NULL) + return (ISC_R_NOMEMORY); + + tlsa->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +generic_freestruct_tlsa(ARGS_FREESTRUCT) { + dns_rdata_tlsa_t *tlsa = source; + + REQUIRE(tlsa != NULL); + + if (tlsa->mctx == NULL) + return; + + if (tlsa->data != NULL) + isc_mem_free(tlsa->mctx, tlsa->data); + tlsa->mctx = NULL; +} + +static inline isc_result_t +fromstruct_tlsa(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_tlsa); + + return (generic_fromstruct_tlsa(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_tlsa(ARGS_TOSTRUCT) { + dns_rdata_tlsa_t *tlsa = target; + + REQUIRE(rdata->type == dns_rdatatype_tlsa); + REQUIRE(target != NULL); + + tlsa->common.rdclass = rdata->rdclass; + tlsa->common.rdtype = rdata->type; + ISC_LINK_INIT(&tlsa->common, link); + + return (generic_tostruct_tlsa(rdata, target, mctx)); +} + +static inline void +freestruct_tlsa(ARGS_FREESTRUCT) { + dns_rdata_tlsa_t *tlsa = source; + + REQUIRE(source != NULL); + REQUIRE(tlsa->common.rdtype == dns_rdatatype_tlsa); + + generic_freestruct_tlsa(source); +} + +static inline isc_result_t +additionaldata_tlsa(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_tlsa); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_tlsa(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_tlsa); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_tlsa(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_tlsa); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_tlsa(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_tlsa); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_tlsa(ARGS_COMPARE) { + return (compare_tlsa(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_TLSA_52_C */ diff --git a/lib/dns/rdata/generic/tlsa_52.h b/lib/dns/rdata/generic/tlsa_52.h new file mode 100644 index 0000000..422fd8b --- /dev/null +++ b/lib/dns/rdata/generic/tlsa_52.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_TLSA_52_H +#define GENERIC_TLSA_52_H 1 + +/*! + * \brief per rfc6698.txt + */ +typedef struct dns_rdata_tlsa { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint8_t usage; + uint8_t selector; + uint8_t match; + uint16_t length; + unsigned char *data; +} dns_rdata_tlsa_t; + +#endif /* GENERIC_TLSA_52_H */ diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c new file mode 100644 index 0000000..3f3842e --- /dev/null +++ b/lib/dns/rdata/generic/txt_16.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_TXT_16_C +#define RDATA_GENERIC_TXT_16_C + +#define RRTYPE_TXT_ATTRIBUTES (0) + +static inline isc_result_t +generic_fromtext_txt(ARGS_FROMTEXT) { + isc_token_t token; + int strings; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + strings = 0; + if ((options & DNS_RDATA_UNKNOWNESCAPE) != 0) { + isc_textregion_t r; + DE_CONST("#", r.base); + r.length = 1; + RETERR(txt_fromtext(&r, target)); + strings++; + } + for (;;) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qstring, + true)); + if (token.type != isc_tokentype_qstring && + token.type != isc_tokentype_string) + break; + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + strings++; + } + /* Let upper layer handle eol/eof. */ + isc_lex_ungettoken(lexer, &token); + return (strings == 0 ? ISC_R_UNEXPECTEDEND : ISC_R_SUCCESS); +} + +static inline isc_result_t +generic_totext_txt(ARGS_TOTEXT) { + isc_region_t region; + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + + while (region.length > 0) { + RETERR(txt_totext(®ion, true, target)); + if (region.length > 0) + RETERR(str_totext(" ", target)); + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +generic_fromwire_txt(ARGS_FROMWIRE) { + isc_result_t result; + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + do { + result = txt_fromwire(source, target); + if (result != ISC_R_SUCCESS) + return (result); + } while (!buffer_empty(source)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromtext_txt(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_txt); + + return (generic_fromtext_txt(rdclass, type, lexer, origin, options, + target, callbacks)); +} + +static inline isc_result_t +totext_txt(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_txt); + + return (generic_totext_txt(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_txt(ARGS_FROMWIRE) { + + REQUIRE(type == dns_rdatatype_txt); + + return (generic_fromwire_txt(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_txt(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_txt); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_txt(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_txt); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +generic_fromstruct_txt(ARGS_FROMSTRUCT) { + dns_rdata_txt_t *txt = source; + isc_region_t region; + uint8_t length; + + REQUIRE(source != NULL); + REQUIRE(txt->common.rdtype == type); + REQUIRE(txt->common.rdclass == rdclass); + REQUIRE(txt->txt != NULL && txt->txt_len != 0); + + UNUSED(type); + UNUSED(rdclass); + + region.base = txt->txt; + region.length = txt->txt_len; + while (region.length > 0) { + length = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + if (region.length < length) + return (ISC_R_UNEXPECTEDEND); + isc_region_consume(®ion, length); + } + + return (mem_tobuffer(target, txt->txt, txt->txt_len)); +} + +static inline isc_result_t +generic_tostruct_txt(ARGS_TOSTRUCT) { + dns_rdata_txt_t *txt = target; + isc_region_t r; + + REQUIRE(target != NULL); + REQUIRE(txt->common.rdclass == rdata->rdclass); + REQUIRE(txt->common.rdtype == rdata->type); + REQUIRE(!ISC_LINK_LINKED(&txt->common, link)); + + dns_rdata_toregion(rdata, &r); + txt->txt_len = r.length; + txt->txt = mem_maybedup(mctx, r.base, r.length); + if (txt->txt == NULL) + return (ISC_R_NOMEMORY); + + txt->offset = 0; + txt->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +generic_freestruct_txt(ARGS_FREESTRUCT) { + dns_rdata_txt_t *txt = source; + + REQUIRE(source != NULL); + + if (txt->mctx == NULL) + return; + + if (txt->txt != NULL) + isc_mem_free(txt->mctx, txt->txt); + txt->mctx = NULL; +} + +static inline isc_result_t +fromstruct_txt(ARGS_FROMSTRUCT) { + + REQUIRE(type == dns_rdatatype_txt); + + return (generic_fromstruct_txt(rdclass, type, source, target)); +} + +static inline isc_result_t +tostruct_txt(ARGS_TOSTRUCT) { + dns_rdata_txt_t *txt = target; + + REQUIRE(rdata->type == dns_rdatatype_txt); + REQUIRE(target != NULL); + + txt->common.rdclass = rdata->rdclass; + txt->common.rdtype = rdata->type; + ISC_LINK_INIT(&txt->common, link); + + return (generic_tostruct_txt(rdata, target, mctx)); +} + +static inline void +freestruct_txt(ARGS_FREESTRUCT) { + dns_rdata_txt_t *txt = source; + + REQUIRE(source != NULL); + REQUIRE(txt->common.rdtype == dns_rdatatype_txt); + + generic_freestruct_txt(source); +} + +static inline isc_result_t +additionaldata_txt(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_txt); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_txt(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_txt); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_txt(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_txt); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_txt(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_txt); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_txt(ARGS_COMPARE) { + return (compare_txt(rdata1, rdata2)); +} + +static isc_result_t +generic_txt_first(dns_rdata_txt_t *txt) { + + REQUIRE(txt != NULL); + REQUIRE(txt->txt != NULL || txt->txt_len == 0); + + if (txt->txt_len == 0) + return (ISC_R_NOMORE); + + txt->offset = 0; + return (ISC_R_SUCCESS); +} + +static isc_result_t +generic_txt_next(dns_rdata_txt_t *txt) { + isc_region_t r; + uint8_t length; + + REQUIRE(txt != NULL); + REQUIRE(txt->txt != NULL && txt->txt_len != 0); + + INSIST(txt->offset + 1 <= txt->txt_len); + r.base = txt->txt + txt->offset; + r.length = txt->txt_len - txt->offset; + length = uint8_fromregion(&r); + INSIST(txt->offset + 1 + length <= txt->txt_len); + txt->offset = txt->offset + 1 + length; + if (txt->offset == txt->txt_len) + return (ISC_R_NOMORE); + return (ISC_R_SUCCESS); +} + +static isc_result_t +generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { + isc_region_t r; + + REQUIRE(txt != NULL); + REQUIRE(string != NULL); + REQUIRE(txt->txt != NULL); + REQUIRE(txt->offset < txt->txt_len); + + INSIST(txt->offset + 1 <= txt->txt_len); + r.base = txt->txt + txt->offset; + r.length = txt->txt_len - txt->offset; + + string->length = uint8_fromregion(&r); + isc_region_consume(&r, 1); + string->data = r.base; + INSIST(txt->offset + 1 + string->length <= txt->txt_len); + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_txt_first(dns_rdata_txt_t *txt) { + + REQUIRE(txt != NULL); + REQUIRE(txt->common.rdtype == dns_rdatatype_txt); + + return (generic_txt_first(txt)); +} + +isc_result_t +dns_rdata_txt_next(dns_rdata_txt_t *txt) { + + REQUIRE(txt != NULL); + REQUIRE(txt->common.rdtype == dns_rdatatype_txt); + + return (generic_txt_next(txt)); +} + +isc_result_t +dns_rdata_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { + + REQUIRE(txt != NULL); + REQUIRE(txt->common.rdtype == dns_rdatatype_txt); + + return (generic_txt_current(txt, string)); +} +#endif /* RDATA_GENERIC_TXT_16_C */ diff --git a/lib/dns/rdata/generic/txt_16.h b/lib/dns/rdata/generic/txt_16.h new file mode 100644 index 0000000..aaf94bf --- /dev/null +++ b/lib/dns/rdata/generic/txt_16.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_TXT_16_H +#define GENERIC_TXT_16_H 1 + + +typedef struct dns_rdata_txt_string { + uint8_t length; + unsigned char *data; +} dns_rdata_txt_string_t; + +typedef struct dns_rdata_txt { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *txt; + uint16_t txt_len; + /* private */ + uint16_t offset; +} dns_rdata_txt_t; + +/* + * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done + * via rdatastructpre.h and rdatastructsuf.h. + */ + +isc_result_t +dns_rdata_txt_first(dns_rdata_txt_t *); + +isc_result_t +dns_rdata_txt_next(dns_rdata_txt_t *); + +isc_result_t +dns_rdata_txt_current(dns_rdata_txt_t *, dns_rdata_txt_string_t *); + +#endif /* GENERIC_TXT_16_H */ diff --git a/lib/dns/rdata/generic/unspec_103.c b/lib/dns/rdata/generic/unspec_103.c new file mode 100644 index 0000000..1c4654f --- /dev/null +++ b/lib/dns/rdata/generic/unspec_103.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef RDATA_GENERIC_UNSPEC_103_C +#define RDATA_GENERIC_UNSPEC_103_C + +#define RRTYPE_UNSPEC_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_unspec(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_unspec); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + return (atob_tobuffer(lexer, target)); +} + +static inline isc_result_t +totext_unspec(ARGS_TOTEXT) { + + REQUIRE(rdata->type == dns_rdatatype_unspec); + + UNUSED(tctx); + + return (btoa_totext(rdata->data, rdata->length, target)); +} + +static inline isc_result_t +fromwire_unspec(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_unspec); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_unspec(ARGS_TOWIRE) { + + REQUIRE(rdata->type == dns_rdatatype_unspec); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_unspec(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_unspec); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_unspec(ARGS_FROMSTRUCT) { + dns_rdata_unspec_t *unspec = source; + + REQUIRE(type == dns_rdatatype_unspec); + REQUIRE(source != NULL); + REQUIRE(unspec->common.rdtype == type); + REQUIRE(unspec->common.rdclass == rdclass); + REQUIRE(unspec->data != NULL || unspec->datalen == 0); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, unspec->data, unspec->datalen)); +} + +static inline isc_result_t +tostruct_unspec(ARGS_TOSTRUCT) { + dns_rdata_unspec_t *unspec = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_unspec); + REQUIRE(target != NULL); + + unspec->common.rdclass = rdata->rdclass; + unspec->common.rdtype = rdata->type; + ISC_LINK_INIT(&unspec->common, link); + + dns_rdata_toregion(rdata, &r); + unspec->datalen = r.length; + unspec->data = mem_maybedup(mctx, r.base, r.length); + if (unspec->data == NULL) + return (ISC_R_NOMEMORY); + + unspec->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_unspec(ARGS_FREESTRUCT) { + dns_rdata_unspec_t *unspec = source; + + REQUIRE(source != NULL); + REQUIRE(unspec->common.rdtype == dns_rdatatype_unspec); + + if (unspec->mctx == NULL) + return; + + if (unspec->data != NULL) + isc_mem_free(unspec->mctx, unspec->data); + unspec->mctx = NULL; +} + +static inline isc_result_t +additionaldata_unspec(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_unspec); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_unspec(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_unspec); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_unspec(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_unspec); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_unspec(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_unspec); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_unspec(ARGS_COMPARE) { + return (compare_unspec(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_UNSPEC_103_C */ diff --git a/lib/dns/rdata/generic/unspec_103.h b/lib/dns/rdata/generic/unspec_103.h new file mode 100644 index 0000000..9afb1bd --- /dev/null +++ b/lib/dns/rdata/generic/unspec_103.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef GENERIC_UNSPEC_103_H +#define GENERIC_UNSPEC_103_H 1 + + +typedef struct dns_rdata_unspec_t { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *data; + uint16_t datalen; +} dns_rdata_unspec_t; + +#endif /* GENERIC_UNSPEC_103_H */ diff --git a/lib/dns/rdata/generic/uri_256.c b/lib/dns/rdata/generic/uri_256.c new file mode 100644 index 0000000..8fb0307 --- /dev/null +++ b/lib/dns/rdata/generic/uri_256.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef GENERIC_URI_256_C +#define GENERIC_URI_256_C 1 + +#define RRTYPE_URI_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_uri(ARGS_FROMTEXT) { + isc_token_t token; + + REQUIRE(type == dns_rdatatype_uri); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * Priority + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Weight + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Target URI + */ + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qstring, false)); + if (token.type != isc_tokentype_qstring) + RETTOK(DNS_R_SYNTAX); + RETTOK(multitxt_fromtext(&token.value.as_textregion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_uri(ARGS_TOTEXT) { + isc_region_t region; + unsigned short priority, weight; + char buf[sizeof("65000 ")]; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_uri); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + + /* + * Priority + */ + priority = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u ", priority); + RETERR(str_totext(buf, target)); + + /* + * Weight + */ + weight = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u ", weight); + RETERR(str_totext(buf, target)); + + /* + * Target URI + */ + RETERR(multitxt_totext(®ion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_uri(ARGS_FROMWIRE) { + isc_region_t region; + + REQUIRE(type == dns_rdatatype_uri); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + /* + * Priority, weight + */ + isc_buffer_activeregion(source, ®ion); + if (region.length < 4) + return (ISC_R_UNEXPECTEDEND); + + /* + * Priority, weight and target URI + */ + isc_buffer_forward(source, region.length); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline isc_result_t +towire_uri(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_uri); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_uri(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_uri); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + /* + * Priority + */ + order = memcmp(r1.base, r2.base, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + isc_region_consume(&r1, 2); + isc_region_consume(&r2, 2); + + /* + * Weight + */ + order = memcmp(r1.base, r2.base, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + isc_region_consume(&r1, 2); + isc_region_consume(&r2, 2); + + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_uri(ARGS_FROMSTRUCT) { + dns_rdata_uri_t *uri = source; + + REQUIRE(type == dns_rdatatype_uri); + REQUIRE(source != NULL); + REQUIRE(uri->common.rdtype == type); + REQUIRE(uri->common.rdclass == rdclass); + REQUIRE(uri->target != NULL && uri->tgt_len != 0); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Priority + */ + RETERR(uint16_tobuffer(uri->priority, target)); + + /* + * Weight + */ + RETERR(uint16_tobuffer(uri->weight, target)); + + /* + * Target URI + */ + return (mem_tobuffer(target, uri->target, uri->tgt_len)); +} + +static inline isc_result_t +tostruct_uri(ARGS_TOSTRUCT) { + dns_rdata_uri_t *uri = target; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_uri); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + uri->common.rdclass = rdata->rdclass; + uri->common.rdtype = rdata->type; + ISC_LINK_INIT(&uri->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Priority + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + uri->priority = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Weight + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + uri->weight = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* + * Target URI + */ + uri->tgt_len = sr.length; + uri->target = mem_maybedup(mctx, sr.base, sr.length); + if (uri->target == NULL) + return (ISC_R_NOMEMORY); + + uri->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_uri(ARGS_FREESTRUCT) { + dns_rdata_uri_t *uri = (dns_rdata_uri_t *) source; + + REQUIRE(source != NULL); + REQUIRE(uri->common.rdtype == dns_rdatatype_uri); + + if (uri->mctx == NULL) + return; + + if (uri->target != NULL) + isc_mem_free(uri->mctx, uri->target); + uri->mctx = NULL; +} + +static inline isc_result_t +additionaldata_uri(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_uri); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_uri(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_uri); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_uri(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_uri); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_uri(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_uri); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_uri(ARGS_COMPARE) { + return (compare_uri(rdata1, rdata2)); +} + +#endif /* GENERIC_URI_256_C */ diff --git a/lib/dns/rdata/generic/uri_256.h b/lib/dns/rdata/generic/uri_256.h new file mode 100644 index 0000000..cea1d22 --- /dev/null +++ b/lib/dns/rdata/generic/uri_256.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_URI_256_H +#define GENERIC_URI_256_H 1 + + +typedef struct dns_rdata_uri { + dns_rdatacommon_t common; + isc_mem_t * mctx; + uint16_t priority; + uint16_t weight; + unsigned char * target; + uint16_t tgt_len; +} dns_rdata_uri_t; + +#endif /* GENERIC_URI_256_H */ diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c new file mode 100644 index 0000000..d267f65 --- /dev/null +++ b/lib/dns/rdata/generic/x25_19.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1183 */ + +#ifndef RDATA_GENERIC_X25_19_C +#define RDATA_GENERIC_X25_19_C + +#define RRTYPE_X25_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_x25(ARGS_FROMTEXT) { + isc_token_t token; + unsigned int i; + + REQUIRE(type == dns_rdatatype_x25); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + false)); + if (token.value.as_textregion.length < 4) + RETTOK(DNS_R_SYNTAX); + for (i = 0; i < token.value.as_textregion.length; i++) + if (!isdigit(token.value.as_textregion.base[i] & 0xff)) + RETTOK(ISC_R_RANGE); + RETTOK(txt_fromtext(&token.value.as_textregion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_x25(ARGS_TOTEXT) { + isc_region_t region; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_x25); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + return (txt_totext(®ion, true, target)); +} + +static inline isc_result_t +fromwire_x25(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_x25); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 5) + return (DNS_R_FORMERR); + return (txt_fromwire(source, target)); +} + +static inline isc_result_t +towire_x25(ARGS_TOWIRE) { + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_x25); + REQUIRE(rdata->length != 0); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_x25(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_x25); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_x25(ARGS_FROMSTRUCT) { + dns_rdata_x25_t *x25 = source; + uint8_t i; + + REQUIRE(type == dns_rdatatype_x25); + REQUIRE(source != NULL); + REQUIRE(x25->common.rdtype == type); + REQUIRE(x25->common.rdclass == rdclass); + REQUIRE(x25->x25 != NULL && x25->x25_len != 0); + + UNUSED(type); + UNUSED(rdclass); + + if (x25->x25_len < 4) + return (ISC_R_RANGE); + + for (i = 0; i < x25->x25_len; i++) + if (!isdigit(x25->x25[i] & 0xff)) + return (ISC_R_RANGE); + + RETERR(uint8_tobuffer(x25->x25_len, target)); + return (mem_tobuffer(target, x25->x25, x25->x25_len)); +} + +static inline isc_result_t +tostruct_x25(ARGS_TOSTRUCT) { + dns_rdata_x25_t *x25 = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_x25); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + x25->common.rdclass = rdata->rdclass; + x25->common.rdtype = rdata->type; + ISC_LINK_INIT(&x25->common, link); + + dns_rdata_toregion(rdata, &r); + x25->x25_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + x25->x25 = mem_maybedup(mctx, r.base, x25->x25_len); + if (x25->x25 == NULL) + return (ISC_R_NOMEMORY); + + x25->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_x25(ARGS_FREESTRUCT) { + dns_rdata_x25_t *x25 = source; + REQUIRE(source != NULL); + REQUIRE(x25->common.rdtype == dns_rdatatype_x25); + + if (x25->mctx == NULL) + return; + + if (x25->x25 != NULL) + isc_mem_free(x25->mctx, x25->x25); + x25->mctx = NULL; +} + +static inline isc_result_t +additionaldata_x25(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_x25); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_x25(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_x25); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_x25(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_x25); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_x25(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_x25); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_x25(ARGS_COMPARE) { + return (compare_x25(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_X25_19_C */ diff --git a/lib/dns/rdata/generic/x25_19.h b/lib/dns/rdata/generic/x25_19.h new file mode 100644 index 0000000..b10063c --- /dev/null +++ b/lib/dns/rdata/generic/x25_19.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef GENERIC_X25_19_H +#define GENERIC_X25_19_H 1 + + +/*! + * \brief Per RFC1183 */ + +typedef struct dns_rdata_x25 { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *x25; + uint8_t x25_len; +} dns_rdata_x25_t; + +#endif /* GENERIC_X25_19_H */ diff --git a/lib/dns/rdata/hs_4/a_1.c b/lib/dns/rdata/hs_4/a_1.c new file mode 100644 index 0000000..973465e --- /dev/null +++ b/lib/dns/rdata/hs_4/a_1.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_HS_4_A_1_C +#define RDATA_HS_4_A_1_C + +#include <isc/net.h> + +#define RRTYPE_A_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_hs_a(ARGS_FROMTEXT) { + isc_token_t token; + struct in_addr addr; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_hs); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1) + RETTOK(DNS_R_BADDOTTEDQUAD); + isc_buffer_availableregion(target, ®ion); + if (region.length < 4) + return (ISC_R_NOSPACE); + memmove(region.base, &addr, 4); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_hs_a(ARGS_TOTEXT) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_hs); + REQUIRE(rdata->length == 4); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + return (inet_totext(AF_INET, ®ion, target)); +} + +static inline isc_result_t +fromwire_hs_a(ARGS_FROMWIRE) { + isc_region_t sregion; + isc_region_t tregion; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_hs); + + UNUSED(type); + UNUSED(dctx); + UNUSED(options); + UNUSED(rdclass); + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + if (sregion.length < 4) + return (ISC_R_UNEXPECTEDEND); + if (tregion.length < 4) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 4); + isc_buffer_forward(source, 4); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_hs_a(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_hs); + REQUIRE(rdata->length == 4); + + UNUSED(cctx); + + isc_buffer_availableregion(target, ®ion); + if (region.length < rdata->length) + return (ISC_R_NOSPACE); + memmove(region.base, rdata->data, rdata->length); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline int +compare_hs_a(ARGS_COMPARE) { + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_a); + REQUIRE(rdata1->rdclass == dns_rdataclass_hs); + REQUIRE(rdata1->length == 4); + REQUIRE(rdata2->length == 4); + + order = memcmp(rdata1->data, rdata2->data, 4); + if (order != 0) + order = (order < 0) ? -1 : 1; + + return (order); +} + +static inline isc_result_t +fromstruct_hs_a(ARGS_FROMSTRUCT) { + dns_rdata_hs_a_t *a = source; + uint32_t n; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_hs); + REQUIRE(source != NULL); + REQUIRE(a->common.rdtype == type); + REQUIRE(a->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + n = ntohl(a->in_addr.s_addr); + + return (uint32_tobuffer(n, target)); +} + +static inline isc_result_t +tostruct_hs_a(ARGS_TOSTRUCT) { + dns_rdata_hs_a_t *a = target; + uint32_t n; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_hs); + REQUIRE(rdata->length == 4); + + UNUSED(mctx); + + a->common.rdclass = rdata->rdclass; + a->common.rdtype = rdata->type; + ISC_LINK_INIT(&a->common, link); + + dns_rdata_toregion(rdata, ®ion); + n = uint32_fromregion(®ion); + a->in_addr.s_addr = htonl(n); + + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_hs_a(ARGS_FREESTRUCT) { + UNUSED(source); + + REQUIRE(source != NULL); +} + +static inline isc_result_t +additionaldata_hs_a(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_hs); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_hs_a(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_hs); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_hs_a(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_hs); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_hs_a(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_hs); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_hs_a(ARGS_COMPARE) { + return (compare_hs_a(rdata1, rdata2)); +} + +#endif /* RDATA_HS_4_A_1_C */ diff --git a/lib/dns/rdata/hs_4/a_1.h b/lib/dns/rdata/hs_4/a_1.h new file mode 100644 index 0000000..c5f6996 --- /dev/null +++ b/lib/dns/rdata/hs_4/a_1.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef HS_4_A_1_H +#define HS_4_A_1_H 1 + + +typedef struct dns_rdata_hs_a { + dns_rdatacommon_t common; + struct in_addr in_addr; +} dns_rdata_hs_a_t; + +#endif /* HS_4_A_1_H */ diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c new file mode 100644 index 0000000..9d7d431 --- /dev/null +++ b/lib/dns/rdata/in_1/a6_38.c @@ -0,0 +1,460 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC2874 */ + +#ifndef RDATA_IN_1_A6_28_C +#define RDATA_IN_1_A6_28_C + +#include <isc/net.h> + +#define RRTYPE_A6_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_a6(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char addr[16]; + unsigned char prefixlen; + unsigned char octets; + unsigned char mask; + dns_name_t name; + isc_buffer_t buffer; + bool ok; + + REQUIRE(type == dns_rdatatype_a6); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Prefix length. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 128U) + RETTOK(ISC_R_RANGE); + + prefixlen = (unsigned char)token.value.as_ulong; + RETERR(mem_tobuffer(target, &prefixlen, 1)); + + /* + * Suffix. + */ + if (prefixlen != 128) { + /* + * Prefix 0..127. + */ + octets = prefixlen/8; + /* + * Octets 0..15. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + false)); + if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1) + RETTOK(DNS_R_BADAAAA); + mask = 0xff >> (prefixlen % 8); + addr[octets] &= mask; + RETERR(mem_tobuffer(target, &addr[octets], 16 - octets)); + } + + if (prefixlen == 0) + return (ISC_R_SUCCESS); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_a6(ARGS_TOTEXT) { + isc_region_t sr, ar; + unsigned char addr[16]; + unsigned char prefixlen; + unsigned char octets; + unsigned char mask; + char buf[sizeof("128")]; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_a6); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + prefixlen = sr.base[0]; + INSIST(prefixlen <= 128); + isc_region_consume(&sr, 1); + snprintf(buf, sizeof(buf), "%u", prefixlen); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + if (prefixlen != 128) { + octets = prefixlen/8; + memset(addr, 0, sizeof(addr)); + memmove(&addr[octets], sr.base, 16 - octets); + mask = 0xff >> (prefixlen % 8); + addr[octets] &= mask; + ar.base = addr; + ar.length = sizeof(addr); + RETERR(inet_totext(AF_INET6, &ar, target)); + isc_region_consume(&sr, 16 - octets); + } + + if (prefixlen == 0) + return (ISC_R_SUCCESS); + + RETERR(str_totext(" ", target)); + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_name_fromregion(&name, &sr); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_in_a6(ARGS_FROMWIRE) { + isc_region_t sr; + unsigned char prefixlen; + unsigned char octets; + unsigned char mask; + dns_name_t name; + + REQUIRE(type == dns_rdatatype_a6); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + isc_buffer_activeregion(source, &sr); + /* + * Prefix length. + */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + prefixlen = sr.base[0]; + if (prefixlen > 128) + return (ISC_R_RANGE); + isc_region_consume(&sr, 1); + RETERR(mem_tobuffer(target, &prefixlen, 1)); + isc_buffer_forward(source, 1); + + /* + * Suffix. + */ + if (prefixlen != 128) { + octets = 16 - prefixlen / 8; + if (sr.length < octets) + return (ISC_R_UNEXPECTEDEND); + mask = 0xff >> (prefixlen % 8); + sr.base[0] &= mask; /* Ensure pad bits are zero. */ + RETERR(mem_tobuffer(target, sr.base, octets)); + isc_buffer_forward(source, octets); + } + + if (prefixlen == 0) + return (ISC_R_SUCCESS); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_in_a6(ARGS_TOWIRE) { + isc_region_t sr; + dns_name_t name; + dns_offsets_t offsets; + unsigned char prefixlen; + unsigned char octets; + + REQUIRE(rdata->type == dns_rdatatype_a6); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_rdata_toregion(rdata, &sr); + prefixlen = sr.base[0]; + INSIST(prefixlen <= 128); + + octets = 1 + 16 - prefixlen / 8; + RETERR(mem_tobuffer(target, sr.base, octets)); + isc_region_consume(&sr, octets); + + if (prefixlen == 0) + return (ISC_R_SUCCESS); + + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_in_a6(ARGS_COMPARE) { + int order; + unsigned char prefixlen1, prefixlen2; + unsigned char octets; + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_a6); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + prefixlen1 = region1.base[0]; + prefixlen2 = region2.base[0]; + isc_region_consume(®ion1, 1); + isc_region_consume(®ion2, 1); + if (prefixlen1 < prefixlen2) + return (-1); + else if (prefixlen1 > prefixlen2) + return (1); + /* + * Prefix lengths are equal. + */ + octets = 16 - prefixlen1 / 8; + + if (octets > 0) { + order = memcmp(region1.base, region2.base, octets); + if (order < 0) + return (-1); + else if (order > 0) + return (1); + /* + * Address suffixes are equal. + */ + if (prefixlen1 == 0) + return (order); + isc_region_consume(®ion1, octets); + isc_region_consume(®ion2, octets); + } + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_in_a6(ARGS_FROMSTRUCT) { + dns_rdata_in_a6_t *a6 = source; + isc_region_t region; + int octets; + uint8_t bits; + uint8_t first; + uint8_t mask; + + REQUIRE(type == dns_rdatatype_a6); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(a6->common.rdtype == type); + REQUIRE(a6->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + if (a6->prefixlen > 128) + return (ISC_R_RANGE); + + RETERR(uint8_tobuffer(a6->prefixlen, target)); + + /* Suffix */ + if (a6->prefixlen != 128) { + octets = 16 - a6->prefixlen / 8; + bits = a6->prefixlen % 8; + if (bits != 0) { + mask = 0xffU >> bits; + first = a6->in6_addr.s6_addr[16 - octets] & mask; + RETERR(uint8_tobuffer(first, target)); + octets--; + } + if (octets > 0) + RETERR(mem_tobuffer(target, + a6->in6_addr.s6_addr + 16 - octets, + octets)); + } + + if (a6->prefixlen == 0) + return (ISC_R_SUCCESS); + dns_name_toregion(&a6->prefix, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_in_a6(ARGS_TOSTRUCT) { + dns_rdata_in_a6_t *a6 = target; + unsigned char octets; + dns_name_t name; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_a6); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + a6->common.rdclass = rdata->rdclass; + a6->common.rdtype = rdata->type; + ISC_LINK_INIT(&a6->common, link); + + dns_rdata_toregion(rdata, &r); + + a6->prefixlen = uint8_fromregion(&r); + isc_region_consume(&r, 1); + memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr)); + + /* + * Suffix. + */ + if (a6->prefixlen != 128) { + octets = 16 - a6->prefixlen / 8; + INSIST(r.length >= octets); + memmove(a6->in6_addr.s6_addr + 16 - octets, r.base, octets); + isc_region_consume(&r, octets); + } + + /* + * Prefix. + */ + dns_name_init(&a6->prefix, NULL); + if (a6->prefixlen != 0) { + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + RETERR(name_duporclone(&name, mctx, &a6->prefix)); + } + a6->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_a6(ARGS_FREESTRUCT) { + dns_rdata_in_a6_t *a6 = source; + + REQUIRE(source != NULL); + REQUIRE(a6->common.rdclass == dns_rdataclass_in); + REQUIRE(a6->common.rdtype == dns_rdatatype_a6); + + if (a6->mctx == NULL) + return; + + if (dns_name_dynamic(&a6->prefix)) + dns_name_free(&a6->prefix, a6->mctx); + a6->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_a6(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_a6); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_a6(ARGS_DIGEST) { + isc_region_t r1, r2; + unsigned char prefixlen, octets; + isc_result_t result; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_a6); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + prefixlen = r1.base[0]; + octets = 1 + 16 - prefixlen / 8; + + r1.length = octets; + result = (digest)(arg, &r1); + if (result != ISC_R_SUCCESS) + return (result); + if (prefixlen == 0) + return (ISC_R_SUCCESS); + + isc_region_consume(&r2, octets); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_in_a6(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_a6); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + return (dns_name_ishostname(name, wildcard)); +} + +static inline bool +checknames_in_a6(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + unsigned int prefixlen; + + REQUIRE(rdata->type == dns_rdatatype_a6); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + prefixlen = uint8_fromregion(®ion); + if (prefixlen == 0) + return (true); + isc_region_consume(®ion, 1 + 16 - prefixlen / 8); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_in_a6(ARGS_COMPARE) { + return (compare_in_a6(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_A6_38_C */ diff --git a/lib/dns/rdata/in_1/a6_38.h b/lib/dns/rdata/in_1/a6_38.h new file mode 100644 index 0000000..9811640 --- /dev/null +++ b/lib/dns/rdata/in_1/a6_38.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_A6_38_H +#define IN_1_A6_38_H 1 + + +/*! + * \brief Per RFC2874 */ + +typedef struct dns_rdata_in_a6 { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t prefix; + uint8_t prefixlen; + struct in6_addr in6_addr; +} dns_rdata_in_a6_t; + +#endif /* IN_1_A6_38_H */ diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c new file mode 100644 index 0000000..d277699 --- /dev/null +++ b/lib/dns/rdata/in_1/a_1.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_IN_1_A_1_C +#define RDATA_IN_1_A_1_C + +#include <string.h> + +#include <isc/net.h> + +#define RRTYPE_A_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_a(ARGS_FROMTEXT) { + isc_token_t token; + struct in_addr addr; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1) + RETTOK(DNS_R_BADDOTTEDQUAD); + isc_buffer_availableregion(target, ®ion); + if (region.length < 4) + return (ISC_R_NOSPACE); + memmove(region.base, &addr, 4); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_a(ARGS_TOTEXT) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length == 4); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + return (inet_totext(AF_INET, ®ion, target)); +} + +static inline isc_result_t +fromwire_in_a(ARGS_FROMWIRE) { + isc_region_t sregion; + isc_region_t tregion; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(dctx); + UNUSED(options); + UNUSED(rdclass); + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + if (sregion.length < 4) + return (ISC_R_UNEXPECTEDEND); + if (tregion.length < 4) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 4); + isc_buffer_forward(source, 4); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_in_a(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length == 4); + + UNUSED(cctx); + + isc_buffer_availableregion(target, ®ion); + if (region.length < rdata->length) + return (ISC_R_NOSPACE); + memmove(region.base, rdata->data, rdata->length); + isc_buffer_add(target, 4); + return (ISC_R_SUCCESS); +} + +static inline int +compare_in_a(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_a); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length == 4); + REQUIRE(rdata2->length == 4); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_in_a(ARGS_FROMSTRUCT) { + dns_rdata_in_a_t *a = source; + uint32_t n; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(a->common.rdtype == type); + REQUIRE(a->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + n = ntohl(a->in_addr.s_addr); + + return (uint32_tobuffer(n, target)); +} + + +static inline isc_result_t +tostruct_in_a(ARGS_TOSTRUCT) { + dns_rdata_in_a_t *a = target; + uint32_t n; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length == 4); + + UNUSED(mctx); + + a->common.rdclass = rdata->rdclass; + a->common.rdtype = rdata->type; + ISC_LINK_INIT(&a->common, link); + + dns_rdata_toregion(rdata, ®ion); + n = uint32_fromregion(®ion); + a->in_addr.s_addr = htonl(n); + + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_a(ARGS_FREESTRUCT) { + dns_rdata_in_a_t *a = source; + + REQUIRE(source != NULL); + REQUIRE(a->common.rdtype == dns_rdatatype_a); + REQUIRE(a->common.rdclass == dns_rdataclass_in); + + UNUSED(a); +} + +static inline isc_result_t +additionaldata_in_a(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_a(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_in_a(ARGS_CHECKOWNER) { + dns_name_t prefix, suffix; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Handle Active Diretory gc._msdcs.<forest> name. + */ + if (dns_name_countlabels(name) > 2U) { + dns_name_init(&prefix, NULL); + dns_name_init(&suffix, NULL); + dns_name_split(name, dns_name_countlabels(name) - 2, + &prefix, &suffix); + if (dns_name_equal(&gc_msdcs, &prefix) && + dns_name_ishostname(&suffix, false)) + return (true); + } + + return (dns_name_ishostname(name, wildcard)); +} + +static inline bool +checknames_in_a(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_a); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_a(ARGS_COMPARE) { + return (compare_in_a(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_A_1_C */ diff --git a/lib/dns/rdata/in_1/a_1.h b/lib/dns/rdata/in_1/a_1.h new file mode 100644 index 0000000..f44809d --- /dev/null +++ b/lib/dns/rdata/in_1/a_1.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef IN_1_A_1_H +#define IN_1_A_1_H 1 + + +typedef struct dns_rdata_in_a { + dns_rdatacommon_t common; + struct in_addr in_addr; +} dns_rdata_in_a_t; + +#endif /* IN_1_A_1_H */ diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c new file mode 100644 index 0000000..655c5ed --- /dev/null +++ b/lib/dns/rdata/in_1/aaaa_28.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1886 */ + +#ifndef RDATA_IN_1_AAAA_28_C +#define RDATA_IN_1_AAAA_28_C + +#include <isc/net.h> + +#define RRTYPE_AAAA_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_aaaa(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char addr[16]; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_aaaa); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1) + RETTOK(DNS_R_BADAAAA); + isc_buffer_availableregion(target, ®ion); + if (region.length < 16) + return (ISC_R_NOSPACE); + memmove(region.base, addr, 16); + isc_buffer_add(target, 16); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_aaaa(ARGS_TOTEXT) { + isc_region_t region; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length == 16); + + dns_rdata_toregion(rdata, ®ion); + return (inet_totext(AF_INET6, ®ion, target)); +} + +static inline isc_result_t +fromwire_in_aaaa(ARGS_FROMWIRE) { + isc_region_t sregion; + isc_region_t tregion; + + REQUIRE(type == dns_rdatatype_aaaa); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(dctx); + UNUSED(options); + UNUSED(rdclass); + + isc_buffer_activeregion(source, &sregion); + isc_buffer_availableregion(target, &tregion); + if (sregion.length < 16) + return (ISC_R_UNEXPECTEDEND); + if (tregion.length < 16) + return (ISC_R_NOSPACE); + + memmove(tregion.base, sregion.base, 16); + isc_buffer_forward(source, 16); + isc_buffer_add(target, 16); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_in_aaaa(ARGS_TOWIRE) { + isc_region_t region; + + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length == 16); + + isc_buffer_availableregion(target, ®ion); + if (region.length < rdata->length) + return (ISC_R_NOSPACE); + memmove(region.base, rdata->data, rdata->length); + isc_buffer_add(target, 16); + return (ISC_R_SUCCESS); +} + +static inline int +compare_in_aaaa(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_aaaa); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length == 16); + REQUIRE(rdata2->length == 16); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_in_aaaa(ARGS_FROMSTRUCT) { + dns_rdata_in_aaaa_t *aaaa = source; + + REQUIRE(type == dns_rdatatype_aaaa); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(aaaa->common.rdtype == type); + REQUIRE(aaaa->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, aaaa->in6_addr.s6_addr, 16)); +} + +static inline isc_result_t +tostruct_in_aaaa(ARGS_TOSTRUCT) { + dns_rdata_in_aaaa_t *aaaa = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length == 16); + + UNUSED(mctx); + + aaaa->common.rdclass = rdata->rdclass; + aaaa->common.rdtype = rdata->type; + ISC_LINK_INIT(&aaaa->common, link); + + dns_rdata_toregion(rdata, &r); + INSIST(r.length == 16); + memmove(aaaa->in6_addr.s6_addr, r.base, 16); + + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_aaaa(ARGS_FREESTRUCT) { + dns_rdata_in_aaaa_t *aaaa = source; + + REQUIRE(source != NULL); + REQUIRE(aaaa->common.rdclass == dns_rdataclass_in); + REQUIRE(aaaa->common.rdtype == dns_rdatatype_aaaa); + + UNUSED(aaaa); +} + +static inline isc_result_t +additionaldata_in_aaaa(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_aaaa(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_in_aaaa(ARGS_CHECKOWNER) { + dns_name_t prefix, suffix; + + REQUIRE(type == dns_rdatatype_aaaa); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Handle Active Diretory gc._msdcs.<forest> name. + */ + if (dns_name_countlabels(name) > 2U) { + dns_name_init(&prefix, NULL); + dns_name_init(&suffix, NULL); + dns_name_split(name, dns_name_countlabels(name) - 2, + &prefix, &suffix); + if (dns_name_equal(&gc_msdcs, &prefix) && + dns_name_ishostname(&suffix, false)) + return (true); + } + + return (dns_name_ishostname(name, wildcard)); +} + +static inline bool +checknames_in_aaaa(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_aaaa(ARGS_COMPARE) { + return (compare_in_aaaa(rdata1, rdata2)); +} +#endif /* RDATA_IN_1_AAAA_28_C */ diff --git a/lib/dns/rdata/in_1/aaaa_28.h b/lib/dns/rdata/in_1/aaaa_28.h new file mode 100644 index 0000000..caabf7e --- /dev/null +++ b/lib/dns/rdata/in_1/aaaa_28.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_AAAA_28_H +#define IN_1_AAAA_28_H 1 + + +/*! + * \brief Per RFC1886 */ + +typedef struct dns_rdata_in_aaaa { + dns_rdatacommon_t common; + struct in6_addr in6_addr; +} dns_rdata_in_aaaa_t; + +#endif /* IN_1_AAAA_28_H */ diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c new file mode 100644 index 0000000..ae35db9 --- /dev/null +++ b/lib/dns/rdata/in_1/apl_42.c @@ -0,0 +1,456 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC3123 */ + +#ifndef RDATA_IN_1_APL_42_C +#define RDATA_IN_1_APL_42_C + +#define RRTYPE_APL_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_apl(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char addr[16]; + unsigned long afi; + uint8_t prefix; + uint8_t len; + bool neg; + char *cp, *ap, *slash; + int n; + + REQUIRE(type == dns_rdatatype_apl); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + do { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, true)); + if (token.type != isc_tokentype_string) + break; + + cp = DNS_AS_STR(token); + neg = (*cp == '!'); + if (neg) + cp++; + afi = strtoul(cp, &ap, 10); + if (*ap++ != ':' || cp == ap) + RETTOK(DNS_R_SYNTAX); + if (afi > 0xffffU) + RETTOK(ISC_R_RANGE); + slash = strchr(ap, '/'); + if (slash == NULL || slash == ap) + RETTOK(DNS_R_SYNTAX); + RETTOK(isc_parse_uint8(&prefix, slash + 1, 10)); + switch (afi) { + case 1: + *slash = '\0'; + n = inet_pton(AF_INET, ap, addr); + *slash = '/'; + if (n != 1) + RETTOK(DNS_R_BADDOTTEDQUAD); + if (prefix > 32) + RETTOK(ISC_R_RANGE); + for (len = 4; len > 0; len--) + if (addr[len - 1] != 0) + break; + break; + + case 2: + *slash = '\0'; + n = inet_pton(AF_INET6, ap, addr); + *slash = '/'; + if (n != 1) + RETTOK(DNS_R_BADAAAA); + if (prefix > 128) + RETTOK(ISC_R_RANGE); + for (len = 16; len > 0; len--) + if (addr[len - 1] != 0) + break; + break; + + default: + RETTOK(ISC_R_NOTIMPLEMENTED); + } + RETERR(uint16_tobuffer(afi, target)); + RETERR(uint8_tobuffer(prefix, target)); + RETERR(uint8_tobuffer(len | ((neg) ? 0x80 : 0), target)); + RETERR(mem_tobuffer(target, addr, len)); + } while (1); + + /* + * Let upper layer handle eol/eof. + */ + isc_lex_ungettoken(lexer, &token); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_apl(ARGS_TOTEXT) { + isc_region_t sr; + isc_region_t ir; + uint16_t afi; + uint8_t prefix; + uint8_t len; + bool neg; + unsigned char buf[16]; + char txt[sizeof(" !64000:")]; + const char *sep = ""; + int n; + + REQUIRE(rdata->type == dns_rdatatype_apl); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + ir.base = buf; + ir.length = sizeof(buf); + + while (sr.length > 0) { + INSIST(sr.length >= 4); + afi = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + prefix = *sr.base; + isc_region_consume(&sr, 1); + len = (*sr.base & 0x7f); + neg = (*sr.base & 0x80); + isc_region_consume(&sr, 1); + INSIST(len <= sr.length); + n = snprintf(txt, sizeof(txt), "%s%s%u:", sep, + neg ? "!" : "", afi); + INSIST(n < (int)sizeof(txt)); + RETERR(str_totext(txt, target)); + switch (afi) { + case 1: + INSIST(len <= 4); + INSIST(prefix <= 32); + memset(buf, 0, sizeof(buf)); + memmove(buf, sr.base, len); + RETERR(inet_totext(AF_INET, &ir, target)); + break; + + case 2: + INSIST(len <= 16); + INSIST(prefix <= 128); + memset(buf, 0, sizeof(buf)); + memmove(buf, sr.base, len); + RETERR(inet_totext(AF_INET6, &ir, target)); + break; + + default: + return (ISC_R_NOTIMPLEMENTED); + } + n = snprintf(txt, sizeof(txt), "/%u", prefix); + INSIST(n < (int)sizeof(txt)); + RETERR(str_totext(txt, target)); + isc_region_consume(&sr, len); + sep = " "; + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_in_apl(ARGS_FROMWIRE) { + isc_region_t sr, sr2; + isc_region_t tr; + uint16_t afi; + uint8_t prefix; + uint8_t len; + + REQUIRE(type == dns_rdatatype_apl); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(dctx); + UNUSED(rdclass); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + isc_buffer_availableregion(target, &tr); + if (sr.length > tr.length) + return (ISC_R_NOSPACE); + sr2 = sr; + + /* Zero or more items */ + while (sr.length > 0) { + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + afi = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + prefix = *sr.base; + isc_region_consume(&sr, 1); + len = (*sr.base & 0x7f); + isc_region_consume(&sr, 1); + if (len > sr.length) + return (ISC_R_UNEXPECTEDEND); + switch (afi) { + case 1: + if (prefix > 32 || len > 4) + return (ISC_R_RANGE); + break; + case 2: + if (prefix > 128 || len > 16) + return (ISC_R_RANGE); + } + if (len > 0 && sr.base[len - 1] == 0) + return (DNS_R_FORMERR); + isc_region_consume(&sr, len); + } + isc_buffer_forward(source, sr2.length); + return (mem_tobuffer(target, sr2.base, sr2.length)); +} + +static inline isc_result_t +towire_in_apl(ARGS_TOWIRE) { + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_apl); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_in_apl(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_apl); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_in_apl(ARGS_FROMSTRUCT) { + dns_rdata_in_apl_t *apl = source; + isc_buffer_t b; + + REQUIRE(type == dns_rdatatype_apl); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(apl->common.rdtype == type); + REQUIRE(apl->common.rdclass == rdclass); + REQUIRE(apl->apl != NULL || apl->apl_len == 0); + + isc_buffer_init(&b, apl->apl, apl->apl_len); + isc_buffer_add(&b, apl->apl_len); + isc_buffer_setactive(&b, apl->apl_len); + return(fromwire_in_apl(rdclass, type, &b, NULL, false, target)); +} + +static inline isc_result_t +tostruct_in_apl(ARGS_TOSTRUCT) { + dns_rdata_in_apl_t *apl = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_apl); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + apl->common.rdclass = rdata->rdclass; + apl->common.rdtype = rdata->type; + ISC_LINK_INIT(&apl->common, link); + + dns_rdata_toregion(rdata, &r); + apl->apl_len = r.length; + apl->apl = mem_maybedup(mctx, r.base, r.length); + if (apl->apl == NULL) + return (ISC_R_NOMEMORY); + + apl->offset = 0; + apl->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_apl(ARGS_FREESTRUCT) { + dns_rdata_in_apl_t *apl = source; + + REQUIRE(source != NULL); + REQUIRE(apl->common.rdtype == dns_rdatatype_apl); + REQUIRE(apl->common.rdclass == dns_rdataclass_in); + + if (apl->mctx == NULL) + return; + if (apl->apl != NULL) + isc_mem_free(apl->mctx, apl->apl); + apl->mctx = NULL; +} + +isc_result_t +dns_rdata_apl_first(dns_rdata_in_apl_t *apl) { + uint32_t length; + + REQUIRE(apl != NULL); + REQUIRE(apl->common.rdtype == dns_rdatatype_apl); + REQUIRE(apl->common.rdclass == dns_rdataclass_in); + REQUIRE(apl->apl != NULL || apl->apl_len == 0); + + /* + * If no APL return ISC_R_NOMORE. + */ + if (apl->apl == NULL) + return (ISC_R_NOMORE); + + /* + * Sanity check data. + */ + INSIST(apl->apl_len > 3U); + length = apl->apl[apl->offset + 3] & 0x7f; + INSIST(4 + length <= apl->apl_len); + + apl->offset = 0; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_apl_next(dns_rdata_in_apl_t *apl) { + uint32_t length; + + REQUIRE(apl != NULL); + REQUIRE(apl->common.rdtype == dns_rdatatype_apl); + REQUIRE(apl->common.rdclass == dns_rdataclass_in); + REQUIRE(apl->apl != NULL || apl->apl_len == 0); + + /* + * No APL or have already reached the end return ISC_R_NOMORE. + */ + if (apl->apl == NULL || apl->offset == apl->apl_len) + return (ISC_R_NOMORE); + + /* + * Sanity check data. + */ + INSIST(apl->offset < apl->apl_len); + INSIST(apl->apl_len > 3U); + INSIST(apl->offset <= apl->apl_len - 4U); + length = apl->apl[apl->offset + 3] & 0x7f; + /* + * 16 to 32 bits promotion as 'length' is 32 bits so there is + * no overflow problems. + */ + INSIST(4 + length + apl->offset <= apl->apl_len); + + apl->offset += 4 + length; + return ((apl->offset < apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE); +} + +isc_result_t +dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) { + uint32_t length; + + REQUIRE(apl != NULL); + REQUIRE(apl->common.rdtype == dns_rdatatype_apl); + REQUIRE(apl->common.rdclass == dns_rdataclass_in); + REQUIRE(ent != NULL); + REQUIRE(apl->apl != NULL || apl->apl_len == 0); + REQUIRE(apl->offset <= apl->apl_len); + + if (apl->offset == apl->apl_len) + return (ISC_R_NOMORE); + + /* + * Sanity check data. + */ + INSIST(apl->apl_len > 3U); + INSIST(apl->offset <= apl->apl_len - 4U); + length = (apl->apl[apl->offset + 3] & 0x7f); + /* + * 16 to 32 bits promotion as 'length' is 32 bits so there is + * no overflow problems. + */ + INSIST(4 + length + apl->offset <= apl->apl_len); + + ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1]; + ent->prefix = apl->apl[apl->offset + 2]; + ent->length = length; + ent->negative = (apl->apl[apl->offset + 3] & 0x80); + if (ent->length != 0) + ent->data = &apl->apl[apl->offset + 4]; + else + ent->data = NULL; + return (ISC_R_SUCCESS); +} + +unsigned int +dns_rdata_apl_count(const dns_rdata_in_apl_t *apl) { + return (apl->apl_len); +} + +static inline isc_result_t +additionaldata_in_apl(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_apl); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + (void)add; + (void)arg; + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_apl(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_apl); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_in_apl(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_apl); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + + +static inline bool +checknames_in_apl(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_apl); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_apl(ARGS_COMPARE) { + return (compare_in_apl(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_APL_42_C */ diff --git a/lib/dns/rdata/in_1/apl_42.h b/lib/dns/rdata/in_1/apl_42.h new file mode 100644 index 0000000..8c17a53 --- /dev/null +++ b/lib/dns/rdata/in_1/apl_42.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef IN_1_APL_42_H +#define IN_1_APL_42_H 1 + + +typedef struct dns_rdata_apl_ent { + bool negative; + uint16_t family; + uint8_t prefix; + uint8_t length; + unsigned char *data; +} dns_rdata_apl_ent_t; + +typedef struct dns_rdata_in_apl { + dns_rdatacommon_t common; + isc_mem_t *mctx; + /* type & class specific elements */ + unsigned char *apl; + uint16_t apl_len; + /* private */ + uint16_t offset; +} dns_rdata_in_apl_t; + +/* + * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done + * via rdatastructpre.h and rdatastructsuf.h. + */ + +isc_result_t +dns_rdata_apl_first(dns_rdata_in_apl_t *); + +isc_result_t +dns_rdata_apl_next(dns_rdata_in_apl_t *); + +isc_result_t +dns_rdata_apl_current(dns_rdata_in_apl_t *, dns_rdata_apl_ent_t *); + +unsigned int +dns_rdata_apl_count(const dns_rdata_in_apl_t *apl); + +#endif /* IN_1_APL_42_H */ diff --git a/lib/dns/rdata/in_1/dhcid_49.c b/lib/dns/rdata/in_1/dhcid_49.c new file mode 100644 index 0000000..90971b7 --- /dev/null +++ b/lib/dns/rdata/in_1/dhcid_49.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* RFC 4701 */ + +#ifndef RDATA_IN_1_DHCID_49_C +#define RDATA_IN_1_DHCID_49_C 1 + +#define RRTYPE_DHCID_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_in_dhcid(ARGS_FROMTEXT) { + + REQUIRE(type == dns_rdatatype_dhcid); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_in_dhcid(ARGS_TOTEXT) { + isc_region_t sr, sr2; + char buf[sizeof(" ; 64000 255 64000")]; + size_t n; + + REQUIRE(rdata->type == dns_rdatatype_dhcid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + sr2 = sr; + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext("( " /*)*/, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext(/* ( */ " )", target)); + if (rdata->length > 2) { + n = snprintf(buf, sizeof(buf), " ; %u %u %u", + sr2.base[0] * 256U + sr2.base[1], + sr2.base[2], rdata->length - 3U); + INSIST(n < sizeof(buf)); + RETERR(str_totext(buf, target)); + } + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_in_dhcid(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_dhcid); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length == 0) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_in_dhcid(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_dhcid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_in_dhcid(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_dhcid); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_in_dhcid(ARGS_FROMSTRUCT) { + dns_rdata_in_dhcid_t *dhcid = source; + + REQUIRE(type == dns_rdatatype_dhcid); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(dhcid->common.rdtype == type); + REQUIRE(dhcid->common.rdclass == rdclass); + REQUIRE(dhcid->length != 0); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, dhcid->dhcid, dhcid->length)); +} + +static inline isc_result_t +tostruct_in_dhcid(ARGS_TOSTRUCT) { + dns_rdata_in_dhcid_t *dhcid = target; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_dhcid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + dhcid->common.rdclass = rdata->rdclass; + dhcid->common.rdtype = rdata->type; + ISC_LINK_INIT(&dhcid->common, link); + + dns_rdata_toregion(rdata, ®ion); + + dhcid->dhcid = mem_maybedup(mctx, region.base, region.length); + if (dhcid->dhcid == NULL) + return (ISC_R_NOMEMORY); + + dhcid->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_dhcid(ARGS_FREESTRUCT) { + dns_rdata_in_dhcid_t *dhcid = source; + + REQUIRE(dhcid != NULL); + REQUIRE(dhcid->common.rdtype == dns_rdatatype_dhcid); + REQUIRE(dhcid->common.rdclass == dns_rdataclass_in); + + if (dhcid->mctx == NULL) + return; + + if (dhcid->dhcid != NULL) + isc_mem_free(dhcid->mctx, dhcid->dhcid); + dhcid->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_dhcid(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_dhcid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_dhcid(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_dhcid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_in_dhcid(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_dhcid); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_in_dhcid(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_dhcid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_dhcid(ARGS_COMPARE) { + return (compare_in_dhcid(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_DHCID_49_C */ diff --git a/lib/dns/rdata/in_1/dhcid_49.h b/lib/dns/rdata/in_1/dhcid_49.h new file mode 100644 index 0000000..455eaed --- /dev/null +++ b/lib/dns/rdata/in_1/dhcid_49.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#ifndef IN_1_DHCID_49_H +#define IN_1_DHCID_49_H 1 + + +typedef struct dns_rdata_in_dhcid { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *dhcid; + unsigned int length; +} dns_rdata_in_dhcid_t; + +#endif /* IN_1_DHCID_49_H */ diff --git a/lib/dns/rdata/in_1/kx_36.c b/lib/dns/rdata/in_1/kx_36.c new file mode 100644 index 0000000..2786951 --- /dev/null +++ b/lib/dns/rdata/in_1/kx_36.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2230 */ + +#ifndef RDATA_IN_1_KX_36_C +#define RDATA_IN_1_KX_36_C + +#define RRTYPE_KX_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_kx(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_kx); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_kx(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_kx); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_in_kx(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_kx); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length < 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sregion.base, 2)); + isc_buffer_forward(source, 2); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_in_kx(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_kx); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_rdata_toregion(rdata, ®ion); + RETERR(mem_tobuffer(target, region.base, 2)); + isc_region_consume(®ion, 2); + + dns_name_init(&name, offsets); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_in_kx(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_kx); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + order = memcmp(rdata1->data, rdata2->data, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 2); + isc_region_consume(®ion2, 2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_in_kx(ARGS_FROMSTRUCT) { + dns_rdata_in_kx_t *kx = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_kx); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(kx->common.rdtype == type); + REQUIRE(kx->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(kx->preference, target)); + dns_name_toregion(&kx->exchange, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_in_kx(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_in_kx_t *kx = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_kx); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + kx->common.rdclass = rdata->rdclass; + kx->common.rdtype = rdata->type; + ISC_LINK_INIT(&kx->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + + kx->preference = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + dns_name_fromregion(&name, ®ion); + dns_name_init(&kx->exchange, NULL); + RETERR(name_duporclone(&name, mctx, &kx->exchange)); + kx->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_kx(ARGS_FREESTRUCT) { + dns_rdata_in_kx_t *kx = source; + + REQUIRE(source != NULL); + REQUIRE(kx->common.rdclass == dns_rdataclass_in); + REQUIRE(kx->common.rdtype == dns_rdatatype_kx); + + if (kx->mctx == NULL) + return; + + dns_name_free(&kx->exchange, kx->mctx); + kx->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_kx(ARGS_ADDLDATA) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_kx); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + + return ((add)(arg, &name, dns_rdatatype_a)); +} + +static inline isc_result_t +digest_in_kx(ARGS_DIGEST) { + isc_region_t r1, r2; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_kx); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + isc_region_consume(&r2, 2); + r1.length = 2; + RETERR((digest)(arg, &r1)); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_in_kx(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_kx); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_in_kx(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_kx); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_kx(ARGS_COMPARE) { + return (compare_in_kx(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_KX_36_C */ diff --git a/lib/dns/rdata/in_1/kx_36.h b/lib/dns/rdata/in_1/kx_36.h new file mode 100644 index 0000000..577a4c4 --- /dev/null +++ b/lib/dns/rdata/in_1/kx_36.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_KX_36_H +#define IN_1_KX_36_H 1 + + +/*! + * \brief Per RFC2230 */ + +typedef struct dns_rdata_in_kx { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t preference; + dns_name_t exchange; +} dns_rdata_in_kx_t; + +#endif /* IN_1_KX_36_H */ diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.c b/lib/dns/rdata/in_1/nsap-ptr_23.c new file mode 100644 index 0000000..3217300 --- /dev/null +++ b/lib/dns/rdata/in_1/nsap-ptr_23.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1348. Obsoleted in RFC 1706 - use PTR instead. */ + +#ifndef RDATA_IN_1_NSAP_PTR_23_C +#define RDATA_IN_1_NSAP_PTR_23_C + +#define RRTYPE_NSAP_PTR_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_nsap_ptr(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_nsap_ptr); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_nsap_ptr(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + + REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + sub = name_prefix(&name, tctx->origin, &prefix); + + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_in_nsap_ptr(ARGS_FROMWIRE) { + dns_name_t name; + + REQUIRE(type == dns_rdatatype_nsap_ptr); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_in_nsap_ptr(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_in_nsap_ptr(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_in_nsap_ptr(ARGS_FROMSTRUCT) { + dns_rdata_in_nsap_ptr_t *nsap_ptr = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_nsap_ptr); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(nsap_ptr->common.rdtype == type); + REQUIRE(nsap_ptr->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + dns_name_toregion(&nsap_ptr->owner, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_in_nsap_ptr(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_in_nsap_ptr_t *nsap_ptr = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + nsap_ptr->common.rdclass = rdata->rdclass; + nsap_ptr->common.rdtype = rdata->type; + ISC_LINK_INIT(&nsap_ptr->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + dns_name_fromregion(&name, ®ion); + dns_name_init(&nsap_ptr->owner, NULL); + RETERR(name_duporclone(&name, mctx, &nsap_ptr->owner)); + nsap_ptr->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_nsap_ptr(ARGS_FREESTRUCT) { + dns_rdata_in_nsap_ptr_t *nsap_ptr = source; + + REQUIRE(source != NULL); + REQUIRE(nsap_ptr->common.rdclass == dns_rdataclass_in); + REQUIRE(nsap_ptr->common.rdtype == dns_rdatatype_nsap_ptr); + + if (nsap_ptr->mctx == NULL) + return; + + dns_name_free(&nsap_ptr->owner, nsap_ptr->mctx); + nsap_ptr->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_nsap_ptr(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_nsap_ptr(ARGS_DIGEST) { + isc_region_t r; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_in_nsap_ptr(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_nsap_ptr); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_in_nsap_ptr(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_nsap_ptr(ARGS_COMPARE) { + return (compare_in_nsap_ptr(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_NSAP_PTR_23_C */ diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.h b/lib/dns/rdata/in_1/nsap-ptr_23.h new file mode 100644 index 0000000..4880a09 --- /dev/null +++ b/lib/dns/rdata/in_1/nsap-ptr_23.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_NSAP_PTR_23_H +#define IN_1_NSAP_PTR_23_H 1 + + +/*! + * \brief Per RFC1348. Obsoleted in RFC 1706 - use PTR instead. */ + +typedef struct dns_rdata_in_nsap_ptr { + dns_rdatacommon_t common; + isc_mem_t *mctx; + dns_name_t owner; +} dns_rdata_in_nsap_ptr_t; + +#endif /* IN_1_NSAP_PTR_23_H */ diff --git a/lib/dns/rdata/in_1/nsap_22.c b/lib/dns/rdata/in_1/nsap_22.c new file mode 100644 index 0000000..ba3e69c --- /dev/null +++ b/lib/dns/rdata/in_1/nsap_22.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC1706 */ + +#ifndef RDATA_IN_1_NSAP_22_C +#define RDATA_IN_1_NSAP_22_C + +#define RRTYPE_NSAP_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_nsap(ARGS_FROMTEXT) { + isc_token_t token; + isc_textregion_t *sr; + int n; + bool valid = false; + int digits = 0; + unsigned char c = 0; + + REQUIRE(type == dns_rdatatype_nsap); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + UNUSED(callbacks); + + /* 0x<hex.string.with.periods> */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + sr = &token.value.as_textregion; + if (sr->length < 2) + RETTOK(ISC_R_UNEXPECTEDEND); + if (sr->base[0] != '0' || (sr->base[1] != 'x' && sr->base[1] != 'X')) + RETTOK(DNS_R_SYNTAX); + isc_textregion_consume(sr, 2); + while (sr->length > 0) { + if (sr->base[0] == '.') { + isc_textregion_consume(sr, 1); + continue; + } + if ((n = hexvalue(sr->base[0])) == -1) + RETTOK(DNS_R_SYNTAX); + c <<= 4; + c += n; + if (++digits == 2) { + RETERR(mem_tobuffer(target, &c, 1)); + valid = true; + digits = 0; + c = 0; + } + isc_textregion_consume(sr, 1); + } + if (digits != 0 || !valid) + RETTOK(ISC_R_UNEXPECTEDEND); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_nsap(ARGS_TOTEXT) { + isc_region_t region; + char buf[sizeof("xx")]; + + REQUIRE(rdata->type == dns_rdatatype_nsap); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + RETERR(str_totext("0x", target)); + while (region.length != 0) { + snprintf(buf, sizeof(buf), "%02x", region.base[0]); + isc_region_consume(®ion, 1); + RETERR(str_totext(buf, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_in_nsap(ARGS_FROMWIRE) { + isc_region_t region; + + REQUIRE(type == dns_rdatatype_nsap); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(dctx); + UNUSED(options); + UNUSED(rdclass); + + isc_buffer_activeregion(source, ®ion); + if (region.length < 1) + return (ISC_R_UNEXPECTEDEND); + + RETERR(mem_tobuffer(target, region.base, region.length)); + isc_buffer_forward(source, region.length); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_in_nsap(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_nsap); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static inline int +compare_in_nsap(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_nsap); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_in_nsap(ARGS_FROMSTRUCT) { + dns_rdata_in_nsap_t *nsap = source; + + REQUIRE(type == dns_rdatatype_nsap); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(nsap->common.rdtype == type); + REQUIRE(nsap->common.rdclass == rdclass); + REQUIRE(nsap->nsap != NULL || nsap->nsap_len == 0); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, nsap->nsap, nsap->nsap_len)); +} + +static inline isc_result_t +tostruct_in_nsap(ARGS_TOSTRUCT) { + dns_rdata_in_nsap_t *nsap = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nsap); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + nsap->common.rdclass = rdata->rdclass; + nsap->common.rdtype = rdata->type; + ISC_LINK_INIT(&nsap->common, link); + + dns_rdata_toregion(rdata, &r); + nsap->nsap_len = r.length; + nsap->nsap = mem_maybedup(mctx, r.base, r.length); + if (nsap->nsap == NULL) + return (ISC_R_NOMEMORY); + + nsap->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_nsap(ARGS_FREESTRUCT) { + dns_rdata_in_nsap_t *nsap = source; + + REQUIRE(source != NULL); + REQUIRE(nsap->common.rdclass == dns_rdataclass_in); + REQUIRE(nsap->common.rdtype == dns_rdatatype_nsap); + + if (nsap->mctx == NULL) + return; + + if (nsap->nsap != NULL) + isc_mem_free(nsap->mctx, nsap->nsap); + nsap->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_nsap(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nsap); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_nsap(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nsap); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_in_nsap(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_nsap); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_in_nsap(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_nsap); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_nsap(ARGS_COMPARE) { + return (compare_in_nsap(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_NSAP_22_C */ diff --git a/lib/dns/rdata/in_1/nsap_22.h b/lib/dns/rdata/in_1/nsap_22.h new file mode 100644 index 0000000..79599ef --- /dev/null +++ b/lib/dns/rdata/in_1/nsap_22.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_NSAP_22_H +#define IN_1_NSAP_22_H 1 + + +/*! + * \brief Per RFC1706 */ + +typedef struct dns_rdata_in_nsap { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *nsap; + uint16_t nsap_len; +} dns_rdata_in_nsap_t; + +#endif /* IN_1_NSAP_22_H */ diff --git a/lib/dns/rdata/in_1/px_26.c b/lib/dns/rdata/in_1/px_26.c new file mode 100644 index 0000000..a94b9df --- /dev/null +++ b/lib/dns/rdata/in_1/px_26.c @@ -0,0 +1,370 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2163 */ + +#ifndef RDATA_IN_1_PX_26_C +#define RDATA_IN_1_PX_26_C + +#define RRTYPE_PX_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_px(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + + REQUIRE(type == dns_rdatatype_px); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + if (origin == NULL) + origin = dns_rootname; + + /* + * Preference. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * MAP822. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + + /* + * MAPX400. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_px(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_px); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + /* + * Preference. + */ + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * MAP822. + */ + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + isc_region_consume(®ion, name_length(&name)); + RETERR(dns_name_totext(&prefix, sub, target)); + RETERR(str_totext(" ", target)); + + /* + * MAPX400. + */ + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return(dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_in_px(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_px); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + /* + * Preference. + */ + isc_buffer_activeregion(source, &sregion); + if (sregion.length < 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sregion.base, 2)); + isc_buffer_forward(source, 2); + + /* + * MAP822. + */ + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + /* + * MAPX400. + */ + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_in_px(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_px); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + /* + * Preference. + */ + dns_rdata_toregion(rdata, ®ion); + RETERR(mem_tobuffer(target, region.base, 2)); + isc_region_consume(®ion, 2); + + /* + * MAP822. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, ®ion); + RETERR(dns_name_towire(&name, cctx, target)); + isc_region_consume(®ion, name_length(&name)); + + /* + * MAPX400. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, ®ion); + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_in_px(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_px); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + order = memcmp(rdata1->data, rdata2->data, 2); + if (order != 0) + return (order < 0 ? -1 : 1); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 2); + isc_region_consume(®ion2, 2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_in_px(ARGS_FROMSTRUCT) { + dns_rdata_in_px_t *px = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_px); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(px->common.rdtype == type); + REQUIRE(px->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(px->preference, target)); + dns_name_toregion(&px->map822, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + dns_name_toregion(&px->mapx400, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_in_px(ARGS_TOSTRUCT) { + dns_rdata_in_px_t *px = target; + dns_name_t name; + isc_region_t region; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_px); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + px->common.rdclass = rdata->rdclass; + px->common.rdtype = rdata->type; + ISC_LINK_INIT(&px->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + + px->preference = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + dns_name_fromregion(&name, ®ion); + + dns_name_init(&px->map822, NULL); + RETERR(name_duporclone(&name, mctx, &px->map822)); + isc_region_consume(®ion, name_length(&px->map822)); + + dns_name_init(&px->mapx400, NULL); + result = name_duporclone(&name, mctx, &px->mapx400); + if (result != ISC_R_SUCCESS) + goto cleanup; + + px->mctx = mctx; + return (result); + + cleanup: + dns_name_free(&px->map822, mctx); + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_in_px(ARGS_FREESTRUCT) { + dns_rdata_in_px_t *px = source; + + REQUIRE(source != NULL); + REQUIRE(px->common.rdclass == dns_rdataclass_in); + REQUIRE(px->common.rdtype == dns_rdatatype_px); + + if (px->mctx == NULL) + return; + + dns_name_free(&px->map822, px->mctx); + dns_name_free(&px->mapx400, px->mctx); + px->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_px(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_px); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_px(ARGS_DIGEST) { + isc_region_t r1, r2; + dns_name_t name; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_px); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + isc_region_consume(&r2, 2); + r1.length = 2; + result = (digest)(arg, &r1); + if (result != ISC_R_SUCCESS) + return (result); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + result = dns_name_digest(&name, digest, arg); + if (result != ISC_R_SUCCESS) + return (result); + isc_region_consume(&r2, name_length(&name)); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_in_px(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_px); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_in_px(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_px); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_px(ARGS_COMPARE) { + return (compare_in_px(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_PX_26_C */ diff --git a/lib/dns/rdata/in_1/px_26.h b/lib/dns/rdata/in_1/px_26.h new file mode 100644 index 0000000..3cab1f1 --- /dev/null +++ b/lib/dns/rdata/in_1/px_26.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_PX_26_H +#define IN_1_PX_26_H 1 + + +/*! + * \brief Per RFC2163 */ + +typedef struct dns_rdata_in_px { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t preference; + dns_name_t map822; + dns_name_t mapx400; +} dns_rdata_in_px_t; + +#endif /* IN_1_PX_26_H */ diff --git a/lib/dns/rdata/in_1/srv_33.c b/lib/dns/rdata/in_1/srv_33.c new file mode 100644 index 0000000..63a4e80 --- /dev/null +++ b/lib/dns/rdata/in_1/srv_33.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* RFC2782 */ + +#ifndef RDATA_IN_1_SRV_33_C +#define RDATA_IN_1_SRV_33_C + +#define RRTYPE_SRV_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_in_srv(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + bool ok; + + REQUIRE(type == dns_rdatatype_srv); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Priority. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Weight. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Port. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Target. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + dns_name_init(&name, NULL); + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) + origin = dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); + ok = true; + if ((options & DNS_RDATA_CHECKNAMES) != 0) + ok = dns_name_ishostname(&name, false); + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) + RETTOK(DNS_R_BADNAME); + if (!ok && callbacks != NULL) + warn_badname(&name, lexer, callbacks); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_srv(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("64000")]; + unsigned short num; + + REQUIRE(rdata->type == dns_rdatatype_srv); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + /* + * Priority. + */ + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Weight. + */ + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Port. + */ + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* + * Target. + */ + dns_name_fromregion(&name, ®ion); + sub = name_prefix(&name, tctx->origin, &prefix); + return (dns_name_totext(&prefix, sub, target)); +} + +static inline isc_result_t +fromwire_in_srv(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sr; + + REQUIRE(type == dns_rdatatype_srv); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + /* + * Priority, weight, port. + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 6) + return (ISC_R_UNEXPECTEDEND); + RETERR(mem_tobuffer(target, sr.base, 6)); + isc_buffer_forward(source, 6); + + /* + * Target. + */ + return (dns_name_fromwire(&name, source, dctx, options, target)); +} + +static inline isc_result_t +towire_in_srv(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t sr; + + REQUIRE(rdata->type == dns_rdatatype_srv); + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + /* + * Priority, weight, port. + */ + dns_rdata_toregion(rdata, &sr); + RETERR(mem_tobuffer(target, sr.base, 6)); + isc_region_consume(&sr, 6); + + /* + * Target. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + return (dns_name_towire(&name, cctx, target)); +} + +static inline int +compare_in_srv(ARGS_COMPARE) { + dns_name_t name1; + dns_name_t name2; + isc_region_t region1; + isc_region_t region2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_srv); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + /* + * Priority, weight, port. + */ + order = memcmp(rdata1->data, rdata2->data, 6); + if (order != 0) + return (order < 0 ? -1 : 1); + + /* + * Target. + */ + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + isc_region_consume(®ion1, 6); + isc_region_consume(®ion2, 6); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + return (dns_name_rdatacompare(&name1, &name2)); +} + +static inline isc_result_t +fromstruct_in_srv(ARGS_FROMSTRUCT) { + dns_rdata_in_srv_t *srv = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_srv); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(srv->common.rdtype == type); + REQUIRE(srv->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(srv->priority, target)); + RETERR(uint16_tobuffer(srv->weight, target)); + RETERR(uint16_tobuffer(srv->port, target)); + dns_name_toregion(&srv->target, ®ion); + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_in_srv(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_in_srv_t *srv = target; + dns_name_t name; + + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->type == dns_rdatatype_srv); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + srv->common.rdclass = rdata->rdclass; + srv->common.rdtype = rdata->type; + ISC_LINK_INIT(&srv->common, link); + + dns_name_init(&name, NULL); + dns_rdata_toregion(rdata, ®ion); + srv->priority = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + srv->weight = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + srv->port = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + dns_name_init(&srv->target, NULL); + RETERR(name_duporclone(&name, mctx, &srv->target)); + srv->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_srv(ARGS_FREESTRUCT) { + dns_rdata_in_srv_t *srv = source; + + REQUIRE(source != NULL); + REQUIRE(srv->common.rdclass == dns_rdataclass_in); + REQUIRE(srv->common.rdtype == dns_rdatatype_srv); + + if (srv->mctx == NULL) + return; + + dns_name_free(&srv->target, srv->mctx); + srv->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_srv(ARGS_ADDLDATA) { + char buf[sizeof("_65000._tcp")]; + dns_fixedname_t fixed; + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + uint16_t port; + isc_result_t result; + + REQUIRE(rdata->type == dns_rdatatype_srv); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_name_init(&name, offsets); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 4); + port = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + + if (dns_name_equal(&name, dns_rootname)) + return (ISC_R_SUCCESS); + + result = (add)(arg, &name, dns_rdatatype_a); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&fixed); + snprintf(buf, sizeof(buf), "_%u._tcp", port); + result = dns_name_fromstring2(dns_fixedname_name(&fixed), buf, NULL, + 0, NULL); + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + + result = dns_name_concatenate(dns_fixedname_name(&fixed), &name, + dns_fixedname_name(&fixed), NULL); + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + + return ((add)(arg, dns_fixedname_name(&fixed), dns_rdatatype_tlsa)); +} + +static inline isc_result_t +digest_in_srv(ARGS_DIGEST) { + isc_region_t r1, r2; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_srv); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r1); + r2 = r1; + isc_region_consume(&r2, 6); + r1.length = 6; + RETERR((digest)(arg, &r1)); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r2); + return (dns_name_digest(&name, digest, arg)); +} + +static inline bool +checkowner_in_srv(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_srv); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static inline bool +checknames_in_srv(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_srv); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 6); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) + dns_name_clone(&name, bad); + return (false); + } + return (true); +} + +static inline int +casecompare_in_srv(ARGS_COMPARE) { + return (compare_in_srv(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_SRV_33_C */ diff --git a/lib/dns/rdata/in_1/srv_33.h b/lib/dns/rdata/in_1/srv_33.h new file mode 100644 index 0000000..78d5ba9 --- /dev/null +++ b/lib/dns/rdata/in_1/srv_33.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_SRV_33_H +#define IN_1_SRV_33_H 1 + +/*! + * \brief Per RFC2782 */ + +typedef struct dns_rdata_in_srv { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t priority; + uint16_t weight; + uint16_t port; + dns_name_t target; +} dns_rdata_in_srv_t; + +#endif /* IN_1_SRV_33_H */ diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c new file mode 100644 index 0000000..0dc5804 --- /dev/null +++ b/lib/dns/rdata/in_1/wks_11.c @@ -0,0 +1,412 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_IN_1_WKS_11_C +#define RDATA_IN_1_WKS_11_C + +#include <limits.h> +#include <stdlib.h> + +#include <isc/net.h> +#include <isc/netdb.h> +#include <isc/once.h> + +/* + * Redefine CHECK here so cppcheck "sees" the define. + */ +#ifndef CHECK +#define CHECK(op) \ + do { result = (op); \ + if (result != ISC_R_SUCCESS) goto cleanup; \ + } while (0) +#endif + +#define RRTYPE_WKS_ATTRIBUTES (0) + +static isc_mutex_t wks_lock; + +static void init_lock(void) { + RUNTIME_CHECK(isc_mutex_init(&wks_lock) == ISC_R_SUCCESS); +} + +static bool +mygetprotobyname(const char *name, long *proto) { + struct protoent *pe; + + LOCK(&wks_lock); + pe = getprotobyname(name); + if (pe != NULL) + *proto = pe->p_proto; + UNLOCK(&wks_lock); + return (pe != NULL); +} + +static bool +mygetservbyname(const char *name, const char *proto, long *port) { + struct servent *se; + + LOCK(&wks_lock); + se = getservbyname(name, proto); + if (se != NULL) + *port = ntohs(se->s_port); + UNLOCK(&wks_lock); + return (se != NULL); +} + +#ifdef _WIN32 +#include <windows.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#endif + +static inline isc_result_t +fromtext_in_wks(ARGS_FROMTEXT) { + static isc_once_t once = ISC_ONCE_INIT; + isc_token_t token; + isc_region_t region; + struct in_addr addr; + char *e; + long proto; + unsigned char bm[8*1024]; /* 64k bits */ + long port; + long maxport = -1; + const char *ps = NULL; + unsigned int n; + char service[32]; + int i; + isc_result_t result; + + REQUIRE(type == dns_rdatatype_wks); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + + RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); + +#ifdef _WIN32 + { + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData ); + if (err != 0) + return (ISC_R_FAILURE); + } +#endif + + /* + * IPv4 dotted quad. + */ + CHECK(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + isc_buffer_availableregion(target, ®ion); + if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1) + CHECKTOK(DNS_R_BADDOTTEDQUAD); + if (region.length < 4) + return (ISC_R_NOSPACE); + memmove(region.base, &addr, 4); + isc_buffer_add(target, 4); + + /* + * Protocol. + */ + CHECK(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + proto = strtol(DNS_AS_STR(token), &e, 10); + if (*e == 0) + ; + else if (!mygetprotobyname(DNS_AS_STR(token), &proto)) + CHECKTOK(DNS_R_UNKNOWNPROTO); + + if (proto < 0 || proto > 0xff) + CHECKTOK(ISC_R_RANGE); + + if (proto == IPPROTO_TCP) + ps = "tcp"; + else if (proto == IPPROTO_UDP) + ps = "udp"; + + CHECK(uint8_tobuffer(proto, target)); + + memset(bm, 0, sizeof(bm)); + do { + CHECK(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, true)); + if (token.type != isc_tokentype_string) + break; + + /* + * Lowercase the service string as some getservbyname() are + * case sensitive and the database is usually in lowercase. + */ + strncpy(service, DNS_AS_STR(token), sizeof(service)); + service[sizeof(service)-1] = '\0'; + for (i = strlen(service) - 1; i >= 0; i--) + if (isupper(service[i]&0xff)) + service[i] = tolower(service[i]&0xff); + + port = strtol(DNS_AS_STR(token), &e, 10); + if (*e == 0) + ; + else if (!mygetservbyname(service, ps, &port) && + !mygetservbyname(DNS_AS_STR(token), ps, &port)) + CHECKTOK(DNS_R_UNKNOWNSERVICE); + if (port < 0 || port > 0xffff) + CHECKTOK(ISC_R_RANGE); + if (port > maxport) + maxport = port; + bm[port / 8] |= (0x80 >> (port % 8)); + } while (1); + + /* + * Let upper layer handle eol/eof. + */ + isc_lex_ungettoken(lexer, &token); + + n = (maxport + 8) / 8; + result = mem_tobuffer(target, bm, n); + + cleanup: +#ifdef _WIN32 + WSACleanup(); +#endif + + return (result); +} + +static inline isc_result_t +totext_in_wks(ARGS_TOTEXT) { + isc_region_t sr; + unsigned short proto; + char buf[sizeof("65535")]; + unsigned int i, j; + + UNUSED(tctx); + + REQUIRE(rdata->type == dns_rdatatype_wks); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length >= 5); + + dns_rdata_toregion(rdata, &sr); + RETERR(inet_totext(AF_INET, &sr, target)); + isc_region_consume(&sr, 4); + + proto = uint8_fromregion(&sr); + snprintf(buf, sizeof(buf), "%u", proto); + RETERR(str_totext(" ", target)); + RETERR(str_totext(buf, target)); + isc_region_consume(&sr, 1); + + INSIST(sr.length <= 8*1024); + for (i = 0; i < sr.length; i++) { + if (sr.base[i] != 0) + for (j = 0; j < 8; j++) + if ((sr.base[i] & (0x80 >> j)) != 0) { + snprintf(buf, sizeof(buf), + "%u", i * 8 + j); + RETERR(str_totext(" ", target)); + RETERR(str_totext(buf, target)); + } + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_in_wks(ARGS_FROMWIRE) { + isc_region_t sr; + isc_region_t tr; + + REQUIRE(type == dns_rdatatype_wks); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(dctx); + UNUSED(options); + UNUSED(rdclass); + + isc_buffer_activeregion(source, &sr); + isc_buffer_availableregion(target, &tr); + + if (sr.length < 5) + return (ISC_R_UNEXPECTEDEND); + if (sr.length > 8 * 1024 + 5) + return (DNS_R_EXTRADATA); + if (tr.length < sr.length) + return (ISC_R_NOSPACE); + + memmove(tr.base, sr.base, sr.length); + isc_buffer_add(target, sr.length); + isc_buffer_forward(source, sr.length); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_in_wks(ARGS_TOWIRE) { + isc_region_t sr; + + UNUSED(cctx); + + REQUIRE(rdata->type == dns_rdatatype_wks); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_in_wks(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_wks); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_in_wks(ARGS_FROMSTRUCT) { + dns_rdata_in_wks_t *wks = source; + uint32_t a; + + REQUIRE(type == dns_rdatatype_wks); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(source != NULL); + REQUIRE(wks->common.rdtype == type); + REQUIRE(wks->common.rdclass == rdclass); + REQUIRE((wks->map != NULL && wks->map_len <= 8*1024) || + wks->map_len == 0); + + UNUSED(type); + UNUSED(rdclass); + + a = ntohl(wks->in_addr.s_addr); + RETERR(uint32_tobuffer(a, target)); + RETERR(uint8_tobuffer(wks->protocol, target)); + return (mem_tobuffer(target, wks->map, wks->map_len)); +} + +static inline isc_result_t +tostruct_in_wks(ARGS_TOSTRUCT) { + dns_rdata_in_wks_t *wks = target; + uint32_t n; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_wks); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + wks->common.rdclass = rdata->rdclass; + wks->common.rdtype = rdata->type; + ISC_LINK_INIT(&wks->common, link); + + dns_rdata_toregion(rdata, ®ion); + n = uint32_fromregion(®ion); + wks->in_addr.s_addr = htonl(n); + isc_region_consume(®ion, 4); + wks->protocol = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + wks->map_len = region.length; + wks->map = mem_maybedup(mctx, region.base, region.length); + if (wks->map == NULL) + return (ISC_R_NOMEMORY); + wks->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_in_wks(ARGS_FREESTRUCT) { + dns_rdata_in_wks_t *wks = source; + + REQUIRE(source != NULL); + REQUIRE(wks->common.rdtype == dns_rdatatype_wks); + REQUIRE(wks->common.rdclass == dns_rdataclass_in); + + if (wks->mctx == NULL) + return; + + if (wks->map != NULL) + isc_mem_free(wks->mctx, wks->map); + wks->mctx = NULL; +} + +static inline isc_result_t +additionaldata_in_wks(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == dns_rdatatype_wks); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_in_wks(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_wks); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline bool +checkowner_in_wks(ARGS_CHECKOWNER) { + + REQUIRE(type == dns_rdatatype_wks); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + return (dns_name_ishostname(name, wildcard)); +} + +static inline bool +checknames_in_wks(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == dns_rdatatype_wks); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static inline int +casecompare_in_wks(ARGS_COMPARE) { + return (compare_in_wks(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_WKS_11_C */ diff --git a/lib/dns/rdata/in_1/wks_11.h b/lib/dns/rdata/in_1/wks_11.h new file mode 100644 index 0000000..d7883dd --- /dev/null +++ b/lib/dns/rdata/in_1/wks_11.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_WKS_11_H +#define IN_1_WKS_11_H 1 + + +typedef struct dns_rdata_in_wks { + dns_rdatacommon_t common; + isc_mem_t *mctx; + struct in_addr in_addr; + uint16_t protocol; + unsigned char *map; + uint16_t map_len; +} dns_rdata_in_wks_t; + +#endif /* IN_1_WKS_11_H */ diff --git a/lib/dns/rdata/rdatastructpre.h b/lib/dns/rdata/rdatastructpre.h new file mode 100644 index 0000000..d09cb27 --- /dev/null +++ b/lib/dns/rdata/rdatastructpre.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef DNS_RDATASTRUCT_H +#define DNS_RDATASTRUCT_H 1 + +#include <isc/lang.h> +#include <isc/sockaddr.h> + +#include <dns/name.h> +#include <dns/types.h> + +ISC_LANG_BEGINDECLS + +typedef struct dns_rdatacommon { + dns_rdataclass_t rdclass; + dns_rdatatype_t rdtype; + ISC_LINK(struct dns_rdatacommon) link; +} dns_rdatacommon_t; + +#define DNS_RDATACOMMON_INIT(_data, _rdtype, _rdclass) \ + do { \ + (_data)->common.rdtype = (_rdtype); \ + (_data)->common.rdclass = (_rdclass); \ + ISC_LINK_INIT(&(_data)->common, link); \ + } while (0) diff --git a/lib/dns/rdata/rdatastructsuf.h b/lib/dns/rdata/rdatastructsuf.h new file mode 100644 index 0000000..d3a8e46 --- /dev/null +++ b/lib/dns/rdata/rdatastructsuf.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +ISC_LANG_ENDDECLS + +#endif /* DNS_RDATASTRUCT_H */ diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c new file mode 100644 index 0000000..59b3a74 --- /dev/null +++ b/lib/dns/rdatalist.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <stddef.h> +#include <string.h> + +#include <isc/util.h> + +#include <dns/name.h> +#include <dns/nsec3.h> +#include <dns/rdata.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> + +#include "rdatalist_p.h" + +static dns_rdatasetmethods_t methods = { + isc__rdatalist_disassociate, + isc__rdatalist_first, + isc__rdatalist_next, + isc__rdatalist_current, + isc__rdatalist_clone, + isc__rdatalist_count, + isc__rdatalist_addnoqname, + isc__rdatalist_getnoqname, + isc__rdatalist_addclosest, + isc__rdatalist_getclosest, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + isc__rdatalist_setownercase, + isc__rdatalist_getownercase +}; + +void +dns_rdatalist_init(dns_rdatalist_t *rdatalist) { + + REQUIRE(rdatalist != NULL); + + /* + * Initialize rdatalist. + */ + + rdatalist->rdclass = 0; + rdatalist->type = 0; + rdatalist->covers = 0; + rdatalist->ttl = 0; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LINK_INIT(rdatalist, link); + memset(rdatalist->upper, 0xeb, sizeof(rdatalist->upper)); + /* + * Clear upper set bit. + */ + rdatalist->upper[0] &= ~0x01; +} + +isc_result_t +dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist, + dns_rdataset_t *rdataset) +{ + /* + * Make 'rdataset' refer to the rdata in 'rdatalist'. + */ + + REQUIRE(rdatalist != NULL); + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(! dns_rdataset_isassociated(rdataset)); + + /* Check if dns_rdatalist_init has was called. */ + REQUIRE(rdatalist->upper[0] == 0xea); + + rdataset->methods = &methods; + rdataset->rdclass = rdatalist->rdclass; + rdataset->type = rdatalist->type; + rdataset->covers = rdatalist->covers; + rdataset->ttl = rdatalist->ttl; + rdataset->trust = 0; + rdataset->private1 = rdatalist; + rdataset->private2 = NULL; + rdataset->private3 = NULL; + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset, + dns_rdatalist_t **rdatalist) +{ + REQUIRE(rdatalist != NULL && rdataset != NULL); + *rdatalist = rdataset->private1; + + return (ISC_R_SUCCESS); +} + +void +isc__rdatalist_disassociate(dns_rdataset_t *rdataset) { + UNUSED(rdataset); +} + +isc_result_t +isc__rdatalist_first(dns_rdataset_t *rdataset) { + dns_rdatalist_t *rdatalist; + + rdatalist = rdataset->private1; + rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata); + + if (rdataset->private2 == NULL) + return (ISC_R_NOMORE); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__rdatalist_next(dns_rdataset_t *rdataset) { + dns_rdata_t *rdata; + + REQUIRE(rdataset != NULL); + + rdata = rdataset->private2; + if (rdata == NULL) + return (ISC_R_NOMORE); + + rdataset->private2 = ISC_LIST_NEXT(rdata, link); + + if (rdataset->private2 == NULL) + return (ISC_R_NOMORE); + + return (ISC_R_SUCCESS); +} + +void +isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + dns_rdata_t *list_rdata; + + REQUIRE(rdataset != NULL); + + list_rdata = rdataset->private2; + INSIST(list_rdata != NULL); + + dns_rdata_clone(list_rdata, rdata); +} + +void +isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) { + + REQUIRE(source != NULL); + REQUIRE(target != NULL); + + *target = *source; + + /* + * Reset iterator state. + */ + target->private2 = NULL; +} + +unsigned int +isc__rdatalist_count(dns_rdataset_t *rdataset) { + dns_rdatalist_t *rdatalist; + dns_rdata_t *rdata; + unsigned int count; + + REQUIRE(rdataset != NULL); + + rdatalist = rdataset->private1; + + count = 0; + for (rdata = ISC_LIST_HEAD(rdatalist->rdata); + rdata != NULL; + rdata = ISC_LIST_NEXT(rdata, link)) + count++; + + return (count); +} + +isc_result_t +isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) { + dns_rdataset_t *neg = NULL; + dns_rdataset_t *negsig = NULL; + dns_rdataset_t *rdset; + dns_ttl_t ttl; + + REQUIRE(rdataset != NULL); + + for (rdset = ISC_LIST_HEAD(name->list); + rdset != NULL; + rdset = ISC_LIST_NEXT(rdset, link)) + { + if (rdset->rdclass != rdataset->rdclass) + continue; + if (rdset->type == dns_rdatatype_nsec || + rdset->type == dns_rdatatype_nsec3) + neg = rdset; + } + if (neg == NULL) + return (ISC_R_NOTFOUND); + + for (rdset = ISC_LIST_HEAD(name->list); + rdset != NULL; + rdset = ISC_LIST_NEXT(rdset, link)) + { + if (rdset->type == dns_rdatatype_rrsig && + rdset->covers == neg->type) + negsig = rdset; + } + + if (negsig == NULL) + return (ISC_R_NOTFOUND); + /* + * Minimise ttl. + */ + ttl = rdataset->ttl; + if (neg->ttl < ttl) + ttl = neg->ttl; + if (negsig->ttl < ttl) + ttl = negsig->ttl; + rdataset->ttl = neg->ttl = negsig->ttl = ttl; + rdataset->attributes |= DNS_RDATASETATTR_NOQNAME; + rdataset->private6 = name; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, + dns_rdataset_t *neg, dns_rdataset_t *negsig) +{ + dns_rdataclass_t rdclass = rdataset->rdclass; + dns_rdataset_t *tneg = NULL; + dns_rdataset_t *tnegsig = NULL; + dns_name_t *noqname = rdataset->private6; + + REQUIRE(rdataset != NULL); + REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0); + + (void)dns_name_dynamic(noqname); /* Sanity Check. */ + + for (rdataset = ISC_LIST_HEAD(noqname->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (rdataset->rdclass != rdclass) + continue; + if (rdataset->type == dns_rdatatype_nsec || + rdataset->type == dns_rdatatype_nsec3) + tneg = rdataset; + } + if (tneg == NULL) + return (ISC_R_NOTFOUND); + + for (rdataset = ISC_LIST_HEAD(noqname->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (rdataset->type == dns_rdatatype_rrsig && + rdataset->covers == tneg->type) + tnegsig = rdataset; + } + if (tnegsig == NULL) + return (ISC_R_NOTFOUND); + + dns_name_clone(noqname, name); + dns_rdataset_clone(tneg, neg); + dns_rdataset_clone(tnegsig, negsig); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) { + dns_rdataset_t *neg = NULL; + dns_rdataset_t *negsig = NULL; + dns_rdataset_t *rdset; + dns_ttl_t ttl; + + REQUIRE(rdataset != NULL); + + for (rdset = ISC_LIST_HEAD(name->list); + rdset != NULL; + rdset = ISC_LIST_NEXT(rdset, link)) + { + if (rdset->rdclass != rdataset->rdclass) + continue; + if (rdset->type == dns_rdatatype_nsec || + rdset->type == dns_rdatatype_nsec3) + neg = rdset; + } + if (neg == NULL) + return (ISC_R_NOTFOUND); + + for (rdset = ISC_LIST_HEAD(name->list); + rdset != NULL; + rdset = ISC_LIST_NEXT(rdset, link)) + { + if (rdset->type == dns_rdatatype_rrsig && + rdset->covers == neg->type) + negsig = rdset; + } + + if (negsig == NULL) + return (ISC_R_NOTFOUND); + /* + * Minimise ttl. + */ + ttl = rdataset->ttl; + if (neg->ttl < ttl) + ttl = neg->ttl; + if (negsig->ttl < ttl) + ttl = negsig->ttl; + rdataset->ttl = neg->ttl = negsig->ttl = ttl; + rdataset->attributes |= DNS_RDATASETATTR_CLOSEST; + rdataset->private7 = name; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, + dns_rdataset_t *neg, dns_rdataset_t *negsig) +{ + dns_rdataclass_t rdclass = rdataset->rdclass; + dns_rdataset_t *tneg = NULL; + dns_rdataset_t *tnegsig = NULL; + dns_name_t *closest = rdataset->private7; + + REQUIRE(rdataset != NULL); + REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0); + + (void)dns_name_dynamic(closest); /* Sanity Check. */ + + for (rdataset = ISC_LIST_HEAD(closest->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (rdataset->rdclass != rdclass) + continue; + if (rdataset->type == dns_rdatatype_nsec || + rdataset->type == dns_rdatatype_nsec3) + tneg = rdataset; + } + if (tneg == NULL) + return (ISC_R_NOTFOUND); + + for (rdataset = ISC_LIST_HEAD(closest->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (rdataset->type == dns_rdatatype_rrsig && + rdataset->covers == tneg->type) + tnegsig = rdataset; + } + if (tnegsig == NULL) + return (ISC_R_NOTFOUND); + + dns_name_clone(closest, name); + dns_rdataset_clone(tneg, neg); + dns_rdataset_clone(tnegsig, negsig); + return (ISC_R_SUCCESS); +} + +void +isc__rdatalist_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) { + dns_rdatalist_t *rdatalist; + unsigned int i; + + /* + * We do not need to worry about label lengths as they are all + * less than or equal to 63. + */ + rdatalist = rdataset->private1; + memset(rdatalist->upper, 0, sizeof(rdatalist->upper)); + for (i = 1; i < name->length; i++) + if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) + rdatalist->upper[i/8] |= 1 << (i%8); + /* + * Record that upper has been set. + */ + rdatalist->upper[0] |= 0x01; +} + +void +isc__rdatalist_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) { + dns_rdatalist_t *rdatalist; + unsigned int i; + + rdatalist = rdataset->private1; + if ((rdatalist->upper[0] & 0x01) == 0) + return; + for (i = 0; i < name->length; i++) { + /* + * Set the case bit if it does not match the recorded bit. + */ + if (name->ndata[i] >= 0x61 && name->ndata[i] <= 0x7a && + (rdatalist->upper[i/8] & (1 << (i%8))) != 0) + name->ndata[i] &= ~0x20; /* clear the lower case bit */ + else if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a && + (rdatalist->upper[i/8] & (1 << (i%8))) == 0) + name->ndata[i] |= 0x20; /* set the lower case bit */ + } +} diff --git a/lib/dns/rdatalist_p.h b/lib/dns/rdatalist_p.h new file mode 100644 index 0000000..5a599fe --- /dev/null +++ b/lib/dns/rdatalist_p.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef DNS_RDATALIST_P_H +#define DNS_RDATALIST_P_H + +/*! \file */ + +#include <isc/result.h> +#include <dns/types.h> + +ISC_LANG_BEGINDECLS + +void +isc__rdatalist_disassociate(dns_rdataset_t *rdatasetp); + +isc_result_t +isc__rdatalist_first(dns_rdataset_t *rdataset); + +isc_result_t +isc__rdatalist_next(dns_rdataset_t *rdataset); + +void +isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); + +void +isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target); + +unsigned int +isc__rdatalist_count(dns_rdataset_t *rdataset); + +isc_result_t +isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name); + +isc_result_t +isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, + dns_rdataset_t *neg, dns_rdataset_t *negsig); + +isc_result_t +isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name); + +isc_result_t +isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, + dns_rdataset_t *neg, dns_rdataset_t *negsig); + +void +isc__rdatalist_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name); + +void +isc__rdatalist_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name); + +ISC_LANG_ENDDECLS + +#endif /* DNS_RDATALIST_P_H */ diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c new file mode 100644 index 0000000..a2ac36f --- /dev/null +++ b/lib/dns/rdataset.c @@ -0,0 +1,834 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <inttypes.h> +#include <stdlib.h> + +#include <isc/buffer.h> +#include <isc/mem.h> +#include <isc/random.h> +#include <isc/serial.h> +#include <isc/util.h> + +#include <dns/compress.h> +#include <dns/fixedname.h> +#include <dns/name.h> +#include <dns/ncache.h> +#include <dns/rdata.h> +#include <dns/rdataset.h> + +static const char *trustnames[] = { + "none", + "pending-additional", + "pending-answer", + "additional", + "glue", + "answer", + "authauthority", + "authanswer", + "secure", + "local" /* aka ultimate */ +}; + +const char * +dns_trust_totext(dns_trust_t trust) { + if (trust >= sizeof(trustnames)/sizeof(*trustnames)) + return ("bad"); + return (trustnames[trust]); +} + +void +dns_rdataset_init(dns_rdataset_t *rdataset) { + + /* + * Make 'rdataset' a valid, disassociated rdataset. + */ + + REQUIRE(rdataset != NULL); + + rdataset->magic = DNS_RDATASET_MAGIC; + rdataset->methods = NULL; + ISC_LINK_INIT(rdataset, link); + rdataset->rdclass = 0; + rdataset->type = 0; + rdataset->ttl = 0; + rdataset->trust = 0; + rdataset->covers = 0; + rdataset->attributes = 0; + rdataset->count = UINT32_MAX; + rdataset->private1 = NULL; + rdataset->private2 = NULL; + rdataset->private3 = NULL; + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; + rdataset->private6 = NULL; + rdataset->private7 = NULL; + rdataset->resign = 0; +} + +void +dns_rdataset_invalidate(dns_rdataset_t *rdataset) { + + /* + * Invalidate 'rdataset'. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods == NULL); + + rdataset->magic = 0; + ISC_LINK_INIT(rdataset, link); + rdataset->rdclass = 0; + rdataset->type = 0; + rdataset->ttl = 0; + rdataset->trust = 0; + rdataset->covers = 0; + rdataset->attributes = 0; + rdataset->count = UINT32_MAX; + rdataset->private1 = NULL; + rdataset->private2 = NULL; + rdataset->private3 = NULL; + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; +} + +void +dns_rdataset_disassociate(dns_rdataset_t *rdataset) { + + /* + * Disassociate 'rdataset' from its rdata, allowing it to be reused. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + (rdataset->methods->disassociate)(rdataset); + rdataset->methods = NULL; + ISC_LINK_INIT(rdataset, link); + rdataset->rdclass = 0; + rdataset->type = 0; + rdataset->ttl = 0; + rdataset->trust = 0; + rdataset->covers = 0; + rdataset->attributes = 0; + rdataset->count = UINT32_MAX; + rdataset->private1 = NULL; + rdataset->private2 = NULL; + rdataset->private3 = NULL; + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; + rdataset->private6 = NULL; +} + +bool +dns_rdataset_isassociated(dns_rdataset_t *rdataset) { + /* + * Is 'rdataset' associated? + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + + if (rdataset->methods != NULL) + return (true); + + return (false); +} + +static void +question_disassociate(dns_rdataset_t *rdataset) { + UNUSED(rdataset); +} + +static isc_result_t +question_cursor(dns_rdataset_t *rdataset) { + UNUSED(rdataset); + + return (ISC_R_NOMORE); +} + +static void +question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + /* + * This routine should never be called. + */ + UNUSED(rdataset); + UNUSED(rdata); + + REQUIRE(0); +} + +static void +question_clone(dns_rdataset_t *source, dns_rdataset_t *target) { + *target = *source; +} + +static unsigned int +question_count(dns_rdataset_t *rdataset) { + /* + * This routine should never be called. + */ + UNUSED(rdataset); + REQUIRE(0); + + return (0); +} + +static dns_rdatasetmethods_t question_methods = { + question_disassociate, + question_cursor, + question_cursor, + question_current, + question_clone, + question_count, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void +dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass, + dns_rdatatype_t type) +{ + + /* + * Make 'rdataset' a valid, associated, question rdataset, with a + * question class of 'rdclass' and type 'type'. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods == NULL); + + rdataset->methods = &question_methods; + rdataset->rdclass = rdclass; + rdataset->type = type; + rdataset->attributes |= DNS_RDATASETATTR_QUESTION; +} + +unsigned int +dns_rdataset_count(dns_rdataset_t *rdataset) { + + /* + * Return the number of records in 'rdataset'. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + return ((rdataset->methods->count)(rdataset)); +} + +void +dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { + + /* + * Make 'target' refer to the same rdataset as 'source'. + */ + + REQUIRE(DNS_RDATASET_VALID(source)); + REQUIRE(source->methods != NULL); + REQUIRE(DNS_RDATASET_VALID(target)); + REQUIRE(target->methods == NULL); + + (source->methods->clone)(source, target); +} + +isc_result_t +dns_rdataset_first(dns_rdataset_t *rdataset) { + + /* + * Move the rdata cursor to the first rdata in the rdataset (if any). + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + return ((rdataset->methods->first)(rdataset)); +} + +isc_result_t +dns_rdataset_next(dns_rdataset_t *rdataset) { + + /* + * Move the rdata cursor to the next rdata in the rdataset (if any). + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + return ((rdataset->methods->next)(rdataset)); +} + +void +dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + + /* + * Make 'rdata' refer to the current rdata. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + (rdataset->methods->current)(rdataset, rdata); +} + +#define MAX_SHUFFLE 32 +#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0) +#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0) + +struct towire_sort { + int key; + dns_rdata_t *rdata; +}; + +static int +towire_compare(const void *av, const void *bv) { + const struct towire_sort *a = (const struct towire_sort *) av; + const struct towire_sort *b = (const struct towire_sort *) bv; + return (a->key - b->key); +} + +static isc_result_t +towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, + dns_compress_t *cctx, isc_buffer_t *target, + dns_rdatasetorderfunc_t order, const void *order_arg, + bool partial, unsigned int options, + unsigned int *countp, void **state) +{ + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_region_t r; + isc_result_t result; + unsigned int i, count = 0, added, choice; + isc_buffer_t savedbuffer, rdlen, rrbuffer; + unsigned int headlen; + bool question = false; + bool shuffle = false; + dns_rdata_t *in = NULL, in_fixed[MAX_SHUFFLE]; + struct towire_sort *out = NULL, out_fixed[MAX_SHUFFLE]; + dns_fixedname_t fixed; + dns_name_t *name; + + UNUSED(state); + + /* + * Convert 'rdataset' to wire format, compressing names as specified + * in cctx, and storing the result in 'target'. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + REQUIRE(countp != NULL); + REQUIRE((order == NULL) == (order_arg == NULL)); + REQUIRE(cctx != NULL && cctx->mctx != NULL); + + if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) { + question = true; + count = 1; + result = dns_rdataset_first(rdataset); + INSIST(result == ISC_R_NOMORE); + } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { + /* + * This is a negative caching rdataset. + */ + unsigned int ncache_opts = 0; + if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0) + ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC; + return (dns_ncache_towire(rdataset, cctx, target, ncache_opts, + countp)); + } else { + count = (rdataset->methods->count)(rdataset); + result = dns_rdataset_first(rdataset); + if (result == ISC_R_NOMORE) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + return (result); + } + + /* + * Do we want to shuffle this answer? + */ + if (!question && count > 1 && + (!WANT_FIXED(rdataset) || order != NULL) && + rdataset->type != dns_rdatatype_rrsig) + shuffle = true; + + if (shuffle && count > MAX_SHUFFLE) { + in = isc_mem_get(cctx->mctx, count * sizeof(*in)); + out = isc_mem_get(cctx->mctx, count * sizeof(*out)); + if (in == NULL || out == NULL) + shuffle = false; + } else { + in = in_fixed; + out = out_fixed; + } + + if (shuffle) { + /* + * First we get handles to all of the rdata. + */ + i = 0; + do { + INSIST(i < count); + dns_rdata_init(&in[i]); + dns_rdataset_current(rdataset, &in[i]); + i++; + result = dns_rdataset_next(rdataset); + } while (result == ISC_R_SUCCESS); + if (result != ISC_R_NOMORE) + goto cleanup; + INSIST(i == count); + + /* + * Now we shuffle. + */ + if (WANT_FIXED(rdataset)) { + /* + * 'Fixed' order. + */ + INSIST(order != NULL); + for (i = 0; i < count; i++) { + out[i].key = (*order)(&in[i], order_arg); + out[i].rdata = &in[i]; + } + } else if (WANT_RANDOM(rdataset)) { + /* + * 'Random' order. + */ + for (i = 0; i < count; i++) { + uint32_t val; + + isc_random_get(&val); + choice = i + (val % (count - i)); + rdata = in[i]; + in[i] = in[choice]; + in[choice] = rdata; + if (order != NULL) + out[i].key = (*order)(&in[i], + order_arg); + else + out[i].key = 0; /* Unused */ + out[i].rdata = &in[i]; + } + } else { + /* + * "Cyclic" order. + */ + uint32_t val; + unsigned int j; + + val = rdataset->count; + if (val == UINT32_MAX) + isc_random_get(&val); + j = val % count; + for (i = 0; i < count; i++) { + if (order != NULL) + out[i].key = (*order)(&in[j], + order_arg); + else + out[i].key = 0; /* Unused */ + out[i].rdata = &in[j]; + j++; + if (j == count) + j = 0; /* Wrap around. */ + } + } + + /* + * Sorted order. + */ + if (order != NULL) + qsort(out, count, sizeof(out[0]), towire_compare); + } + + savedbuffer = *target; + i = 0; + added = 0; + + name = dns_fixedname_initname(&fixed); + dns_name_copy(owner_name, name, NULL); + dns_rdataset_getownercase(rdataset, name); + + name->attributes |= owner_name->attributes & + DNS_NAMEATTR_NOCOMPRESS; + + do { + /* + * Copy out the name, type, class, ttl. + */ + + rrbuffer = *target; + dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); + result = dns_name_towire(name, cctx, target); + if (result != ISC_R_SUCCESS) + goto rollback; + headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t); + if (!question) + headlen += sizeof(dns_ttl_t) + + 2; /* XXX 2 for rdata len */ + isc_buffer_availableregion(target, &r); + if (r.length < headlen) { + result = ISC_R_NOSPACE; + goto rollback; + } + isc_buffer_putuint16(target, rdataset->type); + isc_buffer_putuint16(target, rdataset->rdclass); + if (!question) { + isc_buffer_putuint32(target, rdataset->ttl); + + /* + * Save space for rdlen. + */ + rdlen = *target; + isc_buffer_add(target, 2); + + /* + * Copy out the rdata + */ + if (shuffle) + rdata = *(out[i].rdata); + else { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + } + result = dns_rdata_towire(&rdata, cctx, target); + if (result != ISC_R_SUCCESS) + goto rollback; + INSIST((target->used >= rdlen.used + 2) && + (target->used - rdlen.used - 2 < 65536)); + isc_buffer_putuint16(&rdlen, + (uint16_t)(target->used - + rdlen.used - 2)); + added++; + } + + if (shuffle) { + i++; + if (i == count) + result = ISC_R_NOMORE; + else + result = ISC_R_SUCCESS; + } else { + result = dns_rdataset_next(rdataset); + } + } while (result == ISC_R_SUCCESS); + + if (result != ISC_R_NOMORE) + goto rollback; + + *countp += count; + + result = ISC_R_SUCCESS; + goto cleanup; + + rollback: + if (partial && result == ISC_R_NOSPACE) { + INSIST(rrbuffer.used < 65536); + dns_compress_rollback(cctx, (uint16_t)rrbuffer.used); + *countp += added; + *target = rrbuffer; + goto cleanup; + } + INSIST(savedbuffer.used < 65536); + dns_compress_rollback(cctx, (uint16_t)savedbuffer.used); + *countp = 0; + *target = savedbuffer; + + cleanup: + if (out != NULL && out != out_fixed) + isc_mem_put(cctx->mctx, out, count * sizeof(*out)); + if (in != NULL && in != in_fixed) + isc_mem_put(cctx->mctx, in, count * sizeof(*in)); + return (result); +} + +isc_result_t +dns_rdataset_towiresorted(dns_rdataset_t *rdataset, + const dns_name_t *owner_name, + dns_compress_t *cctx, + isc_buffer_t *target, + dns_rdatasetorderfunc_t order, + const void *order_arg, + unsigned int options, + unsigned int *countp) +{ + return (towiresorted(rdataset, owner_name, cctx, target, + order, order_arg, false, options, + countp, NULL)); +} + +isc_result_t +dns_rdataset_towirepartial(dns_rdataset_t *rdataset, + const dns_name_t *owner_name, + dns_compress_t *cctx, + isc_buffer_t *target, + dns_rdatasetorderfunc_t order, + const void *order_arg, + unsigned int options, + unsigned int *countp, + void **state) +{ + REQUIRE(state == NULL); /* XXX remove when implemented */ + return (towiresorted(rdataset, owner_name, cctx, target, + order, order_arg, true, options, + countp, state)); +} + +isc_result_t +dns_rdataset_towire(dns_rdataset_t *rdataset, + dns_name_t *owner_name, + dns_compress_t *cctx, + isc_buffer_t *target, + unsigned int options, + unsigned int *countp) +{ + return (towiresorted(rdataset, owner_name, cctx, target, + NULL, NULL, false, options, countp, NULL)); +} + +isc_result_t +dns_rdataset_additionaldata(dns_rdataset_t *rdataset, + dns_additionaldatafunc_t add, void *arg) +{ + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_result_t result; + + /* + * For each rdata in rdataset, call 'add' for each name and type in the + * rdata which is subject to additional section processing. + */ + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0); + + result = dns_rdataset_first(rdataset); + if (result != ISC_R_SUCCESS) + return (result); + + do { + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_additionaldata(&rdata, add, arg); + if (result == ISC_R_SUCCESS) + result = dns_rdataset_next(rdataset); + dns_rdata_reset(&rdata); + } while (result == ISC_R_SUCCESS); + + if (result != ISC_R_NOMORE) + return (result); + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) { + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + if (rdataset->methods->addnoqname == NULL) + return (ISC_R_NOTIMPLEMENTED); + return((rdataset->methods->addnoqname)(rdataset, name)); +} + +isc_result_t +dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, + dns_rdataset_t *neg, dns_rdataset_t *negsig) +{ + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->getnoqname == NULL) + return (ISC_R_NOTIMPLEMENTED); + return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig)); +} + +isc_result_t +dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) { + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + if (rdataset->methods->addclosest == NULL) + return (ISC_R_NOTIMPLEMENTED); + return((rdataset->methods->addclosest)(rdataset, name)); +} + +isc_result_t +dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, + dns_rdataset_t *neg, dns_rdataset_t *negsig) +{ + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->getclosest == NULL) + return (ISC_R_NOTIMPLEMENTED); + return((rdataset->methods->getclosest)(rdataset, name, neg, negsig)); +} + +/* + * Additional cache stuff + */ +isc_result_t +dns_rdataset_getadditional(dns_rdataset_t *rdataset, + dns_rdatasetadditional_t type, + dns_rdatatype_t qtype, + dns_acache_t *acache, + dns_zone_t **zonep, + dns_db_t **dbp, + dns_dbversion_t **versionp, + dns_dbnode_t **nodep, + dns_name_t *fname, + dns_message_t *msg, + isc_stdtime_t now) +{ + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + REQUIRE(zonep == NULL || *zonep == NULL); + REQUIRE(dbp != NULL && *dbp == NULL); + REQUIRE(versionp != NULL && *versionp == NULL); + REQUIRE(nodep != NULL && *nodep == NULL); + REQUIRE(fname != NULL); + REQUIRE(msg != NULL); + + if (acache != NULL && rdataset->methods->getadditional != NULL) { + return ((rdataset->methods->getadditional)(rdataset, type, + qtype, acache, + zonep, dbp, + versionp, nodep, + fname, msg, now)); + } + + return (ISC_R_FAILURE); +} + +isc_result_t +dns_rdataset_setadditional(dns_rdataset_t *rdataset, + dns_rdatasetadditional_t type, + dns_rdatatype_t qtype, + dns_acache_t *acache, + dns_zone_t *zone, + dns_db_t *db, + dns_dbversion_t *version, + dns_dbnode_t *node, + dns_name_t *fname) +{ + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (acache != NULL && rdataset->methods->setadditional != NULL) { + return ((rdataset->methods->setadditional)(rdataset, type, + qtype, acache, zone, + db, version, + node, fname)); + } + + return (ISC_R_FAILURE); +} + +isc_result_t +dns_rdataset_putadditional(dns_acache_t *acache, + dns_rdataset_t *rdataset, + dns_rdatasetadditional_t type, + dns_rdatatype_t qtype) +{ + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (acache != NULL && rdataset->methods->putadditional != NULL) { + return ((rdataset->methods->putadditional)(acache, rdataset, + type, qtype)); + } + + return (ISC_R_FAILURE); +} + +void +dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->settrust != NULL) + (rdataset->methods->settrust)(rdataset, trust); + else + rdataset->trust = trust; +} + +void +dns_rdataset_expire(dns_rdataset_t *rdataset) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->expire != NULL) + (rdataset->methods->expire)(rdataset); +} + +void +dns_rdataset_clearprefetch(dns_rdataset_t *rdataset) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->clearprefetch != NULL) + (rdataset->methods->clearprefetch)(rdataset); +} + +void +dns_rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->setownercase != NULL) + (rdataset->methods->setownercase)(rdataset, name); +} + +void +dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->getownercase != NULL) + (rdataset->methods->getownercase)(rdataset, name); +} + +void +dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, + dns_rdata_rrsig_t *rrsig, isc_stdtime_t now, + bool acceptexpired) +{ + uint32_t ttl = 0; + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(DNS_RDATASET_VALID(sigrdataset)); + REQUIRE(rrsig != NULL); + + /* + * If we accept expired RRsets keep them for no more than 120 seconds. + */ + if (acceptexpired && + (isc_serial_le(rrsig->timeexpire, ((now + 120) & 0xffffffff)) || + isc_serial_le(rrsig->timeexpire, now))) + ttl = 120; + else if (isc_serial_ge(rrsig->timeexpire, now)) + ttl = rrsig->timeexpire - now; + + ttl = ISC_MIN(ISC_MIN(rdataset->ttl, sigrdataset->ttl), + ISC_MIN(rrsig->originalttl, ttl)); + rdataset->ttl = ttl; + sigrdataset->ttl = ttl; +} diff --git a/lib/dns/rdatasetiter.c b/lib/dns/rdatasetiter.c new file mode 100644 index 0000000..c292ef2 --- /dev/null +++ b/lib/dns/rdatasetiter.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <stddef.h> + +#include <isc/util.h> + +#include <dns/rdataset.h> +#include <dns/rdatasetiter.h> + +void +dns_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { + /* + * Destroy '*iteratorp'. + */ + + REQUIRE(iteratorp != NULL); + REQUIRE(DNS_RDATASETITER_VALID(*iteratorp)); + + (*iteratorp)->methods->destroy(iteratorp); + + ENSURE(*iteratorp == NULL); +} + +isc_result_t +dns_rdatasetiter_first(dns_rdatasetiter_t *iterator) { + /* + * Move the rdataset cursor to the first rdataset at the node (if any). + */ + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + + return (iterator->methods->first(iterator)); +} + +isc_result_t +dns_rdatasetiter_next(dns_rdatasetiter_t *iterator) { + /* + * Move the rdataset cursor to the next rdataset at the node (if any). + */ + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + + return (iterator->methods->next(iterator)); +} + +void +dns_rdatasetiter_current(dns_rdatasetiter_t *iterator, + dns_rdataset_t *rdataset) +{ + /* + * Return the current rdataset. + */ + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(! dns_rdataset_isassociated(rdataset)); + + iterator->methods->current(iterator, rdataset); +} diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c new file mode 100644 index 0000000..930a822 --- /dev/null +++ b/lib/dns/rdataslab.c @@ -0,0 +1,1134 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <stdlib.h> + +#include <isc/mem.h> +#include <isc/region.h> +#include <isc/string.h> /* Required for HP/UX (and others?) */ +#include <isc/util.h> + +#include <dns/result.h> +#include <dns/rdata.h> +#include <dns/rdataset.h> +#include <dns/rdataslab.h> + +/* + * The rdataslab structure allows iteration to occur in both load order + * and DNSSEC order. The structure is as follows: + * + * header (reservelen bytes) + * record count (2 bytes) + * offset table (4 x record count bytes in load order) + * data records + * data length (2 bytes) + * order (2 bytes) + * meta data (1 byte for RRSIG's) + * data (data length bytes) + * + * If DNS_RDATASET_FIXED is defined to be zero (0) the format of a + * rdataslab is as follows: + * + * header (reservelen bytes) + * record count (2 bytes) + * data records + * data length (2 bytes) + * meta data (1 byte for RRSIG's) + * data (data length bytes) + * + * Offsets are from the end of the header. + * + * Load order traversal is performed by walking the offset table to find + * the start of the record (DNS_RDATASET_FIXED = 1). + * + * DNSSEC order traversal is performed by walking the data records. + * + * The order is stored with record to allow for efficient reconstruction + * of the offset table following a merge or subtraction. + * + * The iterator methods here currently only support DNSSEC order iteration. + * + * The iterator methods in rbtdb support both load order and DNSSEC order + * iteration. + * + * WARNING: + * rbtdb.c directly interacts with the slab's raw structures. If the + * structure changes then rbtdb.c also needs to be updated to reflect + * the changes. See the areas tagged with "RDATASLAB". + */ + +struct xrdata { + dns_rdata_t rdata; + unsigned int order; +}; + +/*% Note: the "const void *" are just to make qsort happy. */ +static int +compare_rdata(const void *p1, const void *p2) { + const struct xrdata *x1 = p1; + const struct xrdata *x2 = p2; + return (dns_rdata_compare(&x1->rdata, &x2->rdata)); +} + +#if DNS_RDATASET_FIXED +static void +fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable, + unsigned length) +{ + unsigned int i, j; + unsigned char *raw; + + for (i = 0, j = 0; i < length; i++) { + + if (offsettable[i] == 0) + continue; + + /* + * Fill in offset table. + */ + raw = &offsetbase[j*4 + 2]; + *raw++ = (offsettable[i] & 0xff000000) >> 24; + *raw++ = (offsettable[i] & 0xff0000) >> 16; + *raw++ = (offsettable[i] & 0xff00) >> 8; + *raw = offsettable[i] & 0xff; + + /* + * Fill in table index. + */ + raw = offsetbase + offsettable[i] + 2; + *raw++ = (j & 0xff00) >> 8; + *raw = j++ & 0xff; + } +} +#endif + +isc_result_t +dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, + isc_region_t *region, unsigned int reservelen) +{ + /* + * Use &removed as a sentinal pointer for duplicate + * rdata as rdata.data == NULL is valid. + */ + static unsigned char removed; + struct xrdata *x; + unsigned char *rawbuf; +#if DNS_RDATASET_FIXED + unsigned char *offsetbase; +#endif + unsigned int buflen; + isc_result_t result; + unsigned int nitems; + unsigned int nalloc; + unsigned int i; +#if DNS_RDATASET_FIXED + unsigned int *offsettable; +#endif + unsigned int length; + + buflen = reservelen + 2; + + nitems = dns_rdataset_count(rdataset); + + /* + * If there are no rdata then we can just need to allocate a header + * with zero a record count. + */ + if (nitems == 0) { + if (rdataset->type != 0) + return (ISC_R_FAILURE); + rawbuf = isc_mem_get(mctx, buflen); + if (rawbuf == NULL) + return (ISC_R_NOMEMORY); + region->base = rawbuf; + region->length = buflen; + rawbuf += reservelen; + *rawbuf++ = 0; + *rawbuf = 0; + return (ISC_R_SUCCESS); + } + + if (nitems > 0xffff) + return (ISC_R_NOSPACE); + + /* + * Remember the original number of items. + */ + nalloc = nitems; + x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); + if (x == NULL) + return (ISC_R_NOMEMORY); + + /* + * Save all of the rdata members into an array. + */ + result = dns_rdataset_first(rdataset); + if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) + goto free_rdatas; + for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) { + INSIST(result == ISC_R_SUCCESS); + dns_rdata_init(&x[i].rdata); + dns_rdataset_current(rdataset, &x[i].rdata); + INSIST(x[i].rdata.data != &removed); +#if DNS_RDATASET_FIXED + x[i].order = i; +#endif + result = dns_rdataset_next(rdataset); + } + if (i != nalloc || result != ISC_R_NOMORE) { + /* + * Somehow we iterated over fewer rdatas than + * dns_rdataset_count() said there were or there + * were more items than dns_rdataset_count said + * there were. + */ + result = ISC_R_FAILURE; + goto free_rdatas; + } + + /* + * Put into DNSSEC order. + */ + if (nalloc > 1U) + qsort(x, nalloc, sizeof(struct xrdata), compare_rdata); + + /* + * Remove duplicates and compute the total storage required. + * + * If an rdata is not a duplicate, accumulate the storage size + * required for the rdata. We do not store the class, type, etc, + * just the rdata, so our overhead is 2 bytes for the number of + * records, and 8 for each rdata, (length(2), offset(4) and order(2)) + * and then the rdata itself. + */ + for (i = 1; i < nalloc; i++) { + if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) { + x[i-1].rdata.data = &removed; +#if DNS_RDATASET_FIXED + /* + * Preserve the least order so A, B, A -> A, B + * after duplicate removal. + */ + if (x[i-1].order < x[i].order) + x[i].order = x[i-1].order; +#endif + nitems--; + } else { +#if DNS_RDATASET_FIXED + buflen += (8 + x[i-1].rdata.length); +#else + buflen += (2 + x[i-1].rdata.length); +#endif + /* + * Provide space to store the per RR meta data. + */ + if (rdataset->type == dns_rdatatype_rrsig) + buflen++; + } + } + + /* + * Don't forget the last item! + */ +#if DNS_RDATASET_FIXED + buflen += (8 + x[i-1].rdata.length); +#else + buflen += (2 + x[i-1].rdata.length); +#endif + /* + * Provide space to store the per RR meta data. + */ + if (rdataset->type == dns_rdatatype_rrsig) + buflen++; + + /* + * Ensure that singleton types are actually singletons. + */ + if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) { + /* + * We have a singleton type, but there's more than one + * RR in the rdataset. + */ + result = DNS_R_SINGLETON; + goto free_rdatas; + } + + /* + * Allocate the memory, set up a buffer, start copying in + * data. + */ + rawbuf = isc_mem_get(mctx, buflen); + if (rawbuf == NULL) { + result = ISC_R_NOMEMORY; + goto free_rdatas; + } + +#if DNS_RDATASET_FIXED + /* Allocate temporary offset table. */ + offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int)); + if (offsettable == NULL) { + isc_mem_put(mctx, rawbuf, buflen); + result = ISC_R_NOMEMORY; + goto free_rdatas; + } + memset(offsettable, 0, nalloc * sizeof(unsigned int)); +#endif + + region->base = rawbuf; + region->length = buflen; + + memset(rawbuf, 0, buflen); + rawbuf += reservelen; + +#if DNS_RDATASET_FIXED + offsetbase = rawbuf; +#endif + + *rawbuf++ = (nitems & 0xff00) >> 8; + *rawbuf++ = (nitems & 0x00ff); + +#if DNS_RDATASET_FIXED + /* Skip load order table. Filled in later. */ + rawbuf += nitems * 4; +#endif + + for (i = 0; i < nalloc; i++) { + if (x[i].rdata.data == &removed) + continue; +#if DNS_RDATASET_FIXED + offsettable[x[i].order] = rawbuf - offsetbase; +#endif + length = x[i].rdata.length; + if (rdataset->type == dns_rdatatype_rrsig) + length++; + INSIST(length <= 0xffff); + *rawbuf++ = (length & 0xff00) >> 8; + *rawbuf++ = (length & 0x00ff); +#if DNS_RDATASET_FIXED + rawbuf += 2; /* filled in later */ +#endif + /* + * Store the per RR meta data. + */ + if (rdataset->type == dns_rdatatype_rrsig) { + *rawbuf++ = (x[i].rdata.flags & DNS_RDATA_OFFLINE) ? + DNS_RDATASLAB_OFFLINE : 0; + } + memmove(rawbuf, x[i].rdata.data, x[i].rdata.length); + rawbuf += x[i].rdata.length; + } + +#if DNS_RDATASET_FIXED + fillin_offsets(offsetbase, offsettable, nalloc); + isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int)); +#endif + + result = ISC_R_SUCCESS; + + free_rdatas: + isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); + return (result); +} + +static void +rdataset_disassociate(dns_rdataset_t *rdataset) { + UNUSED(rdataset); +} + +static isc_result_t +rdataset_first(dns_rdataset_t *rdataset) { + unsigned char *raw = rdataset->private3; + unsigned int count; + + count = raw[0] * 256 + raw[1]; + if (count == 0) { + rdataset->private5 = NULL; + return (ISC_R_NOMORE); + } +#if DNS_RDATASET_FIXED + raw += 2 + (4 * count); +#else + raw += 2; +#endif + /* + * The privateuint4 field is the number of rdata beyond the cursor + * position, so we decrement the total count by one before storing + * it. + */ + count--; + rdataset->privateuint4 = count; + rdataset->private5 = raw; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +rdataset_next(dns_rdataset_t *rdataset) { + unsigned int count; + unsigned int length; + unsigned char *raw; + + count = rdataset->privateuint4; + if (count == 0) + return (ISC_R_NOMORE); + count--; + rdataset->privateuint4 = count; + raw = rdataset->private5; + length = raw[0] * 256 + raw[1]; +#if DNS_RDATASET_FIXED + raw += length + 4; +#else + raw += length + 2; +#endif + rdataset->private5 = raw; + + return (ISC_R_SUCCESS); +} + +static void +rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + unsigned char *raw = rdataset->private5; + isc_region_t r; + unsigned int length; + unsigned int flags = 0; + + REQUIRE(raw != NULL); + + length = raw[0] * 256 + raw[1]; +#if DNS_RDATASET_FIXED + raw += 4; +#else + raw += 2; +#endif + if (rdataset->type == dns_rdatatype_rrsig) { + if (*raw & DNS_RDATASLAB_OFFLINE) + flags |= DNS_RDATA_OFFLINE; + length--; + raw++; + } + r.length = length; + r.base = raw; + dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); + rdata->flags |= flags; +} + +static void +rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { + *target = *source; + + /* + * Reset iterator state. + */ + target->privateuint4 = 0; + target->private5 = NULL; +} + +static unsigned int +rdataset_count(dns_rdataset_t *rdataset) { + unsigned char *raw = rdataset->private3; + unsigned int count; + + count = raw[0] * 256 + raw[1]; + + return (count); +} + +static dns_rdatasetmethods_t rdataset_methods = { + rdataset_disassociate, + rdataset_first, + rdataset_next, + rdataset_current, + rdataset_clone, + rdataset_count, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void +dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen, + dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, + dns_rdatatype_t covers, dns_ttl_t ttl, + dns_rdataset_t *rdataset) +{ + REQUIRE(slab != NULL); + REQUIRE(!dns_rdataset_isassociated(rdataset)); + + rdataset->methods = &rdataset_methods; + rdataset->rdclass = rdclass; + rdataset->type = rdtype; + rdataset->covers = covers; + rdataset->ttl = ttl; + rdataset->trust = 0; + rdataset->private1 = NULL; + rdataset->private2 = NULL; + rdataset->private3 = slab + reservelen; + + /* + * Reset iterator state. + */ + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; +} + +unsigned int +dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) { + unsigned int count, length; + unsigned char *current; + + REQUIRE(slab != NULL); + + current = slab + reservelen; + count = *current++ * 256; + count += *current++; +#if DNS_RDATASET_FIXED + current += (4 * count); +#endif + while (count > 0) { + count--; + length = *current++ * 256; + length += *current++; +#if DNS_RDATASET_FIXED + current += length + 2; +#else + current += length; +#endif + } + + return ((unsigned int)(current - slab)); +} + +unsigned int +dns_rdataslab_count(unsigned char *slab, unsigned int reservelen) { + unsigned int count; + unsigned char *current; + + REQUIRE(slab != NULL); + + current = slab + reservelen; + count = *current++ * 256; + count += *current++; + return (count); +} + +/* + * Make the dns_rdata_t 'rdata' refer to the slab item + * beginning at '*current', which is part of a slab of type + * 'type' and class 'rdclass', and advance '*current' to + * point to the next item in the slab. + */ +static inline void +rdata_from_slab(unsigned char **current, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + dns_rdata_t *rdata) +{ + unsigned char *tcurrent = *current; + isc_region_t region; + unsigned int length; + bool offline = false; + + length = *tcurrent++ * 256; + length += *tcurrent++; + + if (type == dns_rdatatype_rrsig) { + if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0) + offline = true; + length--; + tcurrent++; + } + region.length = length; +#if DNS_RDATASET_FIXED + tcurrent += 2; +#endif + region.base = tcurrent; + tcurrent += region.length; + dns_rdata_fromregion(rdata, rdclass, type, ®ion); + if (offline) + rdata->flags |= DNS_RDATA_OFFLINE; + *current = tcurrent; +} + +/* + * Return true iff 'slab' (slab data of type 'type' and class 'rdclass') + * contains an rdata identical to 'rdata'. This does case insensitive + * comparisons per DNSSEC. + */ +static inline bool +rdata_in_slab(unsigned char *slab, unsigned int reservelen, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + dns_rdata_t *rdata) +{ + unsigned int count, i; + unsigned char *current; + dns_rdata_t trdata = DNS_RDATA_INIT; + int n; + + current = slab + reservelen; + count = *current++ * 256; + count += *current++; + +#if DNS_RDATASET_FIXED + current += (4 * count); +#endif + + for (i = 0; i < count; i++) { + rdata_from_slab(¤t, rdclass, type, &trdata); + + n = dns_rdata_compare(&trdata, rdata); + if (n == 0) + return (true); + if (n > 0) /* In DNSSEC order. */ + break; + dns_rdata_reset(&trdata); + } + return (false); +} + +isc_result_t +dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, + unsigned int reservelen, isc_mem_t *mctx, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int flags, unsigned char **tslabp) +{ + unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data; + unsigned int ocount, ncount, count, olength, tlength, tcount, length; + dns_rdata_t ordata = DNS_RDATA_INIT; + dns_rdata_t nrdata = DNS_RDATA_INIT; + bool added_something = false; + unsigned int oadded = 0; + unsigned int nadded = 0; + unsigned int nncount = 0; +#if DNS_RDATASET_FIXED + unsigned int oncount; + unsigned int norder = 0; + unsigned int oorder = 0; + unsigned char *offsetbase; + unsigned int *offsettable; +#endif + + /* + * XXX Need parameter to allow "delete rdatasets in nslab" merge, + * or perhaps another merge routine for this purpose. + */ + + REQUIRE(tslabp != NULL && *tslabp == NULL); + REQUIRE(oslab != NULL && nslab != NULL); + + ocurrent = oslab + reservelen; + ocount = *ocurrent++ * 256; + ocount += *ocurrent++; +#if DNS_RDATASET_FIXED + ocurrent += (4 * ocount); +#endif + ostart = ocurrent; + ncurrent = nslab + reservelen; + ncount = *ncurrent++ * 256; + ncount += *ncurrent++; +#if DNS_RDATASET_FIXED + ncurrent += (4 * ncount); +#endif + INSIST(ocount > 0 && ncount > 0); + +#if DNS_RDATASET_FIXED + oncount = ncount; +#endif + + /* + * Yes, this is inefficient! + */ + + /* + * Figure out the length of the old slab's data. + */ + olength = 0; + for (count = 0; count < ocount; count++) { + length = *ocurrent++ * 256; + length += *ocurrent++; +#if DNS_RDATASET_FIXED + olength += length + 8; + ocurrent += length + 2; +#else + olength += length + 2; + ocurrent += length; +#endif + } + + /* + * Start figuring out the target length and count. + */ + tlength = reservelen + 2 + olength; + tcount = ocount; + + /* + * Add in the length of rdata in the new slab that aren't in + * the old slab. + */ + do { + dns_rdata_init(&nrdata); + rdata_from_slab(&ncurrent, rdclass, type, &nrdata); + if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)) + { + /* + * This rdata isn't in the old slab. + */ +#if DNS_RDATASET_FIXED + tlength += nrdata.length + 8; +#else + tlength += nrdata.length + 2; +#endif + if (type == dns_rdatatype_rrsig) + tlength++; + tcount++; + nncount++; + added_something = true; + } + ncount--; + } while (ncount > 0); + ncount = nncount; + + if (((flags & DNS_RDATASLAB_EXACT) != 0) && + (tcount != ncount + ocount)) + return (DNS_R_NOTEXACT); + + if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0) + return (DNS_R_UNCHANGED); + + /* + * Ensure that singleton types are actually singletons. + */ + if (tcount > 1 && dns_rdatatype_issingleton(type)) { + /* + * We have a singleton type, but there's more than one + * RR in the rdataset. + */ + return (DNS_R_SINGLETON); + } + + if (tcount > 0xffff) + return (ISC_R_NOSPACE); + + /* + * Copy the reserved area from the new slab. + */ + tstart = isc_mem_get(mctx, tlength); + if (tstart == NULL) + return (ISC_R_NOMEMORY); + memmove(tstart, nslab, reservelen); + tcurrent = tstart + reservelen; +#if DNS_RDATASET_FIXED + offsetbase = tcurrent; +#endif + + /* + * Write the new count. + */ + *tcurrent++ = (tcount & 0xff00) >> 8; + *tcurrent++ = (tcount & 0x00ff); + +#if DNS_RDATASET_FIXED + /* + * Skip offset table. + */ + tcurrent += (tcount * 4); + + offsettable = isc_mem_get(mctx, + (ocount + oncount) * sizeof(unsigned int)); + if (offsettable == NULL) { + isc_mem_put(mctx, tstart, tlength); + return (ISC_R_NOMEMORY); + } + memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int)); +#endif + + /* + * Merge the two slabs. + */ + ocurrent = ostart; + INSIST(ocount != 0); +#if DNS_RDATASET_FIXED + oorder = ocurrent[2] * 256 + ocurrent[3]; + INSIST(oorder < ocount); +#endif + rdata_from_slab(&ocurrent, rdclass, type, &ordata); + + ncurrent = nslab + reservelen + 2; +#if DNS_RDATASET_FIXED + ncurrent += (4 * oncount); +#endif + + if (ncount > 0) { + do { + dns_rdata_reset(&nrdata); +#if DNS_RDATASET_FIXED + norder = ncurrent[2] * 256 + ncurrent[3]; + + INSIST(norder < oncount); +#endif + rdata_from_slab(&ncurrent, rdclass, type, &nrdata); + } while (rdata_in_slab(oslab, reservelen, rdclass, + type, &nrdata)); + } + + while (oadded < ocount || nadded < ncount) { + bool fromold; + if (oadded == ocount) + fromold = false; + else if (nadded == ncount) + fromold = true; + else + fromold = dns_rdata_compare(&ordata, &nrdata) < 0; + if (fromold) { +#if DNS_RDATASET_FIXED + offsettable[oorder] = tcurrent - offsetbase; +#endif + length = ordata.length; + data = ordata.data; + if (type == dns_rdatatype_rrsig) { + length++; + data--; + } + *tcurrent++ = (length & 0xff00) >> 8; + *tcurrent++ = (length & 0x00ff); +#if DNS_RDATASET_FIXED + tcurrent += 2; /* fill in later */ +#endif + memmove(tcurrent, data, length); + tcurrent += length; + oadded++; + if (oadded < ocount) { + dns_rdata_reset(&ordata); +#if DNS_RDATASET_FIXED + oorder = ocurrent[2] * 256 + ocurrent[3]; + INSIST(oorder < ocount); +#endif + rdata_from_slab(&ocurrent, rdclass, type, + &ordata); + } + } else { +#if DNS_RDATASET_FIXED + offsettable[ocount + norder] = tcurrent - offsetbase; +#endif + length = nrdata.length; + data = nrdata.data; + if (type == dns_rdatatype_rrsig) { + length++; + data--; + } + *tcurrent++ = (length & 0xff00) >> 8; + *tcurrent++ = (length & 0x00ff); +#if DNS_RDATASET_FIXED + tcurrent += 2; /* fill in later */ +#endif + memmove(tcurrent, data, length); + tcurrent += length; + nadded++; + if (nadded < ncount) { + do { + dns_rdata_reset(&nrdata); +#if DNS_RDATASET_FIXED + norder = ncurrent[2] * 256 + ncurrent[3]; + INSIST(norder < oncount); +#endif + rdata_from_slab(&ncurrent, rdclass, + type, &nrdata); + } while (rdata_in_slab(oslab, reservelen, + rdclass, type, + &nrdata)); + } + } + } + +#if DNS_RDATASET_FIXED + fillin_offsets(offsetbase, offsettable, ocount + oncount); + + isc_mem_put(mctx, offsettable, + (ocount + oncount) * sizeof(unsigned int)); +#endif + + INSIST(tcurrent == tstart + tlength); + + *tslabp = tstart; + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab, + unsigned int reservelen, isc_mem_t *mctx, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int flags, unsigned char **tslabp) +{ + unsigned char *mcurrent, *sstart, *scurrent, *tstart, *tcurrent; + unsigned int mcount, scount, rcount ,count, tlength, tcount, i; + dns_rdata_t srdata = DNS_RDATA_INIT; + dns_rdata_t mrdata = DNS_RDATA_INIT; +#if DNS_RDATASET_FIXED + unsigned char *offsetbase; + unsigned int *offsettable; + unsigned int order; +#endif + + REQUIRE(tslabp != NULL && *tslabp == NULL); + REQUIRE(mslab != NULL && sslab != NULL); + + mcurrent = mslab + reservelen; + mcount = *mcurrent++ * 256; + mcount += *mcurrent++; + scurrent = sslab + reservelen; + scount = *scurrent++ * 256; + scount += *scurrent++; + INSIST(mcount > 0 && scount > 0); + + /* + * Yes, this is inefficient! + */ + + /* + * Start figuring out the target length and count. + */ + tlength = reservelen + 2; + tcount = 0; + rcount = 0; + +#if DNS_RDATASET_FIXED + mcurrent += 4 * mcount; + scurrent += 4 * scount; +#endif + sstart = scurrent; + + /* + * Add in the length of rdata in the mslab that aren't in + * the sslab. + */ + for (i = 0; i < mcount; i++) { + unsigned char *mrdatabegin = mcurrent; + rdata_from_slab(&mcurrent, rdclass, type, &mrdata); + scurrent = sstart; + for (count = 0; count < scount; count++) { + dns_rdata_reset(&srdata); + rdata_from_slab(&scurrent, rdclass, type, &srdata); + if (dns_rdata_compare(&mrdata, &srdata) == 0) + break; + } + if (count == scount) { + /* + * This rdata isn't in the sslab, and thus isn't + * being subtracted. + */ + tlength += (unsigned int)(mcurrent - mrdatabegin); + tcount++; + } else + rcount++; + dns_rdata_reset(&mrdata); + } + +#if DNS_RDATASET_FIXED + tlength += (4 * tcount); +#endif + + /* + * Check that all the records originally existed. The numeric + * check only works as rdataslabs do not contain duplicates. + */ + if (((flags & DNS_RDATASLAB_EXACT) != 0) && (rcount != scount)) + return (DNS_R_NOTEXACT); + + /* + * Don't continue if the new rdataslab would be empty. + */ + if (tcount == 0) + return (DNS_R_NXRRSET); + + /* + * If nothing is going to change, we can stop. + */ + if (rcount == 0) + return (DNS_R_UNCHANGED); + + /* + * Copy the reserved area from the mslab. + */ + tstart = isc_mem_get(mctx, tlength); + if (tstart == NULL) + return (ISC_R_NOMEMORY); + memmove(tstart, mslab, reservelen); + tcurrent = tstart + reservelen; +#if DNS_RDATASET_FIXED + offsetbase = tcurrent; + + offsettable = isc_mem_get(mctx, mcount * sizeof(unsigned int)); + if (offsettable == NULL) { + isc_mem_put(mctx, tstart, tlength); + return (ISC_R_NOMEMORY); + } + memset(offsettable, 0, mcount * sizeof(unsigned int)); +#endif + + /* + * Write the new count. + */ + *tcurrent++ = (tcount & 0xff00) >> 8; + *tcurrent++ = (tcount & 0x00ff); + +#if DNS_RDATASET_FIXED + tcurrent += (4 * tcount); +#endif + + /* + * Copy the parts of mslab not in sslab. + */ + mcurrent = mslab + reservelen; + mcount = *mcurrent++ * 256; + mcount += *mcurrent++; +#if DNS_RDATASET_FIXED + mcurrent += (4 * mcount); +#endif + for (i = 0; i < mcount; i++) { + unsigned char *mrdatabegin = mcurrent; +#if DNS_RDATASET_FIXED + order = mcurrent[2] * 256 + mcurrent[3]; + INSIST(order < mcount); +#endif + rdata_from_slab(&mcurrent, rdclass, type, &mrdata); + scurrent = sstart; + for (count = 0; count < scount; count++) { + dns_rdata_reset(&srdata); + rdata_from_slab(&scurrent, rdclass, type, &srdata); + if (dns_rdata_compare(&mrdata, &srdata) == 0) + break; + } + if (count == scount) { + /* + * This rdata isn't in the sslab, and thus should be + * copied to the tslab. + */ + unsigned int length; + length = (unsigned int)(mcurrent - mrdatabegin); +#if DNS_RDATASET_FIXED + offsettable[order] = tcurrent - offsetbase; +#endif + memmove(tcurrent, mrdatabegin, length); + tcurrent += length; + } + dns_rdata_reset(&mrdata); + } + +#if DNS_RDATASET_FIXED + fillin_offsets(offsetbase, offsettable, mcount); + + isc_mem_put(mctx, offsettable, mcount * sizeof(unsigned int)); +#endif + + INSIST(tcurrent == tstart + tlength); + + *tslabp = tstart; + + return (ISC_R_SUCCESS); +} + +bool +dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2, + unsigned int reservelen) +{ + unsigned char *current1, *current2; + unsigned int count1, count2; + unsigned int length1, length2; + + current1 = slab1 + reservelen; + count1 = *current1++ * 256; + count1 += *current1++; + + current2 = slab2 + reservelen; + count2 = *current2++ * 256; + count2 += *current2++; + + if (count1 != count2) + return (false); + +#if DNS_RDATASET_FIXED + current1 += (4 * count1); + current2 += (4 * count2); +#endif + + while (count1 > 0) { + length1 = *current1++ * 256; + length1 += *current1++; + + length2 = *current2++ * 256; + length2 += *current2++; + +#if DNS_RDATASET_FIXED + current1 += 2; + current2 += 2; +#endif + + if (length1 != length2 || + memcmp(current1, current2, length1) != 0) + return (false); + + current1 += length1; + current2 += length1; + + count1--; + } + return (true); +} + +bool +dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2, + unsigned int reservelen, dns_rdataclass_t rdclass, + dns_rdatatype_t type) +{ + unsigned char *current1, *current2; + unsigned int count1, count2; + dns_rdata_t rdata1 = DNS_RDATA_INIT; + dns_rdata_t rdata2 = DNS_RDATA_INIT; + + current1 = slab1 + reservelen; + count1 = *current1++ * 256; + count1 += *current1++; + + current2 = slab2 + reservelen; + count2 = *current2++ * 256; + count2 += *current2++; + + if (count1 != count2) + return (false); + +#if DNS_RDATASET_FIXED + current1 += (4 * count1); + current2 += (4 * count2); +#endif + + while (count1-- > 0) { + rdata_from_slab(¤t1, rdclass, type, &rdata1); + rdata_from_slab(¤t2, rdclass, type, &rdata2); + if (dns_rdata_compare(&rdata1, &rdata2) != 0) + return (false); + dns_rdata_reset(&rdata1); + dns_rdata_reset(&rdata2); + } + return (true); +} |