]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_8] CDS/CDNSKEY rrtypes
authorEvan Hunt <each@isc.org>
Thu, 19 Jun 2014 07:37:58 +0000 (00:37 -0700)
committerEvan Hunt <each@isc.org>
Thu, 19 Jun 2014 07:55:21 +0000 (00:55 -0700)
3884. [protocol] Add CDS and CDNSKEY record types. [RT #36333]

(cherry picked from commit cac2181160bdb3ccc89e3560addae5e38d4c05e3)
(cherry picked from commit 716453f37d7d51dcf69c95dac145785258a8087f)
(cherry picked from commit cfaac70c0aac0d5a3d62c41fb5911cdca66caf31)

CHANGES
bin/tests/system/genzone.sh
bin/tests/system/masterformat/ns1/example.db
bin/tests/system/masterformat/tests.sh
bin/tests/system/xfer/dig1.good
bin/tests/system/xfer/dig2.good
lib/dns/rdata/generic/cdnskey_60.c [new file with mode: 0644]
lib/dns/rdata/generic/cdnskey_60.h [new file with mode: 0644]
lib/dns/rdata/generic/cds_59.c [new file with mode: 0644]
lib/dns/rdata/generic/cds_59.h [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 36f118f56d9fb32844622106c004c03cbc5b450f..95dcdfe88cd1dca3d4a8d604658ee5334c63b588 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+3884.  [protocol]      Add CDS and CDNSKEY record types. [RT #36333]
+
 3881.  [bug]           Address memory leak with UPDATE error handling.
                        [RT #36303]
 
index 651659bf8cceb1ee97b7bd02860051aefa5b8aff..7c6cdfa17b538ee1271443b6515cf43b205d7487 100644 (file)
@@ -236,6 +236,17 @@ dnskey01           DNSKEY  512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
                                sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
                                a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
 
+; type 59
+cds01                  CDS     30795 1 1 (
+                                       310D27F4D82C1FC2400704EA9939FE6E1CEA
+                                       A3B9 )
+
+; type 60
+cdnskey01              CDNSKEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+                               9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+                               sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+                               a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
 ; type 249
 ; TKEY is a meta-type and should never occur in master files.
 ; The text representation is not specified in the draft.
index c21670685853cd8076445281165d505e94e7539e..1d7043ec7646d808c043bb616cd9a59aa46012f6 100644 (file)
@@ -45,6 +45,15 @@ dnskey                       300     DNSKEY  256 3 1 (
 ds                     300     DS      30795 1 1 (
                                        310D27F4D82C1FC2400704EA9939FE6E1CEA
                                        A3B9 )
+cdnskey                        300     CDNSKEY 256 3 1 (
+                                       AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg
+                                       +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD
+                                       Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R
+                                       b9VIE5x7KNHAYTvTO5d4S8M=
+                                       )
+cds                    300     CDS     30795 1 1 (
+                                       310D27F4D82C1FC2400704EA9939FE6E1CEA
+                                       A3B9 )
 nsec                   600     NSEC    nsecnext NS DS RRSIG NSEC
 rrsig                  300     RRSIG   SOA 1 0 300 20050714214747 (
                                        20050614214747 30795 .
index 7899a04e80dc57c55385c0202c900c7e1b9cadaa..975421a90865110f089ca3f4db1b0f7ba6251932 100755 (executable)
@@ -25,8 +25,8 @@ echo "I:checking that master file in the raw format worked"
 
 for server in 1 2
 do
-       for name in ns mx a aaaa cname dname txt rrsig nsec dnskey ds
-       do
+       for name in ns mx a aaaa cname dname txt rrsig nsec \
+                   dnskey ds cdnskey cds; do
                $DIG $DIGOPTS $name.example. $name @10.53.0.$server -p 5300
                echo
        done > dig.out.$server
index b10153ea3884356479574761acbcb26e671d4043..abf6e10649e671f001fccb09555b3bc07b43c13c 100644 (file)
@@ -9,6 +9,8 @@ a601.example.           3600    IN      A6      127 ::1 foo.
 a601.example.          3600    IN      A6      128  .
 afsdb01.example.       3600    IN      AFSDB   0 hostname.example.
 afsdb02.example.       3600    IN      AFSDB   65535 .
+cdnskey01.example.     3600    IN      CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example.         3600    IN      CDS     30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
 cert01.example.                3600    IN      CERT    65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
 cname01.example.       3600    IN      CNAME   cname-target.
 cname02.example.       3600    IN      CNAME   cname-target.example.
index 8b63816968df8a0db8b7c735b0ab3116333f71d7..9dd775b67a3c765ddc0d7b0ad18ce3724871934c 100644 (file)
@@ -9,6 +9,8 @@ a601.example.           3600    IN      A6      127 ::1 foo.
 a601.example.          3600    IN      A6      128  .
 afsdb01.example.       3600    IN      AFSDB   0 hostname.example.
 afsdb02.example.       3600    IN      AFSDB   65535 .
+cdnskey01.example.     3600    IN      CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example.         3600    IN      CDS     30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
 cert01.example.                3600    IN      CERT    65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
 cname01.example.       3600    IN      CNAME   cname-target.
 cname02.example.       3600    IN      CNAME   cname-target.example.
diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c
new file mode 100644 (file)
index 0000000..e9339b4
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009, 2012, 2013  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*
+ * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_CDNSKEY_60_C
+#define RDATA_GENERIC_CDNSKEY_60_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_CDNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_cdnskey(ARGS_FROMTEXT) {
+       isc_result_t result;
+       isc_token_t token;
+       dns_secalg_t alg;
+       dns_secproto_t proto;
+       dns_keyflags_t flags;
+
+       REQUIRE(type == 60);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(origin);
+       UNUSED(options);
+       UNUSED(callbacks);
+
+       /* flags */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+       RETERR(uint16_tobuffer(flags, target));
+
+       /* protocol */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &proto, 1));
+
+       /* algorithm */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &alg, 1));
+
+       /* No Key? */
+       if ((flags & 0xc000) == 0xc000)
+               return (ISC_R_SUCCESS);
+
+       result = isc_base64_tobuffer(lexer, target, -1);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       /* Ensure there's at least enough data to compute a key ID for MD5 */
+       if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7)
+               return (ISC_R_UNEXPECTEDEND);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_cdnskey(ARGS_TOTEXT) {
+       isc_region_t sr;
+       char buf[sizeof("64000")];
+       unsigned int flags;
+       unsigned char algorithm;
+       char namebuf[DNS_NAME_FORMATSIZE];
+
+       REQUIRE(rdata->type == 60);
+       REQUIRE(rdata->length != 0);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /* flags */
+       flags = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+       sprintf(buf, "%u", flags);
+       RETERR(str_totext(buf, target));
+       RETERR(str_totext(" ", target));
+
+       /* protocol */
+       sprintf(buf, "%u", sr.base[0]);
+       isc_region_consume(&sr, 1);
+       RETERR(str_totext(buf, target));
+       RETERR(str_totext(" ", target));
+
+       /* algorithm */
+       algorithm = sr.base[0];
+       sprintf(buf, "%u", algorithm);
+       isc_region_consume(&sr, 1);
+       RETERR(str_totext(buf, target));
+
+       /* No Key? */
+       if ((flags & 0xc000) == 0xc000)
+               return (ISC_R_SUCCESS);
+
+       if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 &&
+            algorithm == DNS_KEYALG_PRIVATEDNS) {
+               dns_name_t name;
+               dns_name_init(&name, NULL);
+               dns_name_fromregion(&name, &sr);
+               dns_name_format(&name, namebuf, sizeof(namebuf));
+       } else
+               namebuf[0] = 0;
+
+       /* key */
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" (", target));
+       RETERR(str_totext(tctx->linebreak, target));
+       RETERR(isc_base64_totext(&sr, tctx->width - 2,
+                                tctx->linebreak, target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0)
+               RETERR(str_totext(tctx->linebreak, target));
+       else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" ", target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(")", target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) {
+               isc_region_t tmpr;
+
+               RETERR(str_totext(" ; key id = ", target));
+               dns_rdata_toregion(rdata, &tmpr);
+               sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+               RETERR(str_totext(buf, target));
+               if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+                       RETERR(str_totext(tctx->linebreak, target));
+                       RETERR(str_totext("; alg = ", target));
+                       RETERR(str_totext(namebuf, target));
+               }
+       }
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_cdnskey(ARGS_FROMWIRE) {
+       unsigned char algorithm;
+       isc_region_t sr;
+
+       REQUIRE(type == 60);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(dctx);
+       UNUSED(options);
+
+       isc_buffer_activeregion(source, &sr);
+       if (sr.length < 4)
+               return (ISC_R_UNEXPECTEDEND);
+
+       algorithm = sr.base[3];
+       RETERR(mem_tobuffer(target, sr.base, 4));
+       isc_region_consume(&sr, 4);
+       isc_buffer_forward(source, 4);
+
+       if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+               dns_name_t name;
+               dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+               dns_name_init(&name, NULL);
+               RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+       }
+
+       /*
+        * RSAMD5 computes key ID differently from other
+        * algorithms: we need to ensure there's enough data
+        * present for the computation
+        */
+       if (algorithm == DST_ALG_RSAMD5 && sr.length < 3)
+               return (ISC_R_UNEXPECTEDEND);
+
+       isc_buffer_activeregion(source, &sr);
+       isc_buffer_forward(source, sr.length);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cdnskey(ARGS_TOWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 60);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(cctx);
+
+       dns_rdata_toregion(rdata, &sr);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cdnskey(ARGS_COMPARE) {
+       isc_region_t r1;
+       isc_region_t r2;
+
+       REQUIRE(rdata1->type == rdata2->type);
+       REQUIRE(rdata1->rdclass == rdata2->rdclass);
+       REQUIRE(rdata1->type == 60);
+       REQUIRE(rdata1->length != 0);
+       REQUIRE(rdata2->length != 0);
+
+       dns_rdata_toregion(rdata1, &r1);
+       dns_rdata_toregion(rdata2, &r2);
+       return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_cdnskey(ARGS_FROMSTRUCT) {
+       dns_rdata_cdnskey_t *dnskey = source;
+
+       REQUIRE(type == 60);
+       REQUIRE(source != NULL);
+       REQUIRE(dnskey->common.rdtype == type);
+       REQUIRE(dnskey->common.rdclass == rdclass);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+
+       /* Flags */
+       RETERR(uint16_tobuffer(dnskey->flags, target));
+
+       /* Protocol */
+       RETERR(uint8_tobuffer(dnskey->protocol, target));
+
+       /* Algorithm */
+       RETERR(uint8_tobuffer(dnskey->algorithm, target));
+
+       /* Data */
+       return (mem_tobuffer(target, dnskey->data, dnskey->datalen));
+}
+
+static inline isc_result_t
+tostruct_cdnskey(ARGS_TOSTRUCT) {
+       dns_rdata_cdnskey_t *dnskey = target;
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 60);
+       REQUIRE(target != NULL);
+       REQUIRE(rdata->length != 0);
+
+       dnskey->common.rdclass = rdata->rdclass;
+       dnskey->common.rdtype = rdata->type;
+       ISC_LINK_INIT(&dnskey->common, link);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /* Flags */
+       if (sr.length < 2)
+               return (ISC_R_UNEXPECTEDEND);
+       dnskey->flags = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+
+       /* Protocol */
+       if (sr.length < 1)
+               return (ISC_R_UNEXPECTEDEND);
+       dnskey->protocol = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+
+       /* Algorithm */
+       if (sr.length < 1)
+               return (ISC_R_UNEXPECTEDEND);
+       dnskey->algorithm = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+
+       /* Data */
+       dnskey->datalen = sr.length;
+       dnskey->data = mem_maybedup(mctx, sr.base, dnskey->datalen);
+       if (dnskey->data == NULL)
+               return (ISC_R_NOMEMORY);
+
+       dnskey->mctx = mctx;
+       return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cdnskey(ARGS_FREESTRUCT) {
+       dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *) source;
+
+       REQUIRE(source != NULL);
+       REQUIRE(dnskey->common.rdtype == 60);
+
+       if (dnskey->mctx == NULL)
+               return;
+
+       if (dnskey->data != NULL)
+               isc_mem_free(dnskey->mctx, dnskey->data);
+       dnskey->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cdnskey(ARGS_ADDLDATA) {
+       REQUIRE(rdata->type == 60);
+
+       UNUSED(rdata);
+       UNUSED(add);
+       UNUSED(arg);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cdnskey(ARGS_DIGEST) {
+       isc_region_t r;
+
+       REQUIRE(rdata->type == 60);
+
+       dns_rdata_toregion(rdata, &r);
+
+       return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cdnskey(ARGS_CHECKOWNER) {
+
+       REQUIRE(type == 60);
+
+       UNUSED(name);
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(wildcard);
+
+       return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cdnskey(ARGS_CHECKNAMES) {
+
+       REQUIRE(rdata->type == 60);
+
+       UNUSED(rdata);
+       UNUSED(owner);
+       UNUSED(bad);
+
+       return (ISC_TRUE);
+}
+
+static inline int
+casecompare_cdnskey(ARGS_COMPARE) {
+
+       /*
+        * Treat ALG 253 (private DNS) subtype name case sensistively.
+        */
+       return (compare_cdnskey(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDNSKEY_60_C */
diff --git a/lib/dns/rdata/generic/cdnskey_60.h b/lib/dns/rdata/generic/cdnskey_60.h
new file mode 100644 (file)
index 0000000..692abb5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef GENERIC_CDNSKEY_60_H
+#define GENERIC_CDNSKEY_60_H 1
+
+/* CDNSKEY records have the same RDATA fields as DNSKEY records. */
+typedef struct dns_rdata_cdnskey {
+        dns_rdatacommon_t      common;
+        isc_mem_t *            mctx;
+        isc_uint16_t           flags;
+        isc_uint8_t            protocol;
+        isc_uint8_t            algorithm;
+        isc_uint16_t           datalen;
+        unsigned char *                data;
+} dns_rdata_cdnskey_t;
+
+
+#endif /* GENERIC_CDNSKEY_60_H */
diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c
new file mode 100644 (file)
index 0000000..061942f
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2012  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* draft-ietf-dnsext-delegation-signer-05.txt */
+
+#ifndef RDATA_GENERIC_CDS_59_C
+#define RDATA_GENERIC_CDS_59_C
+
+#define RRTYPE_CDS_ATTRIBUTES \
+       (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT)
+
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+
+#include <dns/ds.h>
+
+static inline isc_result_t
+fromtext_cds(ARGS_FROMTEXT) {
+       isc_token_t token;
+       unsigned char c;
+       int length;
+
+       REQUIRE(type == 59);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(origin);
+       UNUSED(options);
+       UNUSED(callbacks);
+
+       /*
+        * Key tag.
+        */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+                                     ISC_FALSE));
+       if (token.value.as_ulong > 0xffffU)
+               RETTOK(ISC_R_RANGE);
+       RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+       /*
+        * Algorithm.
+        */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &c, 1));
+
+       /*
+        * Digest type.
+        */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+                                     ISC_FALSE));
+       if (token.value.as_ulong > 0xffU)
+               RETTOK(ISC_R_RANGE);
+       RETERR(uint8_tobuffer(token.value.as_ulong, target));
+       c = (unsigned char) token.value.as_ulong;
+
+       /*
+        * Digest.
+        */
+       switch (c) {
+       case DNS_DSDIGEST_SHA1:
+               length = ISC_SHA1_DIGESTLENGTH;
+               break;
+       case DNS_DSDIGEST_SHA256:
+               length = ISC_SHA256_DIGESTLENGTH;
+               break;
+       case DNS_DSDIGEST_GOST:
+               length = ISC_GOST_DIGESTLENGTH;
+               break;
+       case DNS_DSDIGEST_SHA384:
+               length = ISC_SHA384_DIGESTLENGTH;
+               break;
+       default:
+               length = -1;
+               break;
+       }
+       return (isc_hex_tobuffer(lexer, target, length));
+}
+
+static inline isc_result_t
+totext_cds(ARGS_TOTEXT) {
+       isc_region_t sr;
+       char buf[sizeof("64000 ")];
+       unsigned int n;
+
+       REQUIRE(rdata->type == 59);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(tctx);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /*
+        * Key tag.
+        */
+       n = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+       sprintf(buf, "%u ", n);
+       RETERR(str_totext(buf, target));
+
+       /*
+        * Algorithm.
+        */
+       n = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+       sprintf(buf, "%u ", n);
+       RETERR(str_totext(buf, target));
+
+       /*
+        * Digest type.
+        */
+       n = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+       sprintf(buf, "%u", n);
+       RETERR(str_totext(buf, target));
+
+       /*
+        * Digest.
+        */
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" (", target));
+       RETERR(str_totext(tctx->linebreak, target));
+       RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target));
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" )", target));
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_cds(ARGS_FROMWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(type == 59);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(dctx);
+       UNUSED(options);
+
+       isc_buffer_activeregion(source, &sr);
+
+       /*
+        * Check digest lengths if we know them.
+        */
+       if (sr.length < 4 ||
+           (sr.base[3] == DNS_DSDIGEST_SHA1 &&
+            sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+           (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+            sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
+           (sr.base[3] == DNS_DSDIGEST_GOST &&
+            sr.length < 4 + ISC_GOST_DIGESTLENGTH) ||
+           (sr.base[3] == DNS_DSDIGEST_SHA384 &&
+            sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
+               return (ISC_R_UNEXPECTEDEND);
+
+       /*
+        * Only copy digest lengths if we know them.
+        * If there is extra data dns_rdata_fromwire() will
+        * detect that.
+        */
+       if (sr.base[3] == DNS_DSDIGEST_SHA1)
+               sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+       else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+               sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+       else if (sr.base[3] == DNS_DSDIGEST_GOST)
+               sr.length = 4 + ISC_GOST_DIGESTLENGTH;
+       else if (sr.base[3] == DNS_DSDIGEST_SHA384)
+               sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
+
+       isc_buffer_forward(source, sr.length);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cds(ARGS_TOWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 59);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(cctx);
+
+       dns_rdata_toregion(rdata, &sr);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cds(ARGS_COMPARE) {
+       isc_region_t r1;
+       isc_region_t r2;
+
+       REQUIRE(rdata1->type == rdata2->type);
+       REQUIRE(rdata1->rdclass == rdata2->rdclass);
+       REQUIRE(rdata1->type == 59);
+       REQUIRE(rdata1->length != 0);
+       REQUIRE(rdata2->length != 0);
+
+       dns_rdata_toregion(rdata1, &r1);
+       dns_rdata_toregion(rdata2, &r2);
+       return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_cds(ARGS_FROMSTRUCT) {
+       dns_rdata_cds_t *ds = source;
+
+       REQUIRE(type == 59);
+       REQUIRE(source != NULL);
+       REQUIRE(ds->common.rdtype == type);
+       REQUIRE(ds->common.rdclass == rdclass);
+       switch (ds->digest_type) {
+       case DNS_DSDIGEST_SHA1:
+               REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
+               break;
+       case DNS_DSDIGEST_SHA256:
+               REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
+               break;
+       case DNS_DSDIGEST_GOST:
+               REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH);
+               break;
+       case DNS_DSDIGEST_SHA384:
+               REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
+               break;
+       }
+
+       UNUSED(type);
+       UNUSED(rdclass);
+
+       RETERR(uint16_tobuffer(ds->key_tag, target));
+       RETERR(uint8_tobuffer(ds->algorithm, target));
+       RETERR(uint8_tobuffer(ds->digest_type, target));
+
+       return (mem_tobuffer(target, ds->digest, ds->length));
+}
+
+static inline isc_result_t
+tostruct_cds(ARGS_TOSTRUCT) {
+       dns_rdata_cds_t *ds = target;
+       isc_region_t region;
+
+       REQUIRE(rdata->type == 59);
+       REQUIRE(target != NULL);
+       REQUIRE(rdata->length != 0);
+
+       ds->common.rdclass = rdata->rdclass;
+       ds->common.rdtype = rdata->type;
+       ISC_LINK_INIT(&ds->common, link);
+
+       dns_rdata_toregion(rdata, &region);
+
+       ds->key_tag = uint16_fromregion(&region);
+       isc_region_consume(&region, 2);
+       ds->algorithm = uint8_fromregion(&region);
+       isc_region_consume(&region, 1);
+       ds->digest_type = uint8_fromregion(&region);
+       isc_region_consume(&region, 1);
+       ds->length = region.length;
+
+       ds->digest = mem_maybedup(mctx, region.base, region.length);
+       if (ds->digest == NULL)
+               return (ISC_R_NOMEMORY);
+
+       ds->mctx = mctx;
+       return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cds(ARGS_FREESTRUCT) {
+       dns_rdata_cds_t *ds = source;
+
+       REQUIRE(ds != NULL);
+       REQUIRE(ds->common.rdtype == 59);
+
+       if (ds->mctx == NULL)
+               return;
+
+       if (ds->digest != NULL)
+               isc_mem_free(ds->mctx, ds->digest);
+       ds->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cds(ARGS_ADDLDATA) {
+       REQUIRE(rdata->type == 59);
+
+       UNUSED(rdata);
+       UNUSED(add);
+       UNUSED(arg);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cds(ARGS_DIGEST) {
+       isc_region_t r;
+
+       REQUIRE(rdata->type == 59);
+
+       dns_rdata_toregion(rdata, &r);
+
+       return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cds(ARGS_CHECKOWNER) {
+
+       REQUIRE(type == 59);
+
+       UNUSED(name);
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(wildcard);
+
+       return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cds(ARGS_CHECKNAMES) {
+
+       REQUIRE(rdata->type == 59);
+
+       UNUSED(rdata);
+       UNUSED(owner);
+       UNUSED(bad);
+
+       return (ISC_TRUE);
+}
+
+static inline int
+casecompare_cds(ARGS_COMPARE) {
+       return (compare_cds(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDS_59_C */
diff --git a/lib/dns/rdata/generic/cds_59.h b/lib/dns/rdata/generic/cds_59.h
new file mode 100644 (file)
index 0000000..08d82c3
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef GENERIC_CDS_59_H
+#define GENERIC_CDS_59_H 1
+
+/* CDS records have the same RDATA fields as DS records. */
+typedef struct dns_rdata_cds {
+       dns_rdatacommon_t       common;
+       isc_mem_t               *mctx;
+       isc_uint16_t            key_tag;
+       isc_uint8_t             algorithm;
+       isc_uint8_t             digest_type;
+       isc_uint16_t            length;
+       unsigned char           *digest;
+} dns_rdata_cds_t;
+
+#endif /* GENERIC_CDS_59_H */