diff options
Diffstat (limited to 'lib/dns/rdata/in_1')
32 files changed, 6460 insertions, 0 deletions
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..65c0a69 --- /dev/null +++ b/lib/dns/rdata/in_1/a6_38.c @@ -0,0 +1,486 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 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, tctx->flags, &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 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); + if ((sr.base[0] & ~mask) != 0) { + return (DNS_R_FORMERR); + } + 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 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 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 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(a6 != 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 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(a6 != 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 void +freestruct_in_a6(ARGS_FREESTRUCT) { + dns_rdata_in_a6_t *a6 = source; + + REQUIRE(a6 != 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 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 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 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 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 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..bd83092 --- /dev/null +++ b/lib/dns/rdata/in_1/a6_38.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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..b474aa7 --- /dev/null +++ b/lib/dns/rdata/in_1/a_1.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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); + UNUSED(callbacks); + + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 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 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, tctx->flags, ®ion, target)); +} + +static 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 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 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 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(a != 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 isc_result_t +tostruct_in_a(ARGS_TOSTRUCT) { + dns_rdata_in_a_t *a = target; + uint32_t n; + isc_region_t region; + + REQUIRE(a != NULL); + 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 void +freestruct_in_a(ARGS_FREESTRUCT) { + dns_rdata_in_a_t *a = source; + + REQUIRE(a != NULL); + REQUIRE(a->common.rdtype == dns_rdatatype_a); + REQUIRE(a->common.rdclass == dns_rdataclass_in); + + UNUSED(a); +} + +static 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 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 bool +checkowner_in_a(ARGS_CHECKOWNER) { + dns_name_t prefix, suffix; + unsigned int labels, i; + + REQUIRE(type == dns_rdatatype_a); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(rdclass); + + labels = dns_name_countlabels(name); + if (labels > 2U) { + /* + * Handle Active Directory gc._msdcs.<forest> name. + */ + dns_name_init(&prefix, NULL); + dns_name_init(&suffix, NULL); + dns_name_split(name, labels - 2, &prefix, &suffix); + if (dns_name_equal(&gc_msdcs, &prefix) && + dns_name_ishostname(&suffix, false)) + { + return (true); + } + + /* + * Handle SPF exists targets when the seperating label is: + * - "_spf" RFC7208, section 5.7 + * - "_spf_verify" RFC7208, Appendix D1 + * - "_spf_rate" RFC7208, Appendix D1 + */ + for (i = 0; i < labels - 2; i++) { + dns_label_t label; + dns_name_getlabel(name, i, &label); + if ((label.length == 5 && + strncasecmp((char *)label.base, "\x04_spf", 5) == + 0) || + (label.length == 12 && + strncasecmp((char *)label.base, "\x0b_spf_verify", + 12) == 0) || + (label.length == 10 && + strncasecmp((char *)label.base, "\x09_spf_rate", + 10) == 0)) + { + return (true); + } + } + } + + return (dns_name_ishostname(name, wildcard)); +} + +static 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 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..aefc4f3 --- /dev/null +++ b/lib/dns/rdata/in_1/a_1.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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..d60175a --- /dev/null +++ b/lib/dns/rdata/in_1/aaaa_28.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 isc_result_t +totext_in_aaaa(ARGS_TOTEXT) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_aaaa); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length == 16); + + if ((tctx->flags & DNS_STYLEFLAG_EXPANDAAAA) != 0) { + char buf[5 * 8]; + const char *sep = ""; + int i, n; + unsigned int len = 0; + + for (i = 0; i < 16; i += 2) { + INSIST(len < sizeof(buf)); + n = snprintf(buf + len, sizeof(buf) - len, "%s%02x%02x", + sep, rdata->data[i], rdata->data[i + 1]); + if (n < 0) { + return (ISC_R_FAILURE); + } + len += n; + sep = ":"; + } + return (str_totext(buf, target)); + } + dns_rdata_toregion(rdata, ®ion); + return (inet_totext(AF_INET6, tctx->flags, ®ion, target)); +} + +static 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 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 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 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(aaaa != 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 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(aaaa != 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 void +freestruct_in_aaaa(ARGS_FREESTRUCT) { + dns_rdata_in_aaaa_t *aaaa = source; + + REQUIRE(aaaa != NULL); + REQUIRE(aaaa->common.rdclass == dns_rdataclass_in); + REQUIRE(aaaa->common.rdtype == dns_rdatatype_aaaa); + + UNUSED(aaaa); +} + +static 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 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 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 Directory 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 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 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..b7310b2 --- /dev/null +++ b/lib/dns/rdata/in_1/aaaa_28.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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..96372e0 --- /dev/null +++ b/lib/dns/rdata/in_1/apl_42.c @@ -0,0 +1,481 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 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, tctx->flags, &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, tctx->flags, &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 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 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 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 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(apl != 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 isc_result_t +tostruct_in_apl(ARGS_TOSTRUCT) { + dns_rdata_in_apl_t *apl = target; + isc_region_t r; + + REQUIRE(apl != NULL); + 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 void +freestruct_in_apl(ARGS_FREESTRUCT) { + dns_rdata_in_apl_t *apl = source; + + REQUIRE(apl != 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 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 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 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 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 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..603fd3e --- /dev/null +++ b/lib/dns/rdata/in_1/apl_42.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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/atma_34.c b/lib/dns/rdata/in_1/atma_34.c new file mode 100644 index 0000000..c00defd --- /dev/null +++ b/lib/dns/rdata/in_1/atma_34.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf */ + +#ifndef RDATA_IN_1_ATMA_22_C +#define RDATA_IN_1_ATMA_22_C + +#define RRTYPE_ATMA_ATTRIBUTES (0) + +static isc_result_t +fromtext_in_atma(ARGS_FROMTEXT) { + isc_token_t token; + isc_textregion_t *sr; + int n; + bool valid = false; + bool lastwasperiod = true; /* leading periods not allowed */ + int digits = 0; + unsigned char c = 0; + + REQUIRE(type == dns_rdatatype_atma); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + UNUSED(callbacks); + + /* ATM End System Address (AESA) format or E.164 */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + sr = &token.value.as_textregion; + if (sr->length < 1) { + RETTOK(ISC_R_UNEXPECTEDEND); + } + + if (sr->base[0] != '+') { + /* + * Format 0: ATM End System Address (AESA) format. + */ + c = 0; + RETERR(mem_tobuffer(target, &c, 1)); + while (sr->length > 0) { + if (sr->base[0] == '.') { + if (lastwasperiod) { + RETTOK(DNS_R_SYNTAX); + } + isc_textregion_consume(sr, 1); + lastwasperiod = true; + 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); + lastwasperiod = false; + } + if (digits != 0 || !valid || lastwasperiod) { + RETTOK(ISC_R_UNEXPECTEDEND); + } + } else { + /* + * Format 1: E.164. + */ + c = 1; + RETERR(mem_tobuffer(target, &c, 1)); + isc_textregion_consume(sr, 1); + while (sr->length > 0) { + if (sr->base[0] == '.') { + if (lastwasperiod) { + RETTOK(DNS_R_SYNTAX); + } + isc_textregion_consume(sr, 1); + lastwasperiod = true; + continue; + } + if (!isdigit((unsigned char)sr->base[0])) { + RETTOK(DNS_R_SYNTAX); + } + RETERR(mem_tobuffer(target, sr->base, 1)); + isc_textregion_consume(sr, 1); + lastwasperiod = false; + } + if (lastwasperiod) { + RETTOK(ISC_R_UNEXPECTEDEND); + } + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +totext_in_atma(ARGS_TOTEXT) { + isc_region_t region; + char buf[sizeof("xx")]; + + REQUIRE(rdata->type == dns_rdatatype_atma); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, ®ion); + INSIST(region.length > 1); + switch (region.base[0]) { + case 0: + isc_region_consume(®ion, 1); + while (region.length != 0) { + snprintf(buf, sizeof(buf), "%02x", region.base[0]); + isc_region_consume(®ion, 1); + RETERR(str_totext(buf, target)); + } + break; + case 1: + RETERR(str_totext("+", target)); + isc_region_consume(®ion, 1); + RETERR(mem_tobuffer(target, region.base, region.length)); + break; + default: + return (ISC_R_NOTIMPLEMENTED); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +fromwire_in_atma(ARGS_FROMWIRE) { + isc_region_t region; + + REQUIRE(type == dns_rdatatype_atma); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(dctx); + UNUSED(options); + UNUSED(rdclass); + + isc_buffer_activeregion(source, ®ion); + if (region.length < 2) { + return (ISC_R_UNEXPECTEDEND); + } + if (region.base[0] == 1) { + unsigned int i; + for (i = 1; i < region.length; i++) { + if (!isdigit((unsigned char)region.base[i])) { + return (DNS_R_FORMERR); + } + } + } + RETERR(mem_tobuffer(target, region.base, region.length)); + isc_buffer_forward(source, region.length); + return (ISC_R_SUCCESS); +} + +static isc_result_t +towire_in_atma(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_atma); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static int +compare_in_atma(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_atma); + 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 isc_result_t +fromstruct_in_atma(ARGS_FROMSTRUCT) { + dns_rdata_in_atma_t *atma = source; + + REQUIRE(type == dns_rdatatype_atma); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(atma != NULL); + REQUIRE(atma->common.rdtype == type); + REQUIRE(atma->common.rdclass == rdclass); + REQUIRE(atma->atma != NULL || atma->atma_len == 0); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(mem_tobuffer(target, &atma->format, 1)); + return (mem_tobuffer(target, atma->atma, atma->atma_len)); +} + +static isc_result_t +tostruct_in_atma(ARGS_TOSTRUCT) { + dns_rdata_in_atma_t *atma = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_atma); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(atma != NULL); + REQUIRE(rdata->length != 0); + + atma->common.rdclass = rdata->rdclass; + atma->common.rdtype = rdata->type; + ISC_LINK_INIT(&atma->common, link); + + dns_rdata_toregion(rdata, &r); + atma->format = r.base[0]; + isc_region_consume(&r, 1); + atma->atma_len = r.length; + atma->atma = mem_maybedup(mctx, r.base, r.length); + if (atma->atma == NULL) { + return (ISC_R_NOMEMORY); + } + + atma->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static void +freestruct_in_atma(ARGS_FREESTRUCT) { + dns_rdata_in_atma_t *atma = source; + + REQUIRE(atma != NULL); + REQUIRE(atma->common.rdclass == dns_rdataclass_in); + REQUIRE(atma->common.rdtype == dns_rdatatype_atma); + + if (atma->mctx == NULL) { + return; + } + + if (atma->atma != NULL) { + isc_mem_free(atma->mctx, atma->atma); + } + atma->mctx = NULL; +} + +static isc_result_t +additionaldata_in_atma(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_atma); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +digest_in_atma(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_atma); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static bool +checkowner_in_atma(ARGS_CHECKOWNER) { + REQUIRE(type == dns_rdatatype_atma); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static bool +checknames_in_atma(ARGS_CHECKNAMES) { + REQUIRE(rdata->type == dns_rdatatype_atma); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static int +casecompare_in_atma(ARGS_COMPARE) { + return (compare_in_atma(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_atma_22_C */ diff --git a/lib/dns/rdata/in_1/atma_34.h b/lib/dns/rdata/in_1/atma_34.h new file mode 100644 index 0000000..abb5457 --- /dev/null +++ b/lib/dns/rdata/in_1/atma_34.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_ATMA_22_H +#define IN_1_ATMA_22_H 1 + +/*! + * \brief Per RFC1706 */ + +typedef struct dns_rdata_in_atma { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char format; + unsigned char *atma; + uint16_t atma_len; +} dns_rdata_in_atma_t; + +#endif /* IN_1_ATMA_22_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..7d36d50 --- /dev/null +++ b/lib/dns/rdata/in_1/dhcid_49.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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, -2)); +} + +static isc_result_t +totext_in_dhcid(ARGS_TOTEXT) { + isc_region_t sr, sr2; + /* " ; 64000 255 64000" */ + char buf[5 + 3 * 11 + 1]; + + 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) { + snprintf(buf, sizeof(buf), " ; %u %u %u", + sr2.base[0] * 256U + sr2.base[1], sr2.base[2], + rdata->length - 3U); + RETERR(str_totext(buf, target)); + } + } + return (ISC_R_SUCCESS); +} + +static 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 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 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 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(dhcid != 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 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(dhcid != 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 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 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 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 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 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 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..071ea41 --- /dev/null +++ b/lib/dns/rdata/in_1/dhcid_49.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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/eid_31.c b/lib/dns/rdata/in_1/eid_31.c new file mode 100644 index 0000000..104837c --- /dev/null +++ b/lib/dns/rdata/in_1/eid_31.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt */ + +#ifndef RDATA_IN_1_EID_31_C +#define RDATA_IN_1_EID_31_C + +#define RRTYPE_EID_ATTRIBUTES (0) + +static isc_result_t +fromtext_in_eid(ARGS_FROMTEXT) { + REQUIRE(type == dns_rdatatype_eid); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + UNUSED(callbacks); + + return (isc_hex_tobuffer(lexer, target, -2)); +} + +static isc_result_t +totext_in_eid(ARGS_TOTEXT) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_eid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext("( ", target)); + } + if (tctx->width == 0) { + RETERR(isc_hex_totext(®ion, 60, "", target)); + } else { + RETERR(isc_hex_totext(®ion, tctx->width - 2, tctx->linebreak, + target)); + } + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext(" )", target)); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +fromwire_in_eid(ARGS_FROMWIRE) { + isc_region_t region; + + REQUIRE(type == dns_rdatatype_eid); + 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 isc_result_t +towire_in_eid(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_eid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static int +compare_in_eid(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_eid); + 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 isc_result_t +fromstruct_in_eid(ARGS_FROMSTRUCT) { + dns_rdata_in_eid_t *eid = source; + + REQUIRE(type == dns_rdatatype_eid); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(eid != NULL); + REQUIRE(eid->common.rdtype == type); + REQUIRE(eid->common.rdclass == rdclass); + REQUIRE(eid->eid != NULL || eid->eid_len == 0); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, eid->eid, eid->eid_len)); +} + +static isc_result_t +tostruct_in_eid(ARGS_TOSTRUCT) { + dns_rdata_in_eid_t *eid = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_eid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(eid != NULL); + REQUIRE(rdata->length != 0); + + eid->common.rdclass = rdata->rdclass; + eid->common.rdtype = rdata->type; + ISC_LINK_INIT(&eid->common, link); + + dns_rdata_toregion(rdata, &r); + eid->eid_len = r.length; + eid->eid = mem_maybedup(mctx, r.base, r.length); + if (eid->eid == NULL) { + return (ISC_R_NOMEMORY); + } + + eid->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static void +freestruct_in_eid(ARGS_FREESTRUCT) { + dns_rdata_in_eid_t *eid = source; + + REQUIRE(eid != NULL); + REQUIRE(eid->common.rdclass == dns_rdataclass_in); + REQUIRE(eid->common.rdtype == dns_rdatatype_eid); + + if (eid->mctx == NULL) { + return; + } + + if (eid->eid != NULL) { + isc_mem_free(eid->mctx, eid->eid); + } + eid->mctx = NULL; +} + +static isc_result_t +additionaldata_in_eid(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_eid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +digest_in_eid(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_eid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static bool +checkowner_in_eid(ARGS_CHECKOWNER) { + REQUIRE(type == dns_rdatatype_eid); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static bool +checknames_in_eid(ARGS_CHECKNAMES) { + REQUIRE(rdata->type == dns_rdatatype_eid); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static int +casecompare_in_eid(ARGS_COMPARE) { + return (compare_in_eid(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_EID_31_C */ diff --git a/lib/dns/rdata/in_1/eid_31.h b/lib/dns/rdata/in_1/eid_31.h new file mode 100644 index 0000000..879bcf5 --- /dev/null +++ b/lib/dns/rdata/in_1/eid_31.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_EID_31_H +#define IN_1_EID_31_H 1 + +/*! + * \brief http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt + */ + +typedef struct dns_rdata_in_eid { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *eid; + uint16_t eid_len; +} dns_rdata_in_eid_t; + +#endif /* IN_1_EID_31_H */ diff --git a/lib/dns/rdata/in_1/https_65.c b/lib/dns/rdata/in_1/https_65.c new file mode 100644 index 0000000..0581645 --- /dev/null +++ b/lib/dns/rdata/in_1/https_65.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* draft-ietf-dnsop-svcb-https-02 */ + +#ifndef RDATA_IN_1_HTTPS_65_C +#define RDATA_IN_1_HTTPS_65_C + +#define RRTYPE_HTTPS_ATTRIBUTES 0 + +/* + * Most of these functions refer to equivalent functions for SVCB, + * since wire and presentation formats are identical. + */ + +static isc_result_t +fromtext_in_https(ARGS_FROMTEXT) { + REQUIRE(type == dns_rdatatype_https); + REQUIRE(rdclass == dns_rdataclass_in); + + return (generic_fromtext_in_svcb(CALL_FROMTEXT)); +} + +static isc_result_t +totext_in_https(ARGS_TOTEXT) { + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + return (generic_totext_in_svcb(CALL_TOTEXT)); +} + +static isc_result_t +fromwire_in_https(ARGS_FROMWIRE) { + REQUIRE(type == dns_rdatatype_https); + REQUIRE(rdclass == dns_rdataclass_in); + + return (generic_fromwire_in_svcb(CALL_FROMWIRE)); +} + +static isc_result_t +towire_in_https(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->length != 0); + + return (generic_towire_in_svcb(CALL_TOWIRE)); +} + +static int +compare_in_https(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_https); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + 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 isc_result_t +fromstruct_in_https(ARGS_FROMSTRUCT) { + dns_rdata_in_https_t *https = source; + + REQUIRE(type == dns_rdatatype_https); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(https != NULL); + REQUIRE(https->common.rdtype == type); + REQUIRE(https->common.rdclass == rdclass); + + return (generic_fromstruct_in_svcb(CALL_FROMSTRUCT)); +} + +static isc_result_t +tostruct_in_https(ARGS_TOSTRUCT) { + dns_rdata_in_https_t *https = target; + + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(https != NULL); + REQUIRE(rdata->length != 0); + + return (generic_tostruct_in_svcb(CALL_TOSTRUCT)); +} + +static void +freestruct_in_https(ARGS_FREESTRUCT) { + dns_rdata_in_https_t *https = source; + + REQUIRE(https != NULL); + REQUIRE(https->common.rdclass == dns_rdataclass_in); + REQUIRE(https->common.rdtype == dns_rdatatype_https); + + generic_freestruct_in_svcb(CALL_FREESTRUCT); +} + +static isc_result_t +additionaldata_in_https(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + return (generic_additionaldata_in_svcb(CALL_ADDLDATA)); +} + +static isc_result_t +digest_in_https(ARGS_DIGEST) { + isc_region_t region1; + + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, ®ion1); + return ((digest)(arg, ®ion1)); +} + +static bool +checkowner_in_https(ARGS_CHECKOWNER) { + REQUIRE(type == dns_rdatatype_https); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static bool +checknames_in_https(ARGS_CHECKNAMES) { + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + return (generic_checknames_in_svcb(CALL_CHECKNAMES)); +} + +static int +casecompare_in_https(ARGS_COMPARE) { + return (compare_in_https(rdata1, rdata2)); +} + +isc_result_t +dns_rdata_in_https_first(dns_rdata_in_https_t *https) { + REQUIRE(https != NULL); + REQUIRE(https->common.rdtype == dns_rdatatype_https); + REQUIRE(https->common.rdclass == dns_rdataclass_in); + + return (generic_rdata_in_svcb_first(https)); +} + +isc_result_t +dns_rdata_in_https_next(dns_rdata_in_https_t *https) { + REQUIRE(https != NULL); + REQUIRE(https->common.rdtype == dns_rdatatype_https); + REQUIRE(https->common.rdclass == dns_rdataclass_in); + + return (generic_rdata_in_svcb_next(https)); +} + +void +dns_rdata_in_https_current(dns_rdata_in_https_t *https, isc_region_t *region) { + REQUIRE(https != NULL); + REQUIRE(https->common.rdtype == dns_rdatatype_https); + REQUIRE(https->common.rdclass == dns_rdataclass_in); + REQUIRE(region != NULL); + + generic_rdata_in_svcb_current(https, region); +} + +#endif /* RDATA_IN_1_HTTPS_65_C */ diff --git a/lib/dns/rdata/in_1/https_65.h b/lib/dns/rdata/in_1/https_65.h new file mode 100644 index 0000000..a5967a3 --- /dev/null +++ b/lib/dns/rdata/in_1/https_65.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_HTTPS_65_H +#define IN_1_HTTPS_65_H 1 + +/*! + * \brief Per draft-ietf-dnsop-svcb-https-02 + */ + +/* + * Wire and presentation formats for HTTPS are identical to SVCB. + */ +typedef struct dns_rdata_in_svcb dns_rdata_in_https_t; + +isc_result_t +dns_rdata_in_https_first(dns_rdata_in_https_t *); + +isc_result_t +dns_rdata_in_https_next(dns_rdata_in_https_t *); + +void +dns_rdata_in_https_current(dns_rdata_in_https_t *, isc_region_t *); + +#endif /* IN_1_HTTPS_65_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..508def3 --- /dev/null +++ b/lib/dns/rdata/in_1/kx_36.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 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 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 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 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 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(kx != 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 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(kx != 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 void +freestruct_in_kx(ARGS_FREESTRUCT) { + dns_rdata_in_kx_t *kx = source; + + REQUIRE(kx != 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 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 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 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 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 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..b71aadc --- /dev/null +++ b/lib/dns/rdata/in_1/kx_36.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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/nimloc_32.c b/lib/dns/rdata/in_1/nimloc_32.c new file mode 100644 index 0000000..6f1e3d6 --- /dev/null +++ b/lib/dns/rdata/in_1/nimloc_32.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt */ + +#ifndef RDATA_IN_1_NIMLOC_32_C +#define RDATA_IN_1_NIMLOC_32_C + +#define RRTYPE_NIMLOC_ATTRIBUTES (0) + +static isc_result_t +fromtext_in_nimloc(ARGS_FROMTEXT) { + REQUIRE(type == dns_rdatatype_nimloc); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(type); + UNUSED(origin); + UNUSED(options); + UNUSED(rdclass); + UNUSED(callbacks); + + return (isc_hex_tobuffer(lexer, target, -2)); +} + +static isc_result_t +totext_in_nimloc(ARGS_TOTEXT) { + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_nimloc); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext("( ", target)); + } + if (tctx->width == 0) { + RETERR(isc_hex_totext(®ion, 60, "", target)); + } else { + RETERR(isc_hex_totext(®ion, tctx->width - 2, tctx->linebreak, + target)); + } + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext(" )", target)); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +fromwire_in_nimloc(ARGS_FROMWIRE) { + isc_region_t region; + + REQUIRE(type == dns_rdatatype_nimloc); + 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 isc_result_t +towire_in_nimloc(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_nimloc); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + return (mem_tobuffer(target, rdata->data, rdata->length)); +} + +static int +compare_in_nimloc(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_nimloc); + 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 isc_result_t +fromstruct_in_nimloc(ARGS_FROMSTRUCT) { + dns_rdata_in_nimloc_t *nimloc = source; + + REQUIRE(type == dns_rdatatype_nimloc); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(nimloc != NULL); + REQUIRE(nimloc->common.rdtype == type); + REQUIRE(nimloc->common.rdclass == rdclass); + REQUIRE(nimloc->nimloc != NULL || nimloc->nimloc_len == 0); + + UNUSED(type); + UNUSED(rdclass); + + return (mem_tobuffer(target, nimloc->nimloc, nimloc->nimloc_len)); +} + +static isc_result_t +tostruct_in_nimloc(ARGS_TOSTRUCT) { + dns_rdata_in_nimloc_t *nimloc = target; + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nimloc); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(nimloc != NULL); + REQUIRE(rdata->length != 0); + + nimloc->common.rdclass = rdata->rdclass; + nimloc->common.rdtype = rdata->type; + ISC_LINK_INIT(&nimloc->common, link); + + dns_rdata_toregion(rdata, &r); + nimloc->nimloc_len = r.length; + nimloc->nimloc = mem_maybedup(mctx, r.base, r.length); + if (nimloc->nimloc == NULL) { + return (ISC_R_NOMEMORY); + } + + nimloc->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static void +freestruct_in_nimloc(ARGS_FREESTRUCT) { + dns_rdata_in_nimloc_t *nimloc = source; + + REQUIRE(nimloc != NULL); + REQUIRE(nimloc->common.rdclass == dns_rdataclass_in); + REQUIRE(nimloc->common.rdtype == dns_rdatatype_nimloc); + + if (nimloc->mctx == NULL) { + return; + } + + if (nimloc->nimloc != NULL) { + isc_mem_free(nimloc->mctx, nimloc->nimloc); + } + nimloc->mctx = NULL; +} + +static isc_result_t +additionaldata_in_nimloc(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_nimloc); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +digest_in_nimloc(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == dns_rdatatype_nimloc); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static bool +checkowner_in_nimloc(ARGS_CHECKOWNER) { + REQUIRE(type == dns_rdatatype_nimloc); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static bool +checknames_in_nimloc(ARGS_CHECKNAMES) { + REQUIRE(rdata->type == dns_rdatatype_nimloc); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (true); +} + +static int +casecompare_in_nimloc(ARGS_COMPARE) { + return (compare_in_nimloc(rdata1, rdata2)); +} + +#endif /* RDATA_IN_1_NIMLOC_32_C */ diff --git a/lib/dns/rdata/in_1/nimloc_32.h b/lib/dns/rdata/in_1/nimloc_32.h new file mode 100644 index 0000000..02ca047 --- /dev/null +++ b/lib/dns/rdata/in_1/nimloc_32.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_NIMLOC_32_H +#define IN_1_NIMLOC_32_H 1 + +/*! + * \brief http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt + */ + +typedef struct dns_rdata_in_nimloc { + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *nimloc; + uint16_t nimloc_len; +} dns_rdata_in_nimloc_t; + +#endif /* IN_1_NIMLOC_32_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..326e878 --- /dev/null +++ b/lib/dns/rdata/in_1/nsap-ptr_23.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 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 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 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 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 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(nsap_ptr != 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 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(nsap_ptr != 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 void +freestruct_in_nsap_ptr(ARGS_FREESTRUCT) { + dns_rdata_in_nsap_ptr_t *nsap_ptr = source; + + REQUIRE(nsap_ptr != 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 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 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 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 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 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..ef1ee60 --- /dev/null +++ b/lib/dns/rdata/in_1/nsap-ptr_23.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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..5ccb793 --- /dev/null +++ b/lib/dns/rdata/in_1/nsap_22.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 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 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 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 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 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(nsap != 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 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(nsap != 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 void +freestruct_in_nsap(ARGS_FREESTRUCT) { + dns_rdata_in_nsap_t *nsap = source; + + REQUIRE(nsap != 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 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 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 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 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 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..f65c913 --- /dev/null +++ b/lib/dns/rdata/in_1/nsap_22.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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..9f6a21a --- /dev/null +++ b/lib/dns/rdata/in_1/px_26.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 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 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 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 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 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 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(px != 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 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(px != 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 void +freestruct_in_px(ARGS_FREESTRUCT) { + dns_rdata_in_px_t *px = source; + + REQUIRE(px != 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 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 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 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 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 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..1fcbd36 --- /dev/null +++ b/lib/dns/rdata/in_1/px_26.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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..6e24867 --- /dev/null +++ b/lib/dns/rdata/in_1/srv_33.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 (DNS_RDATATYPEATTR_FOLLOWADDITIONAL) + +static 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 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 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 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 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 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(srv != 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 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(srv != 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 void +freestruct_in_srv(ARGS_FREESTRUCT) { + dns_rdata_in_srv_t *srv = source; + + REQUIRE(srv != 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 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 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 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 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 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..554180a --- /dev/null +++ b/lib/dns/rdata/in_1/srv_33.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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/svcb_64.c b/lib/dns/rdata/in_1/svcb_64.c new file mode 100644 index 0000000..a87473f --- /dev/null +++ b/lib/dns/rdata/in_1/svcb_64.c @@ -0,0 +1,1268 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* draft-ietf-dnsop-svcb-https-02 */ + +#ifndef RDATA_IN_1_SVCB_64_C +#define RDATA_IN_1_SVCB_64_C + +#define RRTYPE_SVCB_ATTRIBUTES 0 + +#define SVCB_MAN_KEY 0 +#define SVCB_ALPN_KEY 1 +#define SVCB_NO_DEFAULT_ALPN_KEY 2 + +/* + * Service Binding Parameter Registry + */ +enum encoding { + sbpr_text, + sbpr_port, + sbpr_ipv4s, + sbpr_ipv6s, + sbpr_base64, + sbpr_empty, + sbpr_alpn, + sbpr_keylist, + sbpr_dohpath +}; +static const struct { + const char *name; /* Restricted to lowercase LDH by registry. */ + unsigned int value; + enum encoding encoding; + bool initial; /* Part of the first defined set of encodings. */ +} sbpr[] = { + { "mandatory", 0, sbpr_keylist, true }, + { "alpn", 1, sbpr_alpn, true }, + { "no-default-alpn", 2, sbpr_empty, true }, + { "port", 3, sbpr_port, true }, + { "ipv4hint", 4, sbpr_ipv4s, true }, + { "ech", 5, sbpr_base64, true }, + { "ipv6hint", 6, sbpr_ipv6s, true }, + { "dohpath", 7, sbpr_dohpath, false }, +}; + +static isc_result_t +alpn_fromtxt(isc_textregion_t *source, isc_buffer_t *target) { + isc_textregion_t source0 = *source; + do { + RETERR(commatxt_fromtext(&source0, true, target)); + } while (source0.length != 0); + return (ISC_R_SUCCESS); +} + +static int +svckeycmp(const void *a1, const void *a2) { + const unsigned char *u1 = a1, *u2 = a2; + if (*u1 != *u2) { + return (*u1 - *u2); + } + return (*(++u1) - *(++u2)); +} + +static isc_result_t +svcsortkeylist(isc_buffer_t *target, unsigned int used) { + isc_region_t region; + + isc_buffer_usedregion(target, ®ion); + isc_region_consume(®ion, used); + INSIST(region.length > 0U); + qsort(region.base, region.length / 2, 2, svckeycmp); + /* Reject duplicates. */ + while (region.length >= 4) { + if (region.base[0] == region.base[2] && + region.base[1] == region.base[3]) + { + return (DNS_R_SYNTAX); + } + isc_region_consume(®ion, 2); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +svcb_validate(uint16_t key, isc_region_t *region) { + size_t i; + +#ifndef ARRAYSIZE +/* defined in winnt.h */ +#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x)) +#endif + + for (i = 0; i < ARRAYSIZE(sbpr); i++) { + if (sbpr[i].value == key) { + switch (sbpr[i].encoding) { + case sbpr_port: + if (region->length != 2) { + return (DNS_R_FORMERR); + } + break; + case sbpr_ipv4s: + if ((region->length % 4) != 0 || + region->length == 0) + { + return (DNS_R_FORMERR); + } + break; + case sbpr_ipv6s: + if ((region->length % 16) != 0 || + region->length == 0) + { + return (DNS_R_FORMERR); + } + break; + case sbpr_alpn: { + if (region->length == 0) { + return (DNS_R_FORMERR); + } + while (region->length != 0) { + size_t l = *region->base + 1; + if (l == 1U || l > region->length) { + return (DNS_R_FORMERR); + } + isc_region_consume(region, l); + } + break; + } + case sbpr_keylist: { + if ((region->length % 2) != 0 || + region->length == 0) + { + return (DNS_R_FORMERR); + } + /* In order? */ + while (region->length >= 4) { + if (region->base[0] > region->base[2] || + (region->base[0] == + region->base[2] && + region->base[1] >= + region->base[3])) + { + return (DNS_R_FORMERR); + } + isc_region_consume(region, 2); + } + break; + } + case sbpr_text: + case sbpr_base64: + break; + case sbpr_dohpath: + /* + * Minimum valid dohpath is "/{?dns}" as + * it MUST be relative (leading "/") and + * MUST contain "{?dns}". + */ + if (region->length < 7) { + return (DNS_R_FORMERR); + } + /* MUST be relative */ + if (region->base[0] != '/') { + return (DNS_R_FORMERR); + } + /* MUST be UTF8 */ + if (!isc_utf8_valid(region->base, + region->length)) + { + return (DNS_R_FORMERR); + } + /* MUST contain "{?dns}" */ + if (strnstr((char *)region->base, "{?dns}", + region->length) == NULL) + { + return (DNS_R_FORMERR); + } + break; + case sbpr_empty: + if (region->length != 0) { + return (DNS_R_FORMERR); + } + break; + } + } + } + return (ISC_R_SUCCESS); +} + +/* + * Parse keyname from region. + */ +static isc_result_t +svc_keyfromregion(isc_textregion_t *region, char sep, uint16_t *value, + isc_buffer_t *target) { + char *e = NULL; + size_t i; + unsigned long ul; + + /* Look for known key names. */ + for (i = 0; i < ARRAYSIZE(sbpr); i++) { + size_t len = strlen(sbpr[i].name); + if (strncasecmp(region->base, sbpr[i].name, len) != 0 || + (region->base[len] != 0 && region->base[len] != sep)) + { + continue; + } + isc_textregion_consume(region, len); + ul = sbpr[i].value; + goto finish; + } + /* Handle keyXXXXX form. */ + if (strncmp(region->base, "key", 3) != 0) { + return (DNS_R_SYNTAX); + } + isc_textregion_consume(region, 3); + /* Disallow [+-]XXXXX which is allowed by strtoul. */ + if (region->length == 0 || *region->base == '-' || *region->base == '+') + { + return (DNS_R_SYNTAX); + } + /* No zero padding. */ + if (region->length > 1 && *region->base == '0' && + region->base[1] != sep) + { + return (DNS_R_SYNTAX); + } + ul = strtoul(region->base, &e, 10); + /* Valid number? */ + if (e == region->base || (*e != sep && *e != 0)) { + return (DNS_R_SYNTAX); + } + if (ul > 0xffff) { + return (ISC_R_RANGE); + } + isc_textregion_consume(region, e - region->base); +finish: + if (sep == ',' && region->length == 1) { + return (DNS_R_SYNTAX); + } + /* Consume separator. */ + if (region->length != 0) { + isc_textregion_consume(region, 1); + } + RETERR(uint16_tobuffer(ul, target)); + if (value != NULL) { + *value = ul; + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +svc_fromtext(isc_textregion_t *region, isc_buffer_t *target) { + char *e = NULL; + char abuf[16]; + char tbuf[sizeof("aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:255.255.255.255,")]; + isc_buffer_t sb; + isc_region_t keyregion; + size_t len; + uint16_t key; + unsigned int i; + unsigned int used; + unsigned long ul; + + for (i = 0; i < ARRAYSIZE(sbpr); i++) { + len = strlen(sbpr[i].name); + if (strncmp(region->base, sbpr[i].name, len) != 0 || + (region->base[len] != 0 && region->base[len] != '=')) + { + continue; + } + + if (region->base[len] == '=') { + len++; + } + + RETERR(uint16_tobuffer(sbpr[i].value, target)); + isc_textregion_consume(region, len); + + sb = *target; + RETERR(uint16_tobuffer(0, target)); /* length */ + + switch (sbpr[i].encoding) { + case sbpr_text: + case sbpr_dohpath: + RETERR(multitxt_fromtext(region, target)); + break; + case sbpr_alpn: + RETERR(alpn_fromtxt(region, target)); + break; + case sbpr_port: + if (!isdigit((unsigned char)*region->base)) { + return (DNS_R_SYNTAX); + } + ul = strtoul(region->base, &e, 10); + if (*e != '\0') { + return (DNS_R_SYNTAX); + } + if (ul > 0xffff) { + return (ISC_R_RANGE); + } + RETERR(uint16_tobuffer(ul, target)); + break; + case sbpr_ipv4s: + do { + snprintf(tbuf, sizeof(tbuf), "%*s", + (int)(region->length), region->base); + e = strchr(tbuf, ','); + if (e != NULL) { + *e++ = 0; + isc_textregion_consume(region, + e - tbuf); + } + if (inet_pton(AF_INET, tbuf, abuf) != 1) { + return (DNS_R_SYNTAX); + } + mem_tobuffer(target, abuf, 4); + } while (e != NULL); + break; + case sbpr_ipv6s: + do { + snprintf(tbuf, sizeof(tbuf), "%*s", + (int)(region->length), region->base); + e = strchr(tbuf, ','); + if (e != NULL) { + *e++ = 0; + isc_textregion_consume(region, + e - tbuf); + } + if (inet_pton(AF_INET6, tbuf, abuf) != 1) { + return (DNS_R_SYNTAX); + } + mem_tobuffer(target, abuf, 16); + } while (e != NULL); + break; + case sbpr_base64: + RETERR(isc_base64_decodestring(region->base, target)); + break; + case sbpr_empty: + if (region->length != 0) { + return (DNS_R_SYNTAX); + } + break; + case sbpr_keylist: + if (region->length == 0) { + return (DNS_R_SYNTAX); + } + used = isc_buffer_usedlength(target); + while (region->length != 0) { + RETERR(svc_keyfromregion(region, ',', NULL, + target)); + } + RETERR(svcsortkeylist(target, used)); + break; + default: + UNREACHABLE(); + } + + len = isc_buffer_usedlength(target) - + isc_buffer_usedlength(&sb) - 2; + RETERR(uint16_tobuffer(len, &sb)); /* length */ + switch (sbpr[i].encoding) { + case sbpr_dohpath: + /* + * Apply constraints not applied by multitxt_fromtext. + */ + keyregion.base = isc_buffer_used(&sb); + keyregion.length = isc_buffer_usedlength(target) - + isc_buffer_usedlength(&sb); + RETERR(svcb_validate(sbpr[i].value, &keyregion)); + break; + default: + break; + } + return (ISC_R_SUCCESS); + } + + RETERR(svc_keyfromregion(region, '=', &key, target)); + if (region->length == 0) { + RETERR(uint16_tobuffer(0, target)); /* length */ + /* Sanity check keyXXXXX form. */ + keyregion.base = isc_buffer_used(target); + keyregion.length = 0; + return (svcb_validate(key, &keyregion)); + } + sb = *target; + RETERR(uint16_tobuffer(0, target)); /* dummy length */ + RETERR(multitxt_fromtext(region, target)); + len = isc_buffer_usedlength(target) - isc_buffer_usedlength(&sb) - 2; + RETERR(uint16_tobuffer(len, &sb)); /* length */ + /* Sanity check keyXXXXX form. */ + keyregion.base = isc_buffer_used(&sb); + keyregion.length = len; + return (svcb_validate(key, &keyregion)); +} + +static const char * +svcparamkey(unsigned short value, enum encoding *encoding, char *buf, + size_t len) { + size_t i; + int n; + + for (i = 0; i < ARRAYSIZE(sbpr); i++) { + if (sbpr[i].value == value && sbpr[i].initial) { + *encoding = sbpr[i].encoding; + return (sbpr[i].name); + } + } + n = snprintf(buf, len, "key%u", value); + INSIST(n > 0 && (unsigned)n < len); + *encoding = sbpr_text; + return (buf); +} + +static isc_result_t +svcsortkeys(isc_buffer_t *target, unsigned int used) { + isc_region_t r1, r2, man = { .base = NULL, .length = 0 }; + unsigned char buf[1024]; + uint16_t mankey = 0; + bool have_alpn = false; + + if (isc_buffer_usedlength(target) == used) { + return (ISC_R_SUCCESS); + } + + /* + * Get the parameters into r1. + */ + isc_buffer_usedregion(target, &r1); + isc_region_consume(&r1, used); + + while (1) { + uint16_t key1, len1, key2, len2; + unsigned char *base1, *base2; + + r2 = r1; + + /* + * Get the first parameter. + */ + base1 = r1.base; + key1 = uint16_fromregion(&r1); + isc_region_consume(&r1, 2); + len1 = uint16_fromregion(&r1); + isc_region_consume(&r1, 2); + isc_region_consume(&r1, len1); + + /* + * Was there only one key left? + */ + if (r1.length == 0) { + if (mankey != 0) { + /* Is this the last mandatory key? */ + if (key1 != mankey || man.length != 0) { + return (DNS_R_INCONSISTENTRR); + } + } else if (key1 == SVCB_MAN_KEY) { + /* Lone mandatory field. */ + return (DNS_R_DISALLOWED); + } else if (key1 == SVCB_NO_DEFAULT_ALPN_KEY && + !have_alpn) + { + /* Missing required ALPN field. */ + return (DNS_R_DISALLOWED); + } + return (ISC_R_SUCCESS); + } + + /* + * Find the smallest parameter. + */ + while (r1.length != 0) { + base2 = r1.base; + key2 = uint16_fromregion(&r1); + isc_region_consume(&r1, 2); + len2 = uint16_fromregion(&r1); + isc_region_consume(&r1, 2); + isc_region_consume(&r1, len2); + if (key2 == key1) { + return (DNS_R_DUPLICATE); + } + if (key2 < key1) { + base1 = base2; + key1 = key2; + len1 = len2; + } + } + + /* + * Do we need to move the smallest parameter to the start? + */ + if (base1 != r2.base) { + size_t offset = 0; + size_t bytes = len1 + 4; + size_t length = base1 - r2.base; + + /* + * Move the smallest parameter to the start. + */ + while (bytes > 0) { + size_t count; + + if (bytes > sizeof(buf)) { + count = sizeof(buf); + } else { + count = bytes; + } + memmove(buf, base1, count); + memmove(r2.base + offset + count, + r2.base + offset, length); + memmove(r2.base + offset, buf, count); + base1 += count; + bytes -= count; + offset += count; + } + } + + /* + * Check ALPN is present when NO-DEFAULT-ALPN is set. + */ + if (key1 == SVCB_ALPN_KEY) { + have_alpn = true; + } else if (key1 == SVCB_NO_DEFAULT_ALPN_KEY && !have_alpn) { + /* Missing required ALPN field. */ + return (DNS_R_DISALLOWED); + } + + /* + * Check key against mandatory key list. + */ + if (mankey != 0) { + if (key1 > mankey) { + return (DNS_R_INCONSISTENTRR); + } + if (key1 == mankey) { + if (man.length >= 2) { + mankey = uint16_fromregion(&man); + isc_region_consume(&man, 2); + } else { + mankey = 0; + } + } + } + + /* + * Is this the mandatory key? + */ + if (key1 == SVCB_MAN_KEY) { + man = r2; + man.length = len1 + 4; + isc_region_consume(&man, 4); + if (man.length >= 2) { + mankey = uint16_fromregion(&man); + isc_region_consume(&man, 2); + if (mankey == SVCB_MAN_KEY) { + return (DNS_R_DISALLOWED); + } + } else { + return (DNS_R_SYNTAX); + } + } + + /* + * Consume the smallest parameter. + */ + isc_region_consume(&r2, len1 + 4); + r1 = r2; + } +} + +static isc_result_t +generic_fromtext_in_svcb(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + bool alias; + bool ok = true; + unsigned int used; + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * SvcPriority. + */ + 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)); + + alias = token.value.as_ulong == 0; + + /* + * TargetName. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + 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 (!alias && (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); + } + + if (alias) { + return (ISC_R_SUCCESS); + } + + /* + * SvcParams + */ + used = isc_buffer_usedlength(target); + while (1) { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qvpair, true)); + if (token.type == isc_tokentype_eol || + token.type == isc_tokentype_eof) + { + isc_lex_ungettoken(lexer, &token); + return (svcsortkeys(target, used)); + } + + if (token.type != isc_tokentype_string && /* key only */ + token.type != isc_tokentype_qvpair && + token.type != isc_tokentype_vpair) + { + RETTOK(DNS_R_SYNTAX); + } + RETTOK(svc_fromtext(&token.value.as_textregion, target)); + } +} + +static isc_result_t +fromtext_in_svcb(ARGS_FROMTEXT) { + REQUIRE(type == dns_rdatatype_svcb); + REQUIRE(rdclass == dns_rdataclass_in); + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + return (generic_fromtext_in_svcb(CALL_FROMTEXT)); +} + +static isc_result_t +generic_totext_in_svcb(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + bool sub; + char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; + unsigned short num; + int n; + + REQUIRE(rdata->length != 0); + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + dns_rdata_toregion(rdata, ®ion); + + /* + * SvcPriority. + */ + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + n = snprintf(buf, sizeof(buf), "%u ", num); + INSIST(n > 0 && (unsigned)n < sizeof(buf)); + RETERR(str_totext(buf, target)); + + /* + * TargetName. + */ + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + while (region.length > 0) { + isc_region_t r; + enum encoding encoding; + + RETERR(str_totext(" ", target)); + + INSIST(region.length >= 2); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + RETERR(str_totext(svcparamkey(num, &encoding, buf, sizeof(buf)), + target)); + + INSIST(region.length >= 2); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + INSIST(region.length >= num); + r = region; + r.length = num; + isc_region_consume(®ion, num); + if (num == 0) { + continue; + } + if (encoding != sbpr_empty) { + RETERR(str_totext("=", target)); + } + switch (encoding) { + case sbpr_text: + RETERR(multitxt_totext(&r, target)); + break; + case sbpr_port: + num = uint16_fromregion(&r); + isc_region_consume(&r, 2); + n = snprintf(buf, sizeof(buf), "%u", num); + INSIST(n > 0 && (unsigned)n < sizeof(buf)); + RETERR(str_totext(buf, target)); + INSIST(r.length == 0U); + break; + case sbpr_ipv4s: + while (r.length > 0U) { + INSIST(r.length >= 4U); + inet_ntop(AF_INET, r.base, buf, sizeof(buf)); + RETERR(str_totext(buf, target)); + isc_region_consume(&r, 4); + if (r.length != 0U) { + RETERR(str_totext(",", target)); + } + } + break; + case sbpr_ipv6s: + while (r.length > 0U) { + INSIST(r.length >= 16U); + inet_ntop(AF_INET6, r.base, buf, sizeof(buf)); + RETERR(str_totext(buf, target)); + isc_region_consume(&r, 16); + if (r.length != 0U) { + RETERR(str_totext(",", target)); + } + } + break; + case sbpr_base64: + RETERR(isc_base64_totext(&r, 0, "", target)); + break; + case sbpr_alpn: + INSIST(r.length != 0U); + RETERR(str_totext("\"", target)); + while (r.length != 0) { + commatxt_totext(&r, false, true, target); + if (r.length != 0) { + RETERR(str_totext(",", target)); + } + } + RETERR(str_totext("\"", target)); + break; + case sbpr_empty: + INSIST(r.length == 0U); + break; + case sbpr_keylist: + while (r.length > 0) { + num = uint16_fromregion(&r); + isc_region_consume(&r, 2); + RETERR(str_totext(svcparamkey(num, &encoding, + buf, sizeof(buf)), + target)); + if (r.length != 0) { + RETERR(str_totext(",", target)); + } + } + break; + default: + UNREACHABLE(); + } + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +totext_in_svcb(ARGS_TOTEXT) { + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + return (generic_totext_in_svcb(CALL_TOTEXT)); +} + +static isc_result_t +generic_fromwire_in_svcb(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t region, man = { .base = NULL, .length = 0 }; + bool alias, first = true, have_alpn = false; + uint16_t lastkey = 0, mankey = 0; + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + /* + * SvcPriority. + */ + isc_buffer_activeregion(source, ®ion); + if (region.length < 2) { + return (ISC_R_UNEXPECTEDEND); + } + RETERR(mem_tobuffer(target, region.base, 2)); + alias = uint16_fromregion(®ion) == 0; + isc_buffer_forward(source, 2); + + /* + * TargetName. + */ + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + + if (alias) { + return (ISC_R_SUCCESS); + } + + /* + * SvcParams. + */ + isc_buffer_activeregion(source, ®ion); + while (region.length > 0U) { + isc_region_t keyregion; + uint16_t key, len; + + /* + * SvcParamKey + */ + if (region.length < 2U) { + return (ISC_R_UNEXPECTEDEND); + } + RETERR(mem_tobuffer(target, region.base, 2)); + key = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + /* + * Keys must be unique and in order. + */ + if (!first && key <= lastkey) { + return (DNS_R_FORMERR); + } + + /* + * Check mandatory keys. + */ + if (mankey != 0) { + /* Missing mandatory key? */ + if (key > mankey) { + return (DNS_R_FORMERR); + } + if (key == mankey) { + /* Get next mandatory key. */ + if (man.length >= 2) { + mankey = uint16_fromregion(&man); + isc_region_consume(&man, 2); + } else { + mankey = 0; + } + } + } + + /* + * Check alpn present when no-default-alpn is set. + */ + if (key == SVCB_ALPN_KEY) { + have_alpn = true; + } else if (key == SVCB_NO_DEFAULT_ALPN_KEY && !have_alpn) { + return (DNS_R_FORMERR); + } + + first = false; + lastkey = key; + + /* + * SvcParamValue length. + */ + if (region.length < 2U) { + return (ISC_R_UNEXPECTEDEND); + } + RETERR(mem_tobuffer(target, region.base, 2)); + len = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + /* + * SvcParamValue. + */ + if (region.length < len) { + return (ISC_R_UNEXPECTEDEND); + } + + /* + * Remember manatory key. + */ + if (key == SVCB_MAN_KEY) { + man = region; + man.length = len; + /* Get first mandatory key */ + if (man.length >= 2) { + mankey = uint16_fromregion(&man); + isc_region_consume(&man, 2); + if (mankey == SVCB_MAN_KEY) { + return (DNS_R_FORMERR); + } + } else { + return (DNS_R_FORMERR); + } + } + keyregion = region; + keyregion.length = len; + RETERR(svcb_validate(key, &keyregion)); + RETERR(mem_tobuffer(target, region.base, len)); + isc_region_consume(®ion, len); + isc_buffer_forward(source, len + 4); + } + + /* + * Do we have an outstanding mandatory key? + */ + if (mankey != 0) { + return (DNS_R_FORMERR); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +fromwire_in_svcb(ARGS_FROMWIRE) { + REQUIRE(type == dns_rdatatype_svcb); + REQUIRE(rdclass == dns_rdataclass_in); + + return (generic_fromwire_in_svcb(CALL_FROMWIRE)); +} + +static isc_result_t +generic_towire_in_svcb(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t region; + + REQUIRE(rdata->length != 0); + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + + /* + * SvcPriority. + */ + dns_rdata_toregion(rdata, ®ion); + RETERR(mem_tobuffer(target, region.base, 2)); + isc_region_consume(®ion, 2); + + /* + * TargetName. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, ®ion); + RETERR(dns_name_towire(&name, cctx, target)); + isc_region_consume(®ion, name_length(&name)); + + /* + * SvcParams. + */ + return (mem_tobuffer(target, region.base, region.length)); +} + +static isc_result_t +towire_in_svcb(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->length != 0); + + return (generic_towire_in_svcb(CALL_TOWIRE)); +} + +static int +compare_in_svcb(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_svcb); + REQUIRE(rdata1->rdclass == dns_rdataclass_in); + 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 isc_result_t +generic_fromstruct_in_svcb(ARGS_FROMSTRUCT) { + dns_rdata_in_svcb_t *svcb = source; + isc_region_t region; + + REQUIRE(svcb != NULL); + REQUIRE(svcb->common.rdtype == type); + REQUIRE(svcb->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(svcb->priority, target)); + dns_name_toregion(&svcb->svcdomain, ®ion); + RETERR(isc_buffer_copyregion(target, ®ion)); + + return (mem_tobuffer(target, svcb->svc, svcb->svclen)); +} + +static isc_result_t +fromstruct_in_svcb(ARGS_FROMSTRUCT) { + dns_rdata_in_svcb_t *svcb = source; + + REQUIRE(type == dns_rdatatype_svcb); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(svcb != NULL); + REQUIRE(svcb->common.rdtype == type); + REQUIRE(svcb->common.rdclass == rdclass); + + return (generic_fromstruct_in_svcb(CALL_FROMSTRUCT)); +} + +static isc_result_t +generic_tostruct_in_svcb(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_in_svcb_t *svcb = target; + dns_name_t name; + + REQUIRE(svcb != NULL); + REQUIRE(rdata->length != 0); + + svcb->common.rdclass = rdata->rdclass; + svcb->common.rdtype = rdata->type; + ISC_LINK_INIT(&svcb->common, link); + + dns_rdata_toregion(rdata, ®ion); + + svcb->priority = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + dns_name_init(&svcb->svcdomain, NULL); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + + RETERR(name_duporclone(&name, mctx, &svcb->svcdomain)); + svcb->svclen = region.length; + svcb->svc = mem_maybedup(mctx, region.base, region.length); + + if (svcb->svc == NULL) { + if (mctx != NULL) { + dns_name_free(&svcb->svcdomain, svcb->mctx); + } + return (ISC_R_NOMEMORY); + } + + svcb->offset = 0; + svcb->mctx = mctx; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +tostruct_in_svcb(ARGS_TOSTRUCT) { + dns_rdata_in_svcb_t *svcb = target; + + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(svcb != NULL); + REQUIRE(rdata->length != 0); + + return (generic_tostruct_in_svcb(CALL_TOSTRUCT)); +} + +static void +generic_freestruct_in_svcb(ARGS_FREESTRUCT) { + dns_rdata_in_svcb_t *svcb = source; + + REQUIRE(svcb != NULL); + + if (svcb->mctx == NULL) { + return; + } + + dns_name_free(&svcb->svcdomain, svcb->mctx); + isc_mem_free(svcb->mctx, svcb->svc); + svcb->mctx = NULL; +} + +static void +freestruct_in_svcb(ARGS_FREESTRUCT) { + dns_rdata_in_svcb_t *svcb = source; + + REQUIRE(svcb != NULL); + REQUIRE(svcb->common.rdclass == dns_rdataclass_in); + REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb); + + generic_freestruct_in_svcb(CALL_FREESTRUCT); +} + +static isc_result_t +generic_additionaldata_in_svcb(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +additionaldata_in_svcb(ARGS_ADDLDATA) { + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + return (generic_additionaldata_in_svcb(CALL_ADDLDATA)); +} + +static isc_result_t +digest_in_svcb(ARGS_DIGEST) { + isc_region_t region1; + + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + dns_rdata_toregion(rdata, ®ion1); + return ((digest)(arg, ®ion1)); +} + +static bool +checkowner_in_svcb(ARGS_CHECKOWNER) { + REQUIRE(type == dns_rdatatype_svcb); + REQUIRE(rdclass == dns_rdataclass_in); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (true); +} + +static bool +generic_checknames_in_svcb(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + bool alias; + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + INSIST(region.length > 1); + alias = uint16_fromregion(®ion) == 0; + isc_region_consume(®ion, 2); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + if (!alias && !dns_name_ishostname(&name, false)) { + if (bad != NULL) { + dns_name_clone(&name, bad); + } + return (false); + } + return (true); +} + +static bool +checknames_in_svcb(ARGS_CHECKNAMES) { + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + + return (generic_checknames_in_svcb(CALL_CHECKNAMES)); +} + +static int +casecompare_in_svcb(ARGS_COMPARE) { + return (compare_in_svcb(rdata1, rdata2)); +} + +static isc_result_t +generic_rdata_in_svcb_first(dns_rdata_in_svcb_t *svcb) { + if (svcb->svclen == 0) { + return (ISC_R_NOMORE); + } + svcb->offset = 0; + return (ISC_R_SUCCESS); +} + +static isc_result_t +generic_rdata_in_svcb_next(dns_rdata_in_svcb_t *svcb) { + isc_region_t region; + size_t len; + + if (svcb->offset >= svcb->svclen) { + return (ISC_R_NOMORE); + } + + region.base = svcb->svc + svcb->offset; + region.length = svcb->svclen - svcb->offset; + INSIST(region.length >= 4); + isc_region_consume(®ion, 2); + len = uint16_fromregion(®ion); + INSIST(region.length >= len + 2); + svcb->offset += len + 4; + return (svcb->offset >= svcb->svclen ? ISC_R_NOMORE : ISC_R_SUCCESS); +} + +static void +generic_rdata_in_svcb_current(dns_rdata_in_svcb_t *svcb, isc_region_t *region) { + size_t len; + + INSIST(svcb->offset <= svcb->svclen); + + region->base = svcb->svc + svcb->offset; + region->length = svcb->svclen - svcb->offset; + INSIST(region->length >= 4); + isc_region_consume(region, 2); + len = uint16_fromregion(region); + INSIST(region->length >= len + 2); + region->base = svcb->svc + svcb->offset; + region->length = len + 4; +} + +isc_result_t +dns_rdata_in_svcb_first(dns_rdata_in_svcb_t *svcb) { + REQUIRE(svcb != NULL); + REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb); + REQUIRE(svcb->common.rdclass == dns_rdataclass_in); + + return (generic_rdata_in_svcb_first(svcb)); +} + +isc_result_t +dns_rdata_in_svcb_next(dns_rdata_in_svcb_t *svcb) { + REQUIRE(svcb != NULL); + REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb); + REQUIRE(svcb->common.rdclass == dns_rdataclass_in); + + return (generic_rdata_in_svcb_next(svcb)); +} + +void +dns_rdata_in_svcb_current(dns_rdata_in_svcb_t *svcb, isc_region_t *region) { + REQUIRE(svcb != NULL); + REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb); + REQUIRE(svcb->common.rdclass == dns_rdataclass_in); + REQUIRE(region != NULL); + + generic_rdata_in_svcb_current(svcb, region); +} + +#endif /* RDATA_IN_1_SVCB_64_C */ diff --git a/lib/dns/rdata/in_1/svcb_64.h b/lib/dns/rdata/in_1/svcb_64.h new file mode 100644 index 0000000..e4ddc64 --- /dev/null +++ b/lib/dns/rdata/in_1/svcb_64.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef IN_1_SVCB_64_H +#define IN_1_SVCB_64_H 1 + +/*! + * \brief Per draft-ietf-dnsop-svcb-https-02 + */ + +typedef struct dns_rdata_in_svcb { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t priority; + dns_name_t svcdomain; + unsigned char *svc; + uint16_t svclen; + uint16_t offset; +} dns_rdata_in_svcb_t; + +isc_result_t +dns_rdata_in_svcb_first(dns_rdata_in_svcb_t *); + +isc_result_t +dns_rdata_in_svcb_next(dns_rdata_in_svcb_t *); + +void +dns_rdata_in_svcb_current(dns_rdata_in_svcb_t *, isc_region_t *); + +#endif /* IN_1_SVCB_64_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..bf9f830 --- /dev/null +++ b/lib/dns/rdata/in_1/wks_11.c @@ -0,0 +1,440 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 /* ifndef CHECK */ + +#define RRTYPE_WKS_ATTRIBUTES (0) + +static isc_mutex_t wks_lock; + +static void +init_lock(void) { + isc_mutex_init(&wks_lock); +} + +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 /* ifdef _WIN32 */ + +static 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 = NULL; + 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); + UNUSED(callbacks); + + 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 /* ifdef _WIN32 */ + + /* + * IPv4 dotted quad. + */ + CHECK(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + isc_buffer_availableregion(target, ®ion); + if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 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' && !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. + */ + strlcpy(service, DNS_AS_STR(token), sizeof(service)); + 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 && !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 /* ifdef _WIN32 */ + + return (result); +} + +static 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, tctx->flags, &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 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 (sr.length > 5 && sr.base[sr.length - 1] == 0) { + return (DNS_R_FORMERR); + } + 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 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 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 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(wks != 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 isc_result_t +tostruct_in_wks(ARGS_TOSTRUCT) { + dns_rdata_in_wks_t *wks = target; + uint32_t n; + isc_region_t region; + + REQUIRE(wks != NULL); + 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 void +freestruct_in_wks(ARGS_FREESTRUCT) { + dns_rdata_in_wks_t *wks = source; + + REQUIRE(wks != 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 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 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 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 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 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..9a926b1 --- /dev/null +++ b/lib/dns/rdata/in_1/wks_11.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://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 */ |